diff -urN linux-2.4.0-test10/Documentation/Configure.help linux-2.4.0-test10-lia/Documentation/Configure.help --- linux-2.4.0-test10/Documentation/Configure.help Mon Oct 30 14:46:05 2000 +++ linux-2.4.0-test10-lia/Documentation/Configure.help Wed Nov 1 23:05:34 2000 @@ -11365,6 +11365,12 @@ Say Y here if you would like to be able to read the hard disk partition table format used by SGI machines. +Intel EFI GUID partition support +CONFIG_EFI_PARTITION + Say Y here if you would like to use hard disks under Linux which + were partitioned using EFI GPT. Presently only useful on the + IA-64 platform. + ADFS file system support (EXPERIMENTAL) CONFIG_ADFS_FS The Acorn Disc Filing System is the standard file system of the diff -urN linux-2.4.0-test10/Documentation/DMA-mapping.txt linux-2.4.0-test10-lia/Documentation/DMA-mapping.txt --- linux-2.4.0-test10/Documentation/DMA-mapping.txt Thu Sep 7 08:31:59 2000 +++ linux-2.4.0-test10-lia/Documentation/DMA-mapping.txt Fri Sep 8 14:34:52 2000 @@ -341,7 +341,7 @@ struct my_card_header *hp; /* Examine the header to see if we wish - * to except the data. But synchronize + * to accept the data. But synchronize * the DMA transfer with the CPU first * so that we see updated contents. */ diff -urN linux-2.4.0-test10/Makefile linux-2.4.0-test10-lia/Makefile --- linux-2.4.0-test10/Makefile Fri Oct 27 10:55:48 2000 +++ linux-2.4.0-test10-lia/Makefile Thu Nov 2 00:23:09 2000 @@ -87,7 +87,7 @@ CPPFLAGS := -D__KERNEL__ -I$(HPATH) -CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing +CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -g -O2 -fomit-frame-pointer -fno-strict-aliasing AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS) # @@ -182,14 +182,14 @@ include arch/$(ARCH)/Makefile -export CPPFLAGS CFLAGS AFLAGS +export CPPFLAGS CFLAGS CFLAGS_KERNEL AFLAGS AFLAGS_KERNEL export NETWORKS DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS .S.s: - $(CPP) $(AFLAGS) -traditional -o $*.s $< + $(CPP) $(AFLAGS) $(AFLAGS_KERNEL) -traditional -o $*.s $< .S.o: - $(CC) $(AFLAGS) -traditional -c -o $*.o $< + $(CC) $(AFLAGS) $(AFLAGS_KERNEL) -traditional -c -o $*.o $< Version: dummy @rm -f include/linux/compile.h @@ -206,7 +206,7 @@ $(LIBS) \ --end-group \ -o vmlinux - $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aU] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map + $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map symlinks: rm -f include/asm diff -urN linux-2.4.0-test10/arch/ia64/config.in linux-2.4.0-test10-lia/arch/ia64/config.in --- linux-2.4.0-test10/arch/ia64/config.in Mon Oct 9 17:54:53 2000 +++ linux-2.4.0-test10-lia/arch/ia64/config.in Wed Nov 15 17:52:03 2000 @@ -45,14 +45,18 @@ bool ' Enable Itanium B-step specific code' CONFIG_ITANIUM_BSTEP_SPECIFIC if [ "$CONFIG_ITANIUM_BSTEP_SPECIFIC" = "y" ]; then bool ' Enable Itanium B0-step specific code' CONFIG_ITANIUM_B0_SPECIFIC + bool ' Enable Itanium B1-step specific code' CONFIG_ITANIUM_B1_SPECIFIC + bool ' Enable Itanium B2-step specific code' CONFIG_ITANIUM_B2_SPECIFIC + fi + bool ' Enable Itanium C-step specific code' CONFIG_ITANIUM_CSTEP_SPECIFIC + if [ "$CONFIG_ITANIUM_CSTEP_SPECIFIC" = "y" ]; then + bool ' Enable Itanium C0-step specific code' CONFIG_ITANIUM_C0_SPECIFIC fi bool ' Force interrupt redirection' CONFIG_IA64_HAVE_IRQREDIR bool ' Enable use of global TLB purge instruction (ptc.g)' CONFIG_ITANIUM_PTCG bool ' Enable SoftSDV hacks' CONFIG_IA64_SOFTSDV_HACKS bool ' Enable AzusA hacks' CONFIG_IA64_AZUSA_HACKS bool ' Enable IA-64 Machine Check Abort' CONFIG_IA64_MCA - bool ' Force socket buffers below 4GB?' CONFIG_SKB_BELOW_4GB - bool ' ACPI kernel configuration manager (EXPERIMENTAL)' CONFIG_ACPI_KERNEL_CONFIG if [ "$CONFIG_ACPI_KERNEL_CONFIG" = "y" ]; then define_bool CONFIG_PM y diff -urN linux-2.4.0-test10/arch/ia64/dig/Makefile linux-2.4.0-test10-lia/arch/ia64/dig/Makefile --- linux-2.4.0-test10/arch/ia64/dig/Makefile Fri Apr 21 15:21:23 2000 +++ linux-2.4.0-test10-lia/arch/ia64/dig/Makefile Tue Oct 31 10:13:32 2000 @@ -13,7 +13,7 @@ all: dig.a O_TARGET = dig.a -O_OBJS = iosapic.o setup.o +O_OBJS = setup.o ifdef CONFIG_IA64_GENERIC O_OBJS += machvec.o diff -urN linux-2.4.0-test10/arch/ia64/dig/iosapic.c linux-2.4.0-test10-lia/arch/ia64/dig/iosapic.c --- linux-2.4.0-test10/arch/ia64/dig/iosapic.c Mon Oct 9 17:54:53 2000 +++ linux-2.4.0-test10-lia/arch/ia64/dig/iosapic.c Wed Dec 31 16:00:00 1969 @@ -1,409 +0,0 @@ -/* - * Streamlined APIC support. - * - * Copyright (C) 1999 Intel Corp. - * Copyright (C) 1999 Asit Mallick - * Copyright (C) 1999-2000 Hewlett-Packard Co. - * Copyright (C) 1999-2000 David Mosberger-Tang - * Copyright (C) 1999 VA Linux Systems - * Copyright (C) 1999,2000 Walt Drummond - * - * 00/04/19 D. Mosberger Rewritten to mirror more closely the x86 I/O APIC code. - * In particular, we now have separate handlers for edge - * and level triggered interrupts. - */ -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_ACPI_KERNEL_CONFIG -# include -#endif - -#undef DEBUG_IRQ_ROUTING - -static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED; - -struct iosapic_vector iosapic_vector[NR_IRQS] = { - [0 ... NR_IRQS-1] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } -}; - -/* - * find the IRQ in the IOSAPIC map for the PCI device on bus/slot/pin - */ -int -iosapic_get_PCI_irq_vector (int bus, int slot, int pci_pin) -{ - int i; - - for (i = 0; i < NR_IRQS; i++) { - if ((iosapic_bustype(i) == BUS_PCI) && - (iosapic_bus(i) == bus) && - (iosapic_busdata(i) == ((slot << 16) | pci_pin))) { - return i; - } - } - return -1; -} - -static void -set_rte (unsigned long iosapic_addr, int entry, int pol, int trigger, int delivery, - long dest, int vector) -{ - u32 low32; - u32 high32; - - low32 = ((pol << IO_SAPIC_POLARITY_SHIFT) | - (trigger << IO_SAPIC_TRIGGER_SHIFT) | - (delivery << IO_SAPIC_DELIVERY_SHIFT) | - vector); - -#ifdef CONFIG_IA64_AZUSA_HACKS - /* set Flush Disable bit */ - if (iosapic_addr != 0xc0000000fec00000) - low32 |= (1 << 17); -#endif - - /* dest contains both id and eid */ - high32 = (dest << IO_SAPIC_DEST_SHIFT); - - writel(IO_SAPIC_RTE_HIGH(entry), iosapic_addr + IO_SAPIC_REG_SELECT); - writel(high32, iosapic_addr + IO_SAPIC_WINDOW); - writel(IO_SAPIC_RTE_LOW(entry), iosapic_addr + IO_SAPIC_REG_SELECT); - writel(low32, iosapic_addr + IO_SAPIC_WINDOW); -} - -static void -nop (unsigned int irq) -{ - /* do nothing... */ -} - -static void -mask_irq (unsigned int irq) -{ - unsigned long flags, iosapic_addr = iosapic_addr(irq); - u32 low32; - - spin_lock_irqsave(&iosapic_lock, flags); - { - writel(IO_SAPIC_RTE_LOW(iosapic_pin(irq)), iosapic_addr + IO_SAPIC_REG_SELECT); - low32 = readl(iosapic_addr + IO_SAPIC_WINDOW); - - low32 |= (1 << IO_SAPIC_MASK_SHIFT); /* Zero only the mask bit */ - writel(low32, iosapic_addr + IO_SAPIC_WINDOW); - } - spin_unlock_irqrestore(&iosapic_lock, flags); -} - -static void -unmask_irq (unsigned int irq) -{ - unsigned long flags, iosapic_addr = iosapic_addr(irq); - u32 low32; - - spin_lock_irqsave(&iosapic_lock, flags); - { - writel(IO_SAPIC_RTE_LOW(iosapic_pin(irq)), iosapic_addr + IO_SAPIC_REG_SELECT); - low32 = readl(iosapic_addr + IO_SAPIC_WINDOW); - - low32 &= ~(1 << IO_SAPIC_MASK_SHIFT); /* Zero only the mask bit */ - writel(low32, iosapic_addr + IO_SAPIC_WINDOW); - } - spin_unlock_irqrestore(&iosapic_lock, flags); -} - - -static void -iosapic_set_affinity (unsigned int irq, unsigned long mask) -{ - printk("iosapic_set_affinity: not implemented yet\n"); -} - -/* - * Handlers for level-triggered interrupts. - */ - -static unsigned int -iosapic_startup_level_irq (unsigned int irq) -{ - unmask_irq(irq); - return 0; -} - -static void -iosapic_end_level_irq (unsigned int irq) -{ - writel(irq, iosapic_addr(irq) + IO_SAPIC_EOI); -} - -#define iosapic_shutdown_level_irq mask_irq -#define iosapic_enable_level_irq unmask_irq -#define iosapic_disable_level_irq mask_irq -#define iosapic_ack_level_irq nop - -struct hw_interrupt_type irq_type_iosapic_level = { - typename: "IO-SAPIC-level", - startup: iosapic_startup_level_irq, - shutdown: iosapic_shutdown_level_irq, - enable: iosapic_enable_level_irq, - disable: iosapic_disable_level_irq, - ack: iosapic_ack_level_irq, - end: iosapic_end_level_irq, - set_affinity: iosapic_set_affinity -}; - -/* - * Handlers for edge-triggered interrupts. - */ - -static unsigned int -iosapic_startup_edge_irq (unsigned int irq) -{ - unmask_irq(irq); - /* - * IOSAPIC simply drops interrupts pended while the - * corresponding pin was masked, so we can't know if an - * interrupt is pending already. Let's hope not... - */ - return 0; -} - -static void -iosapic_ack_edge_irq (unsigned int irq) -{ - /* - * Once we have recorded IRQ_PENDING already, we can mask the - * interrupt for real. This prevents IRQ storms from unhandled - * devices. - */ - if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED)) == (IRQ_PENDING | IRQ_DISABLED)) - mask_irq(irq); -} - -#define iosapic_enable_edge_irq unmask_irq -#define iosapic_disable_edge_irq nop -#define iosapic_end_edge_irq nop - -struct hw_interrupt_type irq_type_iosapic_edge = { - typename: "IO-SAPIC-edge", - startup: iosapic_startup_edge_irq, - shutdown: iosapic_disable_edge_irq, - enable: iosapic_enable_edge_irq, - disable: iosapic_disable_edge_irq, - ack: iosapic_ack_edge_irq, - end: iosapic_end_edge_irq, - set_affinity: iosapic_set_affinity -}; - -unsigned int -iosapic_version (unsigned long base_addr) -{ - /* - * IOSAPIC Version Register return 32 bit structure like: - * { - * unsigned int version : 8; - * unsigned int reserved1 : 8; - * unsigned int pins : 8; - * unsigned int reserved2 : 8; - * } - */ - writel(IO_SAPIC_VERSION, base_addr + IO_SAPIC_REG_SELECT); - return readl(IO_SAPIC_WINDOW + base_addr); -} - -void -iosapic_init (unsigned long address, int irqbase) -{ - struct hw_interrupt_type *irq_type; - struct pci_vector_struct *vectors; - int i, irq, num_pci_vectors; - - if (irqbase == 0) - /* - * Map the legacy ISA devices into the IOSAPIC data. - * Some of these may get reprogrammed later on with - * data from the ACPI Interrupt Source Override table. - */ - for (i = 0; i < 16; i++) { - irq = isa_irq_to_vector(i); - iosapic_pin(irq) = i; - iosapic_bus(irq) = BUS_ISA; - iosapic_busdata(irq) = 0; - iosapic_dmode(irq) = IO_SAPIC_LOWEST_PRIORITY; - iosapic_trigger(irq) = IO_SAPIC_EDGE; - iosapic_polarity(irq) = IO_SAPIC_POL_HIGH; -#ifdef DEBUG_IRQ_ROUTING - printk("ISA: IRQ %02x -> Vector %02x IOSAPIC Pin %d\n", - i, irq, iosapic_pin(irq)); -#endif - } - -#ifndef CONFIG_IA64_SOFTSDV_HACKS - /* - * Map the PCI Interrupt data into the ACPI IOSAPIC data using - * the info that the bootstrap loader passed to us. - */ -# ifdef CONFIG_ACPI_KERNEL_CONFIG - acpi_cf_get_pci_vectors(&vectors, &num_pci_vectors); -# else - ia64_boot_param.pci_vectors = (__u64) __va(ia64_boot_param.pci_vectors); - vectors = (struct pci_vector_struct *) ia64_boot_param.pci_vectors; - num_pci_vectors = ia64_boot_param.num_pci_vectors; -# endif - for (i = 0; i < num_pci_vectors; i++) { - irq = vectors[i].irq; - if (irq < 16) - irq = isa_irq_to_vector(irq); - if (iosapic_baseirq(irq) != irqbase) - continue; - - iosapic_bustype(irq) = BUS_PCI; - iosapic_pin(irq) = irq - iosapic_baseirq(irq); - iosapic_bus(irq) = vectors[i].bus; - /* - * Map the PCI slot and pin data into iosapic_busdata() - */ - iosapic_busdata(irq) = (vectors[i].pci_id & 0xffff0000) | vectors[i].pin; - - /* Default settings for PCI */ - iosapic_dmode(irq) = IO_SAPIC_LOWEST_PRIORITY; - iosapic_trigger(irq) = IO_SAPIC_LEVEL; - iosapic_polarity(irq) = IO_SAPIC_POL_LOW; - -# ifdef DEBUG_IRQ_ROUTING - printk("PCI: BUS %d Slot %x Pin %x IRQ %02x --> Vector %02x IOSAPIC Pin %d\n", - vectors[i].bus, vectors[i].pci_id>>16, vectors[i].pin, vectors[i].irq, - irq, iosapic_pin(irq)); -# endif - } -#endif /* CONFIG_IA64_SOFTSDV_HACKS */ - - for (i = 0; i < NR_IRQS; ++i) { - if (iosapic_baseirq(i) != irqbase) - continue; - - if (iosapic_pin(i) != -1) { - if (iosapic_trigger(i) == IO_SAPIC_LEVEL) - irq_type = &irq_type_iosapic_level; - else - irq_type = &irq_type_iosapic_edge; - if (irq_desc[i].handler != &no_irq_type) - printk("dig_irq_init: warning: changing vector %d from %s to %s\n", - i, irq_desc[i].handler->typename, - irq_type->typename); - irq_desc[i].handler = irq_type; - - /* program the IOSAPIC routing table: */ - set_rte(iosapic_addr(i), iosapic_pin(i), iosapic_polarity(i), - iosapic_trigger(i), iosapic_dmode(i), - (ia64_get_lid() >> 16) & 0xffff, i); - } - } -} - -void -dig_irq_init (void) -{ - /* - * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support - * enabled. - */ - outb(0xff, 0xA1); - outb(0xff, 0x21); -} - -void -dig_pci_fixup (void) -{ - struct pci_dev *dev; - int irq; - unsigned char pin; - - pci_for_each_dev(dev) { - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); - if (pin) { - pin--; /* interrupt pins are numbered starting from 1 */ - irq = iosapic_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), - pin); - if (irq < 0 && dev->bus->parent) { /* go back to the bridge */ - struct pci_dev * bridge = dev->bus->self; - - /* allow for multiple bridges on an adapter */ - do { - /* do the bridge swizzle... */ - pin = (pin + PCI_SLOT(dev->devfn)) % 4; - irq = iosapic_get_PCI_irq_vector(bridge->bus->number, - PCI_SLOT(bridge->devfn), pin); - } while (irq < 0 && (bridge = bridge->bus->self)); - if (irq >= 0) - printk(KERN_WARNING - "PCI: using PPB(B%d,I%d,P%d) to get irq %02x\n", - bridge->bus->number, PCI_SLOT(bridge->devfn), - pin, irq); - else - printk(KERN_WARNING - "PCI: Couldn't map irq for B%d,I%d,P%d\n", - bridge->bus->number, PCI_SLOT(bridge->devfn), - pin); - } - if (irq >= 0) { - printk("PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %02x\n", - dev->bus->number, PCI_SLOT(dev->devfn), pin, irq); - dev->irq = irq; - } - } - /* - * Nothing to fixup - * Fix out-of-range IRQ numbers - */ - if (dev->irq >= NR_IRQS) - dev->irq = 15; /* Spurious interrupts */ - } -} - -/* - * Register an IOSAPIC discovered via ACPI. - */ -void __init -dig_register_iosapic (acpi_entry_iosapic_t *iosapic) -{ - unsigned int ver, v; - int l, max_pin; - - ver = iosapic_version((unsigned long) ioremap(iosapic->address, 0)); - max_pin = (ver >> 16) & 0xff; - - printk("IOSAPIC Version %x.%x: address 0x%lx IRQs 0x%x - 0x%x\n", - (ver & 0xf0) >> 4, (ver & 0x0f), iosapic->address, - iosapic->irq_base, iosapic->irq_base + max_pin); - - for (l = 0; l <= max_pin; l++) { - v = iosapic->irq_base + l; - if (v < 16) - v = isa_irq_to_vector(v); - if (v > IA64_MAX_VECTORED_IRQ) { - printk(" !!! bad IOSAPIC interrupt vector: %u\n", v); - continue; - } - /* XXX Check for IOSAPIC collisions */ - iosapic_addr(v) = (unsigned long) ioremap(iosapic->address, 0); - iosapic_baseirq(v) = iosapic->irq_base; - } - iosapic_init(iosapic->address, iosapic->irq_base); -} diff -urN linux-2.4.0-test10/arch/ia64/dig/setup.c linux-2.4.0-test10-lia/arch/ia64/dig/setup.c --- linux-2.4.0-test10/arch/ia64/dig/setup.c Fri Aug 11 19:09:06 2000 +++ linux-2.4.0-test10-lia/arch/ia64/dig/setup.c Mon Oct 30 22:28:55 2000 @@ -84,3 +84,14 @@ screen_info.orig_video_isVGA = 1; /* XXX fake */ screen_info.orig_video_ega_bx = 3; /* XXX fake */ } + +void +dig_irq_init (void) +{ + /* + * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support + * enabled. + */ + outb(0xff, 0xA1); + outb(0xff, 0x21); +} diff -urN linux-2.4.0-test10/arch/ia64/ia32/binfmt_elf32.c linux-2.4.0-test10-lia/arch/ia64/ia32/binfmt_elf32.c --- linux-2.4.0-test10/arch/ia64/ia32/binfmt_elf32.c Mon Oct 9 17:54:53 2000 +++ linux-2.4.0-test10-lia/arch/ia64/ia32/binfmt_elf32.c Mon Oct 30 22:29:21 2000 @@ -9,6 +9,7 @@ #include +#include #include #include @@ -31,6 +32,9 @@ # define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE #endif +#undef CLOCKS_PER_SEC +#define CLOCKS_PER_SEC IA32_CLOCKS_PER_SEC + extern void ia64_elf32_init(struct pt_regs *regs); extern void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long address); @@ -239,6 +243,12 @@ if (eppnt->p_memsz >= (1UL<<32) || addr > (1UL<<32) - eppnt->p_memsz) return -EINVAL; + /* + * Make sure the elf interpreter doesn't get loaded at location 0 + * so that NULL pointers correctly cause segfaults. + */ + if (addr == 0) + addr += PAGE_SIZE; #if 1 set_brk(ia32_mm_addr(addr), addr + eppnt->p_memsz); memset((char *) addr + eppnt->p_filesz, 0, eppnt->p_memsz - eppnt->p_filesz); diff -urN linux-2.4.0-test10/arch/ia64/ia32/ia32_entry.S linux-2.4.0-test10-lia/arch/ia64/ia32/ia32_entry.S --- linux-2.4.0-test10/arch/ia64/ia32/ia32_entry.S Tue Sep 5 13:50:01 2000 +++ linux-2.4.0-test10-lia/arch/ia64/ia32/ia32_entry.S Mon Oct 30 22:29:33 2000 @@ -291,11 +291,43 @@ data8 sys_getcwd data8 sys_capget data8 sys_capset /* 185 */ - data8 sys_sigaltstack + data8 sys32_sigaltstack data8 sys_sendfile data8 sys32_ni_syscall /* streams1 */ data8 sys32_ni_syscall /* streams2 */ data8 sys32_vfork /* 190 */ + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall /* 195 */ + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall /* 200 */ + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall /* 205 */ + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall /* 210 */ + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall /* 215 */ + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall /* 220 */ + data8 sys_ni_syscall + data8 sys_ni_syscall /* * CAUTION: If any system calls are added beyond this point * then the check in `arch/ia64/kernel/ivt.S' will have diff -urN linux-2.4.0-test10/arch/ia64/ia32/ia32_ioctl.c linux-2.4.0-test10-lia/arch/ia64/ia32/ia32_ioctl.c --- linux-2.4.0-test10/arch/ia64/ia32/ia32_ioctl.c Fri Jul 14 16:08:11 2000 +++ linux-2.4.0-test10-lia/arch/ia64/ia32/ia32_ioctl.c Mon Oct 30 22:29:51 2000 @@ -22,81 +22,158 @@ #include #include #include +#include <../drivers/char/drm/drm.h> + +#define IOCTL_NR(a) ((a) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) + +#define DO_IOCTL(fd, cmd, arg) ({ \ + int _ret; \ + mm_segment_t _old_fs = get_fs(); \ + \ + set_fs(KERNEL_DS); \ + _ret = sys_ioctl(fd, cmd, (unsigned long)arg); \ + set_fs(_old_fs); \ + _ret; \ +}) + +#define P(i) ((void *)(long)(i)) + asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); asmlinkage long ia32_ioctl(unsigned int fd, unsigned int cmd, unsigned int arg) { + long ret; + + switch (IOCTL_NR(cmd)) { + + case IOCTL_NR(DRM_IOCTL_VERSION): + break; + case IOCTL_NR(DRM_IOCTL_GET_UNIQUE): + { + drm_unique_t un; + struct { + unsigned int unique_len; + unsigned int unique; + } un32; + + if (copy_from_user(&un32, P(arg), sizeof(un32))) + return -EFAULT; + un.unique_len = un32.unique_len; + un.unique = P(un32.unique); + ret = DO_IOCTL(fd, cmd, &un); + if (ret >= 0) { + un32.unique_len = un.unique_len; + if (copy_to_user(P(arg), &un32, sizeof(un32))) + return -EFAULT; + } + return(ret); + } + case IOCTL_NR(DRM_IOCTL_SET_UNIQUE): + case IOCTL_NR(DRM_IOCTL_ADD_MAP): + case IOCTL_NR(DRM_IOCTL_ADD_BUFS): + case IOCTL_NR(DRM_IOCTL_MARK_BUFS): + case IOCTL_NR(DRM_IOCTL_INFO_BUFS): + case IOCTL_NR(DRM_IOCTL_MAP_BUFS): + case IOCTL_NR(DRM_IOCTL_FREE_BUFS): + case IOCTL_NR(DRM_IOCTL_ADD_CTX): + case IOCTL_NR(DRM_IOCTL_RM_CTX): + case IOCTL_NR(DRM_IOCTL_MOD_CTX): + case IOCTL_NR(DRM_IOCTL_GET_CTX): + case IOCTL_NR(DRM_IOCTL_SWITCH_CTX): + case IOCTL_NR(DRM_IOCTL_NEW_CTX): + case IOCTL_NR(DRM_IOCTL_RES_CTX): + + case IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE): + case IOCTL_NR(DRM_IOCTL_AGP_RELEASE): + case IOCTL_NR(DRM_IOCTL_AGP_ENABLE): + case IOCTL_NR(DRM_IOCTL_AGP_INFO): + case IOCTL_NR(DRM_IOCTL_AGP_ALLOC): + case IOCTL_NR(DRM_IOCTL_AGP_FREE): + case IOCTL_NR(DRM_IOCTL_AGP_BIND): + case IOCTL_NR(DRM_IOCTL_AGP_UNBIND): + + /* Mga specific ioctls */ + + case IOCTL_NR(DRM_IOCTL_MGA_INIT): + + /* I810 specific ioctls */ + + case IOCTL_NR(DRM_IOCTL_I810_GETBUF): + case IOCTL_NR(DRM_IOCTL_I810_COPY): + + /* Rage 128 specific ioctls */ - switch (cmd) { + case IOCTL_NR(DRM_IOCTL_R128_PACKET): - case VFAT_IOCTL_READDIR_BOTH: - case VFAT_IOCTL_READDIR_SHORT: - case MTIOCGET: - case MTIOCPOS: - case MTIOCGETCONFIG: - case MTIOCSETCONFIG: - case PPPIOCSCOMPRESS: - case PPPIOCGIDLE: - case NCP_IOC_GET_FS_INFO_V2: - case NCP_IOC_GETOBJECTNAME: - case NCP_IOC_SETOBJECTNAME: - case NCP_IOC_GETPRIVATEDATA: - case NCP_IOC_SETPRIVATEDATA: - case NCP_IOC_GETMOUNTUID2: - case CAPI_MANUFACTURER_CMD: - case VIDIOCGTUNER: - case VIDIOCSTUNER: - case VIDIOCGWIN: - case VIDIOCSWIN: - case VIDIOCGFBUF: - case VIDIOCSFBUF: - case MGSL_IOCSPARAMS: - case MGSL_IOCGPARAMS: - case ATM_GETNAMES: - case ATM_GETLINKRATE: - case ATM_GETTYPE: - case ATM_GETESI: - case ATM_GETADDR: - case ATM_RSTADDR: - case ATM_ADDADDR: - case ATM_DELADDR: - case ATM_GETCIRANGE: - case ATM_SETCIRANGE: - case ATM_SETESI: - case ATM_SETESIF: - case ATM_GETSTAT: - case ATM_GETSTATZ: - case ATM_GETLOOP: - case ATM_SETLOOP: - case ATM_QUERYLOOP: - case ENI_SETMULT: - case NS_GETPSTAT: - /* case NS_SETBUFLEV: This is a duplicate case with ZATM_GETPOOLZ */ - case ZATM_GETPOOLZ: - case ZATM_GETPOOL: - case ZATM_SETPOOL: - case ZATM_GETTHIST: - case IDT77105_GETSTAT: - case IDT77105_GETSTATZ: - case IXJCTL_TONE_CADENCE: - case IXJCTL_FRAMES_READ: - case IXJCTL_FRAMES_WRITTEN: - case IXJCTL_READ_WAIT: - case IXJCTL_WRITE_WAIT: - case IXJCTL_DRYBUFFER_READ: - case I2OHRTGET: - case I2OLCTGET: - case I2OPARMSET: - case I2OPARMGET: - case I2OSWDL: - case I2OSWUL: - case I2OSWDEL: - case I2OHTML: - printk("%x:unimplemented IA32 ioctl system call\n", cmd); - return(-EINVAL); + case IOCTL_NR(VFAT_IOCTL_READDIR_BOTH): + case IOCTL_NR(VFAT_IOCTL_READDIR_SHORT): + case IOCTL_NR(MTIOCGET): + case IOCTL_NR(MTIOCPOS): + case IOCTL_NR(MTIOCGETCONFIG): + case IOCTL_NR(MTIOCSETCONFIG): + case IOCTL_NR(PPPIOCSCOMPRESS): + case IOCTL_NR(PPPIOCGIDLE): + case IOCTL_NR(NCP_IOC_GET_FS_INFO_V2): + case IOCTL_NR(NCP_IOC_GETOBJECTNAME): + case IOCTL_NR(NCP_IOC_SETOBJECTNAME): + case IOCTL_NR(NCP_IOC_GETPRIVATEDATA): + case IOCTL_NR(NCP_IOC_SETPRIVATEDATA): + case IOCTL_NR(NCP_IOC_GETMOUNTUID2): + case IOCTL_NR(CAPI_MANUFACTURER_CMD): + case IOCTL_NR(VIDIOCGTUNER): + case IOCTL_NR(VIDIOCSTUNER): + case IOCTL_NR(VIDIOCGWIN): + case IOCTL_NR(VIDIOCSWIN): + case IOCTL_NR(VIDIOCGFBUF): + case IOCTL_NR(VIDIOCSFBUF): + case IOCTL_NR(MGSL_IOCSPARAMS): + case IOCTL_NR(MGSL_IOCGPARAMS): + case IOCTL_NR(ATM_GETNAMES): + case IOCTL_NR(ATM_GETLINKRATE): + case IOCTL_NR(ATM_GETTYPE): + case IOCTL_NR(ATM_GETESI): + case IOCTL_NR(ATM_GETADDR): + case IOCTL_NR(ATM_RSTADDR): + case IOCTL_NR(ATM_ADDADDR): + case IOCTL_NR(ATM_DELADDR): + case IOCTL_NR(ATM_GETCIRANGE): + case IOCTL_NR(ATM_SETCIRANGE): + case IOCTL_NR(ATM_SETESI): + case IOCTL_NR(ATM_SETESIF): + case IOCTL_NR(ATM_GETSTAT): + case IOCTL_NR(ATM_GETSTATZ): + case IOCTL_NR(ATM_GETLOOP): + case IOCTL_NR(ATM_SETLOOP): + case IOCTL_NR(ATM_QUERYLOOP): + case IOCTL_NR(ENI_SETMULT): + case IOCTL_NR(NS_GETPSTAT): + /* case IOCTL_NR(NS_SETBUFLEV): This is a duplicate case with ZATM_GETPOOLZ */ + case IOCTL_NR(ZATM_GETPOOLZ): + case IOCTL_NR(ZATM_GETPOOL): + case IOCTL_NR(ZATM_SETPOOL): + case IOCTL_NR(ZATM_GETTHIST): + case IOCTL_NR(IDT77105_GETSTAT): + case IOCTL_NR(IDT77105_GETSTATZ): + case IOCTL_NR(IXJCTL_TONE_CADENCE): + case IOCTL_NR(IXJCTL_FRAMES_READ): + case IOCTL_NR(IXJCTL_FRAMES_WRITTEN): + case IOCTL_NR(IXJCTL_READ_WAIT): + case IOCTL_NR(IXJCTL_WRITE_WAIT): + case IOCTL_NR(IXJCTL_DRYBUFFER_READ): + case IOCTL_NR(I2OHRTGET): + case IOCTL_NR(I2OLCTGET): + case IOCTL_NR(I2OPARMSET): + case IOCTL_NR(I2OPARMGET): + case IOCTL_NR(I2OSWDL): + case IOCTL_NR(I2OSWUL): + case IOCTL_NR(I2OSWDEL): + case IOCTL_NR(I2OHTML): + break; default: return(sys_ioctl(fd, cmd, (unsigned long)arg)); } + printk("%x:unimplemented IA32 ioctl system call\n", cmd); + return(-EINVAL); } diff -urN linux-2.4.0-test10/arch/ia64/ia32/ia32_traps.c linux-2.4.0-test10-lia/arch/ia64/ia32/ia32_traps.c --- linux-2.4.0-test10/arch/ia64/ia32/ia32_traps.c Thu Jun 22 07:09:44 2000 +++ linux-2.4.0-test10-lia/arch/ia64/ia32/ia32_traps.c Mon Oct 30 22:30:04 2000 @@ -119,6 +119,6 @@ default: return -1; } - force_sig_info(SIGTRAP, &siginfo, current); + force_sig_info(siginfo.si_signo, &siginfo, current); return 0; } diff -urN linux-2.4.0-test10/arch/ia64/ia32/sys_ia32.c linux-2.4.0-test10-lia/arch/ia64/ia32/sys_ia32.c --- linux-2.4.0-test10/arch/ia64/ia32/sys_ia32.c Mon Oct 9 17:54:53 2000 +++ linux-2.4.0-test10-lia/arch/ia64/ia32/sys_ia32.c Wed Nov 1 23:48:23 2000 @@ -236,8 +236,6 @@ if (OFFSET4K(addr) || OFFSET4K(off)) return -EINVAL; - if (prot & PROT_WRITE) - prot |= PROT_EXEC; prot |= PROT_WRITE; front = NULL; back = NULL; @@ -287,23 +285,20 @@ unsigned int poff; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + prot |= PROT_EXEC; if ((flags & MAP_FIXED) && ((addr & ~PAGE_MASK) || (offset & ~PAGE_MASK))) error = do_mmap_fake(file, addr, len, prot, flags, (loff_t)offset); - else if (!addr && (offset & ~PAGE_MASK)) { + else { poff = offset & PAGE_MASK; len += offset - poff; down(¤t->mm->mmap_sem); - error = do_mmap(file, addr, len, prot, flags, poff); + error = do_mmap_pgoff(file, addr, len, prot, flags, poff >> PAGE_SHIFT); up(¤t->mm->mmap_sem); if (!IS_ERR((void *) error)) error += offset - poff; - } else { - down(¤t->mm->mmap_sem); - error = do_mmap(file, addr, len, prot, flags, offset); - up(¤t->mm->mmap_sem); } return error; } @@ -2032,14 +2027,14 @@ ret = sys_times(tbuf ? &t : NULL); set_fs (old_fs); if (tbuf) { - err = put_user (t.tms_utime, &tbuf->tms_utime); - err |= __put_user (t.tms_stime, &tbuf->tms_stime); - err |= __put_user (t.tms_cutime, &tbuf->tms_cutime); - err |= __put_user (t.tms_cstime, &tbuf->tms_cstime); + err = put_user (IA32_TICK(t.tms_utime), &tbuf->tms_utime); + err |= __put_user (IA32_TICK(t.tms_stime), &tbuf->tms_stime); + err |= __put_user (IA32_TICK(t.tms_cutime), &tbuf->tms_cutime); + err |= __put_user (IA32_TICK(t.tms_cstime), &tbuf->tms_cstime); if (err) ret = -EFAULT; } - return ret; + return IA32_TICK(ret); } unsigned int @@ -2617,6 +2612,45 @@ * manipulating the page protections... */ return(sys_iopl(3, 0, 0, 0)); +} + +typedef struct { + unsigned int ss_sp; + unsigned int ss_flags; + unsigned int ss_size; +} ia32_stack_t; + +asmlinkage long +sys32_sigaltstack (const ia32_stack_t *uss32, ia32_stack_t *uoss32, +long arg2, long arg3, long arg4, +long arg5, long arg6, long arg7, +long stack) +{ + struct pt_regs *pt = (struct pt_regs *) &stack; + stack_t uss, uoss; + ia32_stack_t buf32; + int ret; + mm_segment_t old_fs = get_fs(); + + if (uss32) + if (copy_from_user(&buf32, (void *)A(uss32), sizeof(ia32_stack_t))) + return(-EFAULT); + uss.ss_sp = (void *) (long) buf32.ss_sp; + uss.ss_flags = buf32.ss_flags; + uss.ss_size = buf32.ss_size; + set_fs(KERNEL_DS); + ret = do_sigaltstack(uss32 ? &uss : NULL, &uoss, pt->r12); + set_fs(old_fs); + if (ret < 0) + return(ret); + if (uoss32) { + buf32.ss_sp = (long) uoss.ss_sp; + buf32.ss_flags = uoss.ss_flags; + buf32.ss_size = uoss.ss_size; + if (copy_to_user((void*)A(uoss32), &buf32, sizeof(ia32_stack_t))) + return(-EFAULT); + } + return(ret); } #ifdef NOTYET /* UNTESTED FOR IA64 FROM HERE DOWN */ diff -urN linux-2.4.0-test10/arch/ia64/kernel/Makefile linux-2.4.0-test10-lia/arch/ia64/kernel/Makefile --- linux-2.4.0-test10/arch/ia64/kernel/Makefile Mon Oct 9 17:54:53 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/Makefile Mon Oct 30 22:33:15 2000 @@ -13,7 +13,8 @@ machvec.o pal.o pci-dma.o process.o perfmon.o ptrace.o sal.o semaphore.o setup.o \ signal.o sys_ia64.o traps.o time.o unaligned.o unwind.o -obj-$(CONFIG_IA64_GENERIC) += machvec.o +obj-$(CONFIG_IA64_GENERIC) += machvec.o iosapic.o +obj-$(CONFIG_IA64_DIG) += iosapic.o obj-$(CONFIG_IA64_PALINFO) += palinfo.o obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_SMP) += smp.o smpboot.o @@ -21,7 +22,7 @@ obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o O_TARGET := kernel.o -O_OBJS := $(obj-y) +O_OBJS := $(obj-y) OX_OBJS := ia64_ksyms.o clean:: diff -urN linux-2.4.0-test10/arch/ia64/kernel/acpi.c linux-2.4.0-test10-lia/arch/ia64/kernel/acpi.c --- linux-2.4.0-test10/arch/ia64/kernel/acpi.c Mon Oct 9 17:54:53 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/acpi.c Mon Oct 30 22:33:27 2000 @@ -6,6 +6,8 @@ * * Copyright (C) 1999 VA Linux Systems * Copyright (C) 1999,2000 Walt Drummond + * Copyright (C) 2000 Hewlett-Packard Co. + * Copyright (C) 2000 David Mosberger-Tang */ #include @@ -36,11 +38,14 @@ void (*pm_idle)(void); +asm (".weak iosapic_register_legacy_irq"); +asm (".weak iosapic_init"); + /* * Identify usable CPU's and remember them for SMP bringup later. */ static void __init -acpi_lsapic(char *p) +acpi_lsapic (char *p) { int add = 1; @@ -58,7 +63,7 @@ printk("Performance Restricted; ignoring.\n"); add = 0; } - + #ifdef CONFIG_SMP smp_boot_data.cpu_phys_id[total_cpus] = -1; #endif @@ -73,83 +78,40 @@ } /* - * Configure legacy IRQ information in iosapic_vector + * Configure legacy IRQ information. */ static void __init -acpi_legacy_irq(char *p) +acpi_legacy_irq (char *p) { - /* - * This is not good. ACPI is not necessarily limited to CONFIG_IA64_DIG, yet - * ACPI does not necessarily imply IOSAPIC either. Perhaps there should be - * a means for platform_setup() to register ACPI handlers? - */ -#ifdef CONFIG_IA64_IRQ_ACPI acpi_entry_int_override_t *legacy = (acpi_entry_int_override_t *) p; - unsigned char vector; - int i; - - vector = isa_irq_to_vector(legacy->isa_irq); + unsigned long polarity = 0, edge_triggered = 0; /* - * Clobber any old pin mapping. It may be that it gets replaced later on + * If the platform we're running doesn't define + * iosapic_register_legacy_irq(), we ignore this info... */ - for (i = 0; i < IA64_MAX_VECTORED_IRQ; i++) { - if (i == vector) - continue; - if (iosapic_pin(i) == iosapic_pin(vector)) - iosapic_pin(i) = 0xff; - } - - iosapic_pin(vector) = legacy->pin; - iosapic_bus(vector) = BUS_ISA; /* This table only overrides the ISA devices */ - iosapic_busdata(vector) = 0; - - /* - * External timer tick is special... - */ - if (vector != TIMER_IRQ) - iosapic_dmode(vector) = IO_SAPIC_LOWEST_PRIORITY; - else - iosapic_dmode(vector) = IO_SAPIC_FIXED; - + if (!iosapic_register_legacy_irq) + return; + /* See MPS 1.4 section 4.3.4 */ switch (legacy->flags) { - case 0x5: - iosapic_polarity(vector) = IO_SAPIC_POL_HIGH; - iosapic_trigger(vector) = IO_SAPIC_EDGE; - break; - case 0x8: - iosapic_polarity(vector) = IO_SAPIC_POL_LOW; - iosapic_trigger(vector) = IO_SAPIC_EDGE; - break; - case 0xd: - iosapic_polarity(vector) = IO_SAPIC_POL_HIGH; - iosapic_trigger(vector) = IO_SAPIC_LEVEL; - break; - case 0xf: - iosapic_polarity(vector) = IO_SAPIC_POL_LOW; - iosapic_trigger(vector) = IO_SAPIC_LEVEL; - break; - default: + case 0x5: polarity = 1; edge_triggered = 1; break; + case 0x8: polarity = 0; edge_triggered = 1; break; + case 0xd: polarity = 1; edge_triggered = 0; break; + case 0xf: polarity = 0; edge_triggered = 0; break; + default: printk(" ACPI Legacy IRQ 0x%02x: Unknown flags 0x%x\n", legacy->isa_irq, legacy->flags); break; } - -# ifdef ACPI_DEBUG - printk("Legacy ISA IRQ %x -> IA64 Vector %x IOSAPIC Pin %x Active %s %s Trigger\n", - legacy->isa_irq, vector, iosapic_pin(vector), - ((iosapic_polarity(vector) == IO_SAPIC_POL_LOW) ? "Low" : "High"), - ((iosapic_trigger(vector) == IO_SAPIC_LEVEL) ? "Level" : "Edge")); -# endif /* ACPI_DEBUG */ -#endif /* CONFIG_IA64_IRQ_ACPI */ + iosapic_register_legacy_irq(legacy->isa_irq, legacy->pin, polarity, edge_triggered); } /* * Info on platform interrupt sources: NMI. PMI, INIT, etc. */ static void __init -acpi_platform(char *p) +acpi_platform (char *p) { acpi_entry_platform_src_t *plat = (acpi_entry_platform_src_t *) p; @@ -161,8 +123,9 @@ * Parse the ACPI Multiple SAPIC Table */ static void __init -acpi_parse_msapic(acpi_sapic_t *msapic) +acpi_parse_msapic (acpi_sapic_t *msapic) { + acpi_entry_iosapic_t *iosapic; char *p, *end; /* Base address of IPI Message Block */ @@ -172,41 +135,31 @@ end = p + (msapic->header.length - sizeof(acpi_sapic_t)); while (p < end) { - switch (*p) { - case ACPI_ENTRY_LOCAL_SAPIC: + case ACPI_ENTRY_LOCAL_SAPIC: acpi_lsapic(p); break; - case ACPI_ENTRY_IO_SAPIC: - platform_register_iosapic((acpi_entry_iosapic_t *) p); + case ACPI_ENTRY_IO_SAPIC: + iosapic = (acpi_entry_iosapic_t *) p; + if (iosapic_init) + iosapic_init(iosapic->address, iosapic->irq_base); break; - case ACPI_ENTRY_INT_SRC_OVERRIDE: + case ACPI_ENTRY_INT_SRC_OVERRIDE: acpi_legacy_irq(p); break; - - case ACPI_ENTRY_PLATFORM_INT_SOURCE: + + case ACPI_ENTRY_PLATFORM_INT_SOURCE: acpi_platform(p); break; - - default: + + default: break; } /* Move to next table entry. */ -#define BAD_ACPI_TABLE -#ifdef BAD_ACPI_TABLE - /* - * Some prototype Lion's have a bad ACPI table - * requiring this fix. Without this fix, those - * machines crash during bootup. - */ - if (p[1] == 0) - p = end; - else -#endif - p += p[1]; + p += p[1]; } /* Make bootup pretty */ @@ -214,7 +167,7 @@ } int __init -acpi_parse(acpi_rsdp_t *rsdp) +acpi_parse (acpi_rsdp_t *rsdp) { acpi_rsdt_t *rsdt; acpi_desc_table_hdr_t *hdrp; @@ -256,7 +209,7 @@ } #ifdef CONFIG_ACPI_KERNEL_CONFIG - acpi_cf_terminate(); + acpi_cf_terminate(); #endif #ifdef CONFIG_SMP diff -urN linux-2.4.0-test10/arch/ia64/kernel/efi.c linux-2.4.0-test10-lia/arch/ia64/kernel/efi.c --- linux-2.4.0-test10/arch/ia64/kernel/efi.c Fri Oct 13 12:05:29 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/efi.c Mon Oct 30 22:33:51 2000 @@ -18,7 +18,6 @@ * Goutham Rao: * Skip non-WB memory and ignore empty memory ranges. */ -#include #include #include #include @@ -364,7 +363,7 @@ #if EFI_DEBUG /* print EFI memory map: */ { - efi_memory_desc_t *md = p; + efi_memory_desc_t *md; void *p; for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) { diff -urN linux-2.4.0-test10/arch/ia64/kernel/entry.S linux-2.4.0-test10-lia/arch/ia64/kernel/entry.S --- linux-2.4.0-test10/arch/ia64/kernel/entry.S Mon Oct 9 17:54:54 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/entry.S Wed Nov 15 17:52:56 2000 @@ -11,6 +11,17 @@ * Copyright (C) 1999 Don Dugger */ /* + * ia64_switch_to now places correct virtual mapping in in TR2 for + * kernel stack. This allows us to handle interrupts without changing + * to physical mode. + * + * ar.k4 is now used to hold last virtual map address + * + * Jonathan Nickin + * Patrick O'Rourke + * 11/07/2000 + / +/* * Global (preserved) predicate usage on syscall entry/exit path: * * pKern: See entry.h. @@ -27,7 +38,8 @@ #include #include #include - +#include + #include "entry.h" .text @@ -98,6 +110,8 @@ br.ret.sptk.many rp END(sys_clone) +#define KSTACK_TR 2 + /* * prev_task <- ia64_switch_to(struct task_struct *next) */ @@ -108,22 +122,55 @@ UNW(.body) adds r22=IA64_TASK_THREAD_KSP_OFFSET,r13 - dep r18=-1,r0,0,61 // build mask 0x1fffffffffffffff + mov r27=ar.k4 + dep r20=0,in0,61,3 // physical address of "current" + ;; + st8 [r22]=sp // save kernel stack pointer of old task + shr.u r26=r20,_PAGE_SIZE_256M + ;; + cmp.eq p7,p6=r26,r0 // check < 256M adds r21=IA64_TASK_THREAD_KSP_OFFSET,in0 ;; - st8 [r22]=sp // save kernel stack pointer of old task - ld8 sp=[r21] // load kernel stack pointer of new task - and r20=in0,r18 // physical address of "current" - ;; - mov ar.k6=r20 // copy "current" into ar.k6 - mov r8=r13 // return pointer to previously running task - mov r13=in0 // set "current" pointer + /* + * If we've already mapped this task's page, we can skip doing it + * again. + */ +(p6) cmp.eq p7,p6=r26,r27 +(p6) br.cond.dpnt.few .map + ;; +.done: ld8 sp=[r21] // load kernel stack pointer of new task +(p6) ssm psr.ic // if we we had to map, renable the psr.ic bit FIRST!!! ;; +(p6) srlz.d + mov ar.k6=r20 // copy "current" into ar.k6 + mov r8=r13 // return pointer to previously running task + mov r13=in0 // set "current" pointer + ;; +(p6) ssm psr.i // renable psr.i AFTER the ic bit is serialized DO_LOAD_SWITCH_STACK( ) + #ifdef CONFIG_SMP - sync.i // ensure "fc"s done by this CPU are visible on other CPUs -#endif - br.ret.sptk.few rp + sync.i // ensure "fc"s done by this CPU are visible on other CPUs +#endif + br.ret.sptk.few rp // boogie on out in new context + +.map: + rsm psr.i | psr.ic + movl r25=__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RWX + ;; + srlz.d + or r23=r25,r20 // construct PA | page properties + mov r25=_PAGE_SIZE_256M<<2 + ;; + mov cr.itir=r25 + mov cr.ifa=in0 // VA of next task... + ;; + mov r25=KSTACK_TR // use tr entry #2... + mov ar.k4=r26 // remember last page we mapped... + ;; + itr.d dtr[r25]=r23 // wire in new mapping... + br.cond.sptk.many .done + ;; END(ia64_switch_to) #ifndef CONFIG_IA64_NEW_UNWIND @@ -503,7 +550,7 @@ ;; ld4 r2=[r2] ;; - shl r2=r2,SMP_LOG_CACHE_BYTES // can't use shladd here... + shl r2=r2,SMP_CACHE_SHIFT // can't use shladd here... ;; add r3=r2,r3 #else @@ -611,14 +658,13 @@ mov ar.ccv=r1 mov ar.fpsr=r13 mov b0=r14 - // turn off interrupts, interrupt collection, & data translation - rsm psr.i | psr.ic | psr.dt + // turn off interrupts, interrupt collection + rsm psr.i | psr.ic ;; srlz.i // EAS 2.5 mov b7=r15 ;; invala // invalidate ALAT - dep r12=0,r12,61,3 // convert sp to physical address bsw.0;; // switch back to bank 0 (must be last in insn group) ;; #ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC @@ -1091,7 +1137,7 @@ data8 sys_setpriority data8 sys_statfs data8 sys_fstatfs - data8 ia64_ni_syscall + data8 ia64_ni_syscall // 1105 data8 sys_semget data8 sys_semop data8 sys_semctl diff -urN linux-2.4.0-test10/arch/ia64/kernel/fw-emu.c linux-2.4.0-test10-lia/arch/ia64/kernel/fw-emu.c --- linux-2.4.0-test10/arch/ia64/kernel/fw-emu.c Mon Oct 9 17:54:54 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/fw-emu.c Wed Nov 15 17:53:32 2000 @@ -402,7 +402,6 @@ sal_systab->sal_rev_minor = 1; sal_systab->sal_rev_major = 0; sal_systab->entry_count = 1; - sal_systab->ia32_bios_present = 0; #ifdef CONFIG_IA64_GENERIC strcpy(sal_systab->oem_id, "Generic"); diff -urN linux-2.4.0-test10/arch/ia64/kernel/head.S linux-2.4.0-test10-lia/arch/ia64/kernel/head.S --- linux-2.4.0-test10/arch/ia64/kernel/head.S Mon Oct 9 17:54:54 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/head.S Wed Nov 15 17:54:03 2000 @@ -74,8 +74,8 @@ ;; #ifdef CONFIG_IA64_EARLY_PRINTK - mov r2=6 - mov r3=(8<<8) | (28<<2) + mov r3=(6<<8) | (28<<2) + movl r2=6<<61 ;; mov rr[r2]=r3 ;; @@ -168,6 +168,11 @@ add r19=IA64_NUM_DBG_REGS*8,in0 ;; 1: mov r16=dbr[r18] +#if defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) || defined(CONFIG_ITANIUM_BSTEP_SPECIFIC) \ + || defined(CONFIG_ITANIUM_C0_SPECIFIC) + ;; + srlz.d +#endif mov r17=ibr[r18] add r18=1,r18 ;; @@ -181,7 +186,8 @@ GLOBAL_ENTRY(ia64_load_debug_regs) alloc r16=ar.pfs,1,0,0,0 -#if !(defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) || defined(CONFIG_ITANIUM_BSTEP_SPECIFIC)) +#if !(defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) \ + || defined(CONFIG_ITANIUM_B0_SPECIFIC) || defined(CONFIG_ITANIUM_B1_SPECIFIC)) lfetch.nta [in0] #endif mov r20=ar.lc // preserve ar.lc @@ -194,6 +200,11 @@ add r18=1,r18 ;; mov dbr[r18]=r16 +#if defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) || defined(CONFIG_ITANIUM_BSTEP_SPECIFIC) \ + || defined(CONFIG_ITANIUM_C0_SPECIFIC) + ;; + srlz.d +#endif mov ibr[r18]=r17 br.cloop.sptk.few 1b ;; @@ -754,7 +765,7 @@ mov tmp=ar.itc (p15) br.cond.sptk .wait ;; - ld1 tmp=[r31] + ld4 tmp=[r31] ;; cmp.ne p15,p0=tmp,r0 mov tmp=ar.itc @@ -764,7 +775,7 @@ mov tmp=1 ;; IA64_SEMFIX_INSN - cmpxchg1.acq tmp=[r31],tmp,ar.ccv + cmpxchg4.acq tmp=[r31],tmp,ar.ccv ;; cmp.eq p15,p0=tmp,r0 diff -urN linux-2.4.0-test10/arch/ia64/kernel/iosapic.c linux-2.4.0-test10-lia/arch/ia64/kernel/iosapic.c --- linux-2.4.0-test10/arch/ia64/kernel/iosapic.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/iosapic.c Mon Oct 30 22:28:42 2000 @@ -0,0 +1,495 @@ +/* + * I/O SAPIC support. + * + * Copyright (C) 1999 Intel Corp. + * Copyright (C) 1999 Asit Mallick + * Copyright (C) 1999-2000 Hewlett-Packard Co. + * Copyright (C) 1999-2000 David Mosberger-Tang + * Copyright (C) 1999 VA Linux Systems + * Copyright (C) 1999,2000 Walt Drummond + * + * 00/04/19 D. Mosberger Rewritten to mirror more closely the x86 I/O APIC code. + * In particular, we now have separate handlers for edge + * and level triggered interrupts. + * 00/10/27 Asit Mallick, Goutham Rao IRQ vector allocation + * PCI to vector mapping, shared PCI interrupts. + * 00/10/27 D. Mosberger Document things a bit more to make them more understandable. + * Clean up much of the old IOSAPIC cruft. + */ +/* + * Here is what the interrupt logic between a PCI device and the CPU looks like: + * + * (1) A PCI device raises one of the four interrupt pins (INTA, INTB, INTC, INTD). The + * device is uniquely identified by its bus-, device-, and slot-number (the function + * number does not matter here because all functions share the same interrupt + * lines). + * + * (2) The motherboard routes the interrupt line to a pin on a IOSAPIC controller. + * Multiple interrupt lines may have to share the same IOSAPIC pin (if they're level + * triggered and use the same polarity). Each interrupt line has a unique IOSAPIC + * irq number which can be calculated as the sum of the controller's base irq number + * and the IOSAPIC pin number to which the line connects. + * + * (3) The IOSAPIC uses an internal table to map the IOSAPIC pin into the IA-64 interrupt + * vector. This interrupt vector is then sent to the CPU. + * + * In other words, there are two levels of indirections involved: + * + * pci pin -> iosapic irq -> IA-64 vector + * + * Note: outside this module, IA-64 vectors are called "irqs". This is because that's + * the traditional name Linux uses for interrupt vectors. + */ +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_ACPI_KERNEL_CONFIG +# include +#endif + +#undef DEBUG_IRQ_ROUTING + +static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED; + +/* PCI pin to IOSAPIC irq routing information. This info typically comes from ACPI. */ + +static struct { + int num_routes; + struct pci_vector_struct *route; +} pci_irq; + +/* This tables maps IA-64 vectors to the IOSAPIC pin that generates this vector. */ + +static struct iosapic_irq { + char *addr; /* base address of IOSAPIC */ + unsigned char base_irq; /* first irq assigned to this IOSAPIC */ + char pin; /* IOSAPIC pin (-1 => not an IOSAPIC irq) */ + unsigned char dmode : 3; /* delivery mode (see iosapic.h) */ + unsigned char polarity : 1; /* interrupt polarity (see iosapic.h) */ + unsigned char trigger : 1; /* trigger mode (see iosapic.h) */ +} iosapic_irq[NR_IRQS]; + +/* + * Translate IOSAPIC irq number to the corresponding IA-64 interrupt vector. If no + * entry exists, return -1. + */ +static int +iosapic_irq_to_vector (int irq) +{ + int vector; + + for (vector = 0; vector < NR_IRQS; ++vector) + if (iosapic_irq[vector].base_irq + iosapic_irq[vector].pin == irq) + return vector; + return -1; +} + +/* + * Map PCI pin to the corresponding IA-64 interrupt vector. If no such mapping exists, + * return -1. + */ +static int +pci_pin_to_vector (int bus, int slot, int pci_pin) +{ + struct pci_vector_struct *r; + + for (r = pci_irq.route; r < pci_irq.route + pci_irq.num_routes; ++r) + if (r->bus == bus && (r->pci_id >> 16) == slot && r->pin == pci_pin) + return iosapic_irq_to_vector(r->irq); + return -1; +} + +static void +set_rte (unsigned int vector, unsigned long dest) +{ + unsigned long pol, trigger, dmode; + u32 low32, high32; + char *addr; + int pin; + + pin = iosapic_irq[vector].pin; + if (pin < 0) + return; /* not an IOSAPIC interrupt */ + + addr = iosapic_irq[vector].addr; + pol = iosapic_irq[vector].polarity; + trigger = iosapic_irq[vector].trigger; + dmode = iosapic_irq[vector].dmode; + + low32 = ((pol << IOSAPIC_POLARITY_SHIFT) | + (trigger << IOSAPIC_TRIGGER_SHIFT) | + (dmode << IOSAPIC_DELIVERY_SHIFT) | + vector); + +#ifdef CONFIG_IA64_AZUSA_HACKS + /* set Flush Disable bit */ + if (addr != (char *) 0xc0000000fec00000) + low32 |= (1 << 17); +#endif + + /* dest contains both id and eid */ + high32 = (dest << IOSAPIC_DEST_SHIFT); + + writel(IOSAPIC_RTE_HIGH(pin), addr + IOSAPIC_REG_SELECT); + writel(high32, addr + IOSAPIC_WINDOW); + writel(IOSAPIC_RTE_LOW(pin), addr + IOSAPIC_REG_SELECT); + writel(low32, addr + IOSAPIC_WINDOW); +} + +static void +nop (unsigned int vector) +{ + /* do nothing... */ +} + +static void +mask_irq (unsigned int vector) +{ + unsigned long flags; + char *addr; + u32 low32; + int pin; + + addr = iosapic_irq[vector].addr; + pin = iosapic_irq[vector].pin; + + if (pin < 0) + return; /* not an IOSAPIC interrupt! */ + + spin_lock_irqsave(&iosapic_lock, flags); + { + writel(IOSAPIC_RTE_LOW(pin), addr + IOSAPIC_REG_SELECT); + low32 = readl(addr + IOSAPIC_WINDOW); + + low32 |= (1 << IOSAPIC_MASK_SHIFT); /* set only the mask bit */ + writel(low32, addr + IOSAPIC_WINDOW); + } + spin_unlock_irqrestore(&iosapic_lock, flags); +} + +static void +unmask_irq (unsigned int vector) +{ + unsigned long flags; + char *addr; + u32 low32; + int pin; + + addr = iosapic_irq[vector].addr; + pin = iosapic_irq[vector].pin; + if (pin < 0) + return; /* not an IOSAPIC interrupt! */ + + spin_lock_irqsave(&iosapic_lock, flags); + { + writel(IOSAPIC_RTE_LOW(pin), addr + IOSAPIC_REG_SELECT); + low32 = readl(addr + IOSAPIC_WINDOW); + + low32 &= ~(1 << IOSAPIC_MASK_SHIFT); /* clear only the mask bit */ + writel(low32, addr + IOSAPIC_WINDOW); + } + spin_unlock_irqrestore(&iosapic_lock, flags); +} + + +static void +iosapic_set_affinity (unsigned int vector, unsigned long mask) +{ + printk("iosapic_set_affinity: not implemented yet\n"); +} + +/* + * Handlers for level-triggered interrupts. + */ + +static unsigned int +iosapic_startup_level_irq (unsigned int vector) +{ + unmask_irq(vector); + return 0; +} + +static void +iosapic_end_level_irq (unsigned int vector) +{ + writel(vector, iosapic_irq[vector].addr + IOSAPIC_EOI); +} + +#define iosapic_shutdown_level_irq mask_irq +#define iosapic_enable_level_irq unmask_irq +#define iosapic_disable_level_irq mask_irq +#define iosapic_ack_level_irq nop + +struct hw_interrupt_type irq_type_iosapic_level = { + typename: "IO-SAPIC-level", + startup: iosapic_startup_level_irq, + shutdown: iosapic_shutdown_level_irq, + enable: iosapic_enable_level_irq, + disable: iosapic_disable_level_irq, + ack: iosapic_ack_level_irq, + end: iosapic_end_level_irq, + set_affinity: iosapic_set_affinity +}; + +/* + * Handlers for edge-triggered interrupts. + */ + +static unsigned int +iosapic_startup_edge_irq (unsigned int vector) +{ + unmask_irq(vector); + /* + * IOSAPIC simply drops interrupts pended while the + * corresponding pin was masked, so we can't know if an + * interrupt is pending already. Let's hope not... + */ + return 0; +} + +static void +iosapic_ack_edge_irq (unsigned int vector) +{ + /* + * Once we have recorded IRQ_PENDING already, we can mask the + * interrupt for real. This prevents IRQ storms from unhandled + * devices. + */ + if ((irq_desc[vector].status & (IRQ_PENDING|IRQ_DISABLED)) == (IRQ_PENDING|IRQ_DISABLED)) + mask_irq(vector); +} + +#define iosapic_enable_edge_irq unmask_irq +#define iosapic_disable_edge_irq nop +#define iosapic_end_edge_irq nop + +struct hw_interrupt_type irq_type_iosapic_edge = { + typename: "IO-SAPIC-edge", + startup: iosapic_startup_edge_irq, + shutdown: iosapic_disable_edge_irq, + enable: iosapic_enable_edge_irq, + disable: iosapic_disable_edge_irq, + ack: iosapic_ack_edge_irq, + end: iosapic_end_edge_irq, + set_affinity: iosapic_set_affinity +}; + +static unsigned int +iosapic_version (char *addr) +{ + /* + * IOSAPIC Version Register return 32 bit structure like: + * { + * unsigned int version : 8; + * unsigned int reserved1 : 8; + * unsigned int pins : 8; + * unsigned int reserved2 : 8; + * } + */ + writel(IOSAPIC_VERSION, addr + IOSAPIC_REG_SELECT); + return readl(IOSAPIC_WINDOW + addr); +} + +/* + * ACPI calls this when it finds an entry for a legacy ISA interrupt. Note that the + * irq_base and IOSAPIC address must be set in iosapic_init(). + */ +void +iosapic_register_legacy_irq (unsigned long irq, + unsigned long pin, unsigned long polarity, + unsigned long edge_triggered) +{ + unsigned int vector = isa_irq_to_vector(irq); + +#ifdef DEBUG_IRQ_ROUTING + printk("ISA: IRQ %u -> IOSAPIC irq 0x%02x (%s, %s) -> vector %02x\n", + (unsigned) irq, (unsigned) pin, + polarity ? "high" : "low", edge_triggered ? "edge" : "level", + vector); +#endif + + iosapic_irq[vector].pin = pin; + iosapic_irq[vector].dmode = IOSAPIC_LOWEST_PRIORITY; + iosapic_irq[vector].polarity = polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW; + iosapic_irq[vector].trigger = edge_triggered ? IOSAPIC_EDGE : IOSAPIC_LEVEL; +} + +void __init +iosapic_init (unsigned long phys_addr, unsigned int base_irq) +{ + struct hw_interrupt_type *irq_type; + int i, irq, max_pin, vector; + unsigned int ver; + char *addr; + static int first_time = 1; + + if (first_time) { + first_time = 0; + + for (vector = 0; vector < NR_IRQS; ++vector) + iosapic_irq[vector].pin = -1; /* mark as unused */ + + /* + * Fetch the PCI interrupt routing table: + */ +#ifdef CONFIG_ACPI_KERNEL_CONFIG + acpi_cf_get_pci_vectors(&pci_irq.route, &pci_irq.num_routes); +#else + pci_irq.route = + (struct pci_vector_struct *) __va(ia64_boot_param.pci_vectors); + pci_irq.num_routes = ia64_boot_param.num_pci_vectors; +#endif + } + + addr = ioremap(phys_addr, 0); + + ver = iosapic_version(addr); + max_pin = (ver >> 16) & 0xff; + + printk("IOSAPIC: version %x.%x, address 0x%lx, IRQs 0x%02x-0x%02x\n", + (ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, base_irq, base_irq + max_pin); + + if (base_irq == 0) + /* + * Map the legacy ISA devices into the IOSAPIC data. Some of these may + * get reprogrammed later on with data from the ACPI Interrupt Source + * Override table. + */ + for (irq = 0; irq < 16; ++irq) { + vector = isa_irq_to_vector(irq); + iosapic_irq[vector].addr = addr; + iosapic_irq[vector].base_irq = 0; + if (iosapic_irq[vector].pin == -1) + iosapic_irq[vector].pin = irq; + iosapic_irq[vector].dmode = IOSAPIC_LOWEST_PRIORITY; + iosapic_irq[vector].trigger = IOSAPIC_EDGE; + iosapic_irq[vector].polarity = IOSAPIC_POL_HIGH; +#ifdef DEBUG_IRQ_ROUTING + printk("ISA: IRQ %u -> IOSAPIC irq 0x%02x (high, edge) -> vector 0x%02x\n", + irq, iosapic_irq[vector].base_irq + iosapic_irq[vector].pin, + vector); +#endif + irq_type = &irq_type_iosapic_edge; + if (irq_desc[vector].handler != irq_type) { + if (irq_desc[vector].handler != &no_irq_type) + printk("iosapic_init: changing vector 0x%02x from %s to " + "%s\n", irq, irq_desc[vector].handler->typename, + irq_type->typename); + irq_desc[vector].handler = irq_type; + } + + /* program the IOSAPIC routing table: */ + set_rte(vector, (ia64_get_lid() >> 16) & 0xffff); + } + +#ifndef CONFIG_IA64_SOFTSDV_HACKS + for (i = 0; i < pci_irq.num_routes; i++) { + irq = pci_irq.route[i].irq; + + if ((unsigned) (irq - base_irq) > max_pin) + /* the interrupt route is for another controller... */ + continue; + + if (irq < 16) + vector = isa_irq_to_vector(irq); + else { + vector = iosapic_irq_to_vector(irq); + if (vector < 0) + /* new iosapic irq: allocate a vector for it */ + vector = ia64_alloc_irq(); + } + + iosapic_irq[vector].addr = addr; + iosapic_irq[vector].base_irq = base_irq; + iosapic_irq[vector].pin = (irq - base_irq); + iosapic_irq[vector].dmode = IOSAPIC_LOWEST_PRIORITY; + iosapic_irq[vector].trigger = IOSAPIC_LEVEL; + iosapic_irq[vector].polarity = IOSAPIC_POL_LOW; + +# ifdef DEBUG_IRQ_ROUTING + printk("PCI: (B%d,I%d,P%d) -> IOSAPIC irq 0x%02x -> vector 0x%02x\n", + pci_irq.route[i].bus, pci_irq.route[i].pci_id>>16, pci_irq.route[i].pin, + iosapic_irq[vector].base_irq + iosapic_irq[vector].pin, vector); +# endif + irq_type = &irq_type_iosapic_level; + if (irq_desc[vector].handler != irq_type){ + if (irq_desc[vector].handler != &no_irq_type) + printk("iosapic_init: changing vector 0x%02x from %s to %s\n", + vector, irq_desc[vector].handler->typename, + irq_type->typename); + irq_desc[vector].handler = irq_type; + } + + /* program the IOSAPIC routing table: */ + set_rte(vector, (ia64_get_lid() >> 16) & 0xffff); + } +#endif /* !CONFIG_IA64_SOFTSDV_HACKS */ +} + +void +iosapic_pci_fixup (void) +{ + struct pci_dev *dev; + unsigned char pin; + int vector; + + pci_for_each_dev(dev) { + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + if (pin) { + pin--; /* interrupt pins are numbered starting from 1 */ + vector = pci_pin_to_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin); + if (vector < 0 && dev->bus->parent) { + /* go back to the bridge */ + struct pci_dev *bridge = dev->bus->self; + + if (bridge) { + /* allow for multiple bridges on an adapter */ + do { + /* do the bridge swizzle... */ + pin = (pin + PCI_SLOT(dev->devfn)) % 4; + vector = pci_pin_to_vector(bridge->bus->number, + PCI_SLOT(bridge->devfn), + pin); + } while (vector < 0 && (bridge = bridge->bus->self)); + } + if (vector >= 0) + printk(KERN_WARNING + "PCI: using PPB(B%d,I%d,P%d) to get vector %02x\n", + bridge->bus->number, PCI_SLOT(bridge->devfn), + pin, vector); + else + printk(KERN_WARNING + "PCI: Couldn't map irq for (B%d,I%d,P%d)o\n", + bridge->bus->number, PCI_SLOT(bridge->devfn), + pin); + } + if (vector >= 0) { + printk("PCI->APIC IRQ transform: (B%d,I%d,P%d) -> 0x%02x\n", + dev->bus->number, PCI_SLOT(dev->devfn), pin, vector); + dev->irq = vector; + } + } + /* + * Nothing to fixup + * Fix out-of-range IRQ numbers + */ + if (dev->irq >= NR_IRQS) + dev->irq = 15; /* Spurious interrupts */ + } +} diff -urN linux-2.4.0-test10/arch/ia64/kernel/irq_ia64.c linux-2.4.0-test10-lia/arch/ia64/kernel/irq_ia64.c --- linux-2.4.0-test10/arch/ia64/kernel/irq_ia64.c Mon Oct 9 17:54:54 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/irq_ia64.c Mon Oct 30 22:35:56 2000 @@ -7,6 +7,9 @@ * * 6/10/99: Updated to bring in sync with x86 version to facilitate * support for SMP and different interrupt controllers. + * + * 09/15/00 Goutham Rao Implemented pci_irq_to_vector + * PCI to vector allocation routine. */ #include @@ -43,15 +46,25 @@ unsigned long ipi_base_addr = (__IA64_UNCACHED_OFFSET | IPI_DEFAULT_BASE_ADDR); /* - * Legacy IRQ to IA-64 vector translation table. Any vector not in - * this table maps to itself (ie: irq 0x30 => IA64 vector 0x30) + * Legacy IRQ to IA-64 vector translation table. */ __u8 isa_irq_to_vector_map[16] = { /* 8259 IRQ translation, first 16 entries */ - 0x60, 0x50, 0x10, 0x51, 0x52, 0x53, 0x43, 0x54, - 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x40, 0x41 + 0x2f, 0x20, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, + 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21 }; +int +ia64_alloc_irq (void) +{ + static int next_irq = FIRST_DEVICE_IRQ; + + if (next_irq > LAST_DEVICE_IRQ) + /* XXX could look for sharable vectors instead of panic'ing... */ + panic("ia64_alloc_irq: out of interrupt vectors!"); + return next_irq++; +} + #ifdef CONFIG_ITANIUM_A1_SPECIFIC int usbfix; @@ -217,7 +230,7 @@ } void -ipi_send (int cpu, int vector, int delivery_mode, int redirect) +ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect) { unsigned long ipi_addr; unsigned long ipi_data; diff -urN linux-2.4.0-test10/arch/ia64/kernel/ivt.S linux-2.4.0-test10-lia/arch/ia64/kernel/ivt.S --- linux-2.4.0-test10/arch/ia64/kernel/ivt.S Mon Oct 9 17:54:54 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/ivt.S Wed Nov 15 17:54:59 2000 @@ -44,20 +44,10 @@ #include #include -#define MINSTATE_START_SAVE_MIN /* no special action needed */ -#define MINSTATE_END_SAVE_MIN \ - or r2=r2,r14; /* make first base a kernel virtual address */ \ - or r12=r12,r14; /* make sp a kernel virtual address */ \ - or r13=r13,r14; /* make `current' a kernel virtual address */ \ - bsw.1; /* switch back to bank 1 (must be last in insn group) */ \ - ;; - +#define MINSTATE_VIRT /* needed by minstate.h */ #include "minstate.h" #define FAULT(n) \ - rsm psr.dt; /* avoid nested faults due to TLB misses... */ \ - ;; \ - srlz.d; /* ensure everyone knows psr.dt is off... */ \ mov r31=pr; \ mov r19=n;; /* prepare to save predicates */ \ br.cond.sptk.many dispatch_to_fault_handler @@ -419,6 +409,10 @@ //----------------------------------------------------------------------------------- // call do_page_fault (predicates are in r31, psr.dt is off, r16 is faulting address) page_fault: + ssm psr.dt + ;; + srlz.i + ;; SAVE_MIN_WITH_COVER // // Copy control registers to temporary registers, then turn on psr bits, @@ -430,7 +424,7 @@ mov r9=cr.isr adds r3=8,r2 // set up second base pointer ;; - ssm psr.ic | psr.dt + ssm psr.ic ;; srlz.i // guarantee that interrupt collection is enabled ;; @@ -725,16 +719,14 @@ mov r16=cr.iim mov r17=__IA64_BREAK_SYSCALL mov r31=pr // prepare to save predicates - rsm psr.dt // avoid nested faults due to TLB misses... ;; - srlz.d // ensure everyone knows psr.dt is off... cmp.eq p0,p7=r16,r17 // is this a system call? (p7 <- false, if so) (p7) br.cond.spnt.many non_syscall SAVE_MIN // uses r31; defines r2: - // turn interrupt collection and data translation back on: - ssm psr.ic | psr.dt + // turn interrupt collection back on: + ssm psr.ic ;; srlz.i // guarantee that interrupt collection is enabled cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0 @@ -795,17 +787,14 @@ .align 1024 ///////////////////////////////////////////////////////////////////////////////////////// // 0x3000 Entry 12 (size 64 bundles) External Interrupt (4) - rsm psr.dt // avoid nested faults due to TLB misses... - ;; - srlz.d // ensure everyone knows psr.dt is off... mov r31=pr // prepare to save predicates ;; SAVE_MIN_WITH_COVER // uses r31; defines r2 and r3 - ssm psr.ic | psr.dt // turn interrupt collection and data translation back on + ssm psr.ic // turn interrupt collection ;; adds r3=8,r2 // set up second base pointer for SAVE_REST - srlz.i // ensure everybody knows psr.ic and psr.dt are back on + srlz.i // ensure everybody knows psr.ic is back on ;; SAVE_REST ;; @@ -855,7 +844,7 @@ // The "alloc" can cause a mandatory store which could lead to // an "Alt DTLB" fault which we can handle only if psr.ic is on. // - ssm psr.ic | psr.dt + ssm psr.ic ;; srlz.i // guarantee that interrupt collection is enabled ;; @@ -900,7 +889,7 @@ SAVE_MIN ;; mov r14=cr.isr - ssm psr.ic | psr.dt + ssm psr.ic ;; srlz.i // guarantee that interrupt collection is enabled ;; @@ -924,7 +913,7 @@ alloc r15=ar.pfs,0,0,6,0 // must first in an insn group ;; ld4 r8=[r14],8 // r8 == EAX (syscall number) - mov r15=190 // sys_vfork - last implemented system call + mov r15=222 // sys_vfork - last implemented system call ;; cmp.leu.unc p6,p7=r8,r15 ld4 out1=[r14],8 // r9 == ecx @@ -985,8 +974,8 @@ mov r8=cr.iim // get break immediate (must be done while psr.ic is off) adds r3=8,r2 // set up second base pointer for SAVE_REST - // turn interrupt collection and data translation back on: - ssm psr.ic | psr.dt + // turn interrupt collection back on: + ssm psr.ic ;; srlz.i // guarantee that interrupt collection is enabled ;; @@ -1023,7 +1012,7 @@ // wouldn't get the state to recover. // mov r15=cr.ifa - ssm psr.ic | psr.dt + ssm psr.ic ;; srlz.i // guarantee that interrupt collection is enabled ;; @@ -1055,7 +1044,6 @@ // // Input: // psr.ic: off - // psr.dt: off // r19: fault vector number (e.g., 24 for General Exception) // r31: contains saved predicates (pr) // @@ -1071,7 +1059,7 @@ mov r10=cr.iim mov r11=cr.itir ;; - ssm psr.ic | psr.dt + ssm psr.ic ;; srlz.i // guarantee that interrupt collection is enabled ;; @@ -1145,9 +1133,7 @@ // 0x5400 Entry 24 (size 16 bundles) General Exception (5,32,34,36,38,39) mov r16=cr.isr mov r31=pr - rsm psr.dt // avoid nested faults due to TLB misses... ;; - srlz.d // ensure everyone knows psr.dt is off... cmp4.eq p6,p0=0,r16 (p6) br.sptk dispatch_illegal_op_fault ;; @@ -1157,7 +1143,7 @@ .align 256 ///////////////////////////////////////////////////////////////////////////////////////// // 0x5500 Entry 25 (size 16 bundles) Disabled FP-Register (35) - rsm psr.dt | psr.dfh // ensure we can access fph + rsm psr.dfh // ensure we can access fph ;; srlz.d mov r31=pr @@ -1218,11 +1204,9 @@ .align 256 ///////////////////////////////////////////////////////////////////////////////////////// // 0x5a00 Entry 30 (size 16 bundles) Unaligned Reference (57) - rsm psr.dt // avoid nested faults due to TLB misses... mov r16=cr.ipsr mov r31=pr // prepare to save predicates ;; - srlz.d // ensure everyone knows psr.dt is off br.cond.sptk.many dispatch_unaligned_handler .align 256 @@ -1304,9 +1288,6 @@ ///////////////////////////////////////////////////////////////////////////////////////// // 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept (30,31,59,70,71) #ifdef CONFIG_IA32_SUPPORT - rsm psr.dt - ;; - srlz.d mov r31=pr mov r16=cr.isr ;; @@ -1334,9 +1315,6 @@ ///////////////////////////////////////////////////////////////////////////////////////// // 0x6b00 Entry 47 (size 16 bundles) IA-32 Interrupt (74) #ifdef CONFIG_IA32_SUPPORT - rsm psr.dt - ;; - srlz.d mov r31=pr br.cond.sptk.many dispatch_to_ia32_handler #else diff -urN linux-2.4.0-test10/arch/ia64/kernel/machvec.c linux-2.4.0-test10-lia/arch/ia64/kernel/machvec.c --- linux-2.4.0-test10/arch/ia64/kernel/machvec.c Sun Aug 13 10:17:16 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/machvec.c Wed Nov 15 17:57:18 2000 @@ -1,10 +1,12 @@ #include + +#ifdef CONFIG_IA64_GENERIC + #include +#include #include #include - -#ifdef CONFIG_IA64_GENERIC struct ia64_machine_vector ia64_mv; diff -urN linux-2.4.0-test10/arch/ia64/kernel/mca.c linux-2.4.0-test10-lia/arch/ia64/kernel/mca.c --- linux-2.4.0-test10/arch/ia64/kernel/mca.c Mon Oct 9 17:54:54 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/mca.c Wed Nov 15 17:57:31 2000 @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -365,7 +366,7 @@ void ia64_mca_wakeup(int cpu) { - ipi_send(cpu, IA64_MCA_WAKEUP_INT_VECTOR, IA64_IPI_DM_INT, 0); + platform_send_ipi(cpu, IA64_MCA_WAKEUP_INT_VECTOR, IA64_IPI_DM_INT, 0); ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; } diff -urN linux-2.4.0-test10/arch/ia64/kernel/mca_asm.S linux-2.4.0-test10-lia/arch/ia64/kernel/mca_asm.S --- linux-2.4.0-test10/arch/ia64/kernel/mca_asm.S Fri Oct 13 12:05:29 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/mca_asm.S Wed Nov 15 17:57:45 2000 @@ -3,11 +3,10 @@ // // Mods by cfleck to integrate into kernel build // 00/03/15 davidm Added various stop bits to get a clean compile -// 00/03/29 cfleck Added code to save INIT handoff state in pt_regs format, switch to temp kstack, -// switch modes, jump to C INIT handler // -#include - +// 00/03/29 cfleck Added code to save INIT handoff state in pt_regs format, switch to temp +// kstack, switch modes, jump to C INIT handler +// #include #include #include @@ -17,14 +16,7 @@ * When we get an machine check, the kernel stack pointer is no longer * valid, so we need to set a new stack pointer. */ -#define MINSTATE_START_SAVE_MIN \ -(pKern) movl sp=ia64_init_stack+IA64_STK_OFFSET-IA64_PT_REGS_SIZE; \ - ;; - -#define MINSTATE_END_SAVE_MIN \ - or r12=r12,r14; /* make sp a kernel virtual address */ \ - or r13=r13,r14; /* make `current' a kernel virtual address */ \ - ;; +#define MINSTATE_PHYS /* Make sure stack access is physical for MINSTATE */ #include "minstate.h" diff -urN linux-2.4.0-test10/arch/ia64/kernel/minstate.h linux-2.4.0-test10-lia/arch/ia64/kernel/minstate.h --- linux-2.4.0-test10/arch/ia64/kernel/minstate.h Mon Oct 9 17:54:54 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/minstate.h Wed Nov 15 22:22:30 2000 @@ -20,6 +20,72 @@ #define rR1 r20 /* + * Here start the source dependent macros. + */ + +/* + * For ivt.s we want to access the stack virtually so we dont have to disable translation + * on interrupts. + */ +#define MINSTATE_START_SAVE_MIN_VIRT \ + dep r1=-1,r1,61,3; /* r1 = current (virtual) */ \ +(p7) mov ar.rsc=r0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \ + ;; \ +(p7) addl rKRBS=IA64_RBS_OFFSET,r1; /* compute base of RBS */ \ +(p7) mov rARRNAT=ar.rnat; \ +(pKern) mov r1=sp; /* get sp */ \ + ;; \ +(p7) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1; /* compute base of memory stack */ \ +(p7) mov rARBSPSTORE=ar.bspstore; /* save ar.bspstore */ \ + ;; \ +(pKern) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \ +(p7) mov ar.bspstore=rKRBS; /* switch to kernel RBS */ \ + ;; \ +(p7) mov r18=ar.bsp; \ +(p7) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \ + +#define MINSTATE_END_SAVE_MIN_VIRT \ + or r13=r13,r14; /* make `current' a kernel virtual address */ \ + bsw.1; /* switch back to bank 1 (must be last in insn group) */ \ + ;; + +/* + * For mca_asm.S we want to access the stack physically since the state is saved before we + * go virtual and dont want to destroy the iip or ipsr. + */ +#define MINSTATE_START_SAVE_MIN_PHYS \ +(pKern) movl sp=ia64_init_stack+IA64_STK_OFFSET-IA64_PT_REGS_SIZE; \ +(p7) mov ar.rsc=r0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \ +(p7) addl rKRBS=IA64_RBS_OFFSET,r1; /* compute base of register backing store */ \ + ;; \ +(p7) mov rARRNAT=ar.rnat; \ +(pKern) dep r1=0,sp,61,3; /* compute physical addr of sp */ \ +(p7) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1; /* compute base of memory stack */ \ +(p7) mov rARBSPSTORE=ar.bspstore; /* save ar.bspstore */ \ +(p7) dep rKRBS=-1,rKRBS,61,3; /* compute kernel virtual addr of RBS */\ + ;; \ +(pKern) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \ +(p7) mov ar.bspstore=rKRBS; /* switch to kernel RBS */ \ + ;; \ +(p7) mov r18=ar.bsp; \ +(p7) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \ + +#define MINSTATE_END_SAVE_MIN_PHYS \ + or r12=r12,r14; /* make sp a kernel virtual address */ \ + or r13=r13,r14; /* make `current' a kernel virtual address */ \ + ;; + +#ifdef MINSTATE_VIRT +# define MINSTATE_START_SAVE_MIN MINSTATE_START_SAVE_MIN_VIRT +# define MINSTATE_END_SAVE_MIN MINSTATE_END_SAVE_MIN_VIRT +#endif + +#ifdef MINSTATE_PHYS +# define MINSTATE_START_SAVE_MIN MINSTATE_START_SAVE_MIN_PHYS +# define MINSTATE_END_SAVE_MIN MINSTATE_END_SAVE_MIN_PHYS +#endif + +/* * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves * the minimum state necessary that allows us to turn psr.ic back * on. @@ -31,7 +97,6 @@ * * Upon exit, the state is as follows: * psr.ic: off - * psr.dt: off * r2 = points to &pt_regs.r16 * r12 = kernel sp (kernel virtual address) * r13 = points to current task_struct (kernel virtual address) @@ -50,7 +115,7 @@ mov rCRIPSR=cr.ipsr; \ mov rB6=b6; /* rB6 = branch reg 6 */ \ mov rCRIIP=cr.iip; \ - mov r1=ar.k6; /* r1 = current */ \ + mov r1=ar.k6; /* r1 = current (physical) */ \ ;; \ invala; \ extr.u r16=rCRIPSR,32,2; /* extract psr.cpl */ \ @@ -58,25 +123,11 @@ cmp.eq pKern,p7=r0,r16; /* are we in kernel mode already? (psr.cpl==0) */ \ /* switch from user to kernel RBS: */ \ COVER; \ - ;; \ - MINSTATE_START_SAVE_MIN \ -(p7) mov ar.rsc=r0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \ -(p7) addl rKRBS=IA64_RBS_OFFSET,r1; /* compute base of register backing store */ \ - ;; \ -(p7) mov rARRNAT=ar.rnat; \ -(pKern) dep r1=0,sp,61,3; /* compute physical addr of sp */ \ -(p7) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1; /* compute base of memory stack */ \ -(p7) mov rARBSPSTORE=ar.bspstore; /* save ar.bspstore */ \ -(p7) dep rKRBS=-1,rKRBS,61,3; /* compute kernel virtual addr of RBS */ \ ;; \ -(pKern) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \ -(p7) mov ar.bspstore=rKRBS; /* switch to kernel RBS */ \ + MINSTATE_START_SAVE_MIN \ ;; \ -(p7) mov r18=ar.bsp; \ -(p7) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \ - \ - mov r16=r1; /* initialize first base pointer */ \ - adds r17=8,r1; /* initialize second base pointer */ \ + mov r16=r1; /* initialize first base pointer */ \ + adds r17=8,r1; /* initialize second base pointer */ \ ;; \ st8 [r16]=rCRIPSR,16; /* save cr.ipsr */ \ st8 [r17]=rCRIIP,16; /* save cr.iip */ \ diff -urN linux-2.4.0-test10/arch/ia64/kernel/pal.S linux-2.4.0-test10-lia/arch/ia64/kernel/pal.S --- linux-2.4.0-test10/arch/ia64/kernel/pal.S Mon Oct 9 17:54:54 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/pal.S Wed Nov 15 17:58:01 2000 @@ -52,10 +52,9 @@ /* * Make a PAL call using the static calling convention. * - * in0 Pointer to struct ia64_pal_retval - * in1 Index of PAL service - * in2 - in4 Remaining PAL arguments - * in5 1 ==> clear psr.ic, 0 ==> don't clear psr.ic + * in0 Index of PAL service + * in1 - in3 Remaining PAL arguments + * in4 1 ==> clear psr.ic, 0 ==> don't clear psr.ic * */ GLOBAL_ENTRY(ia64_pal_call_static) @@ -69,7 +68,7 @@ } ;; ld8 loc2 = [loc2] // loc2 <- entry point - tbit.nz p6,p7 = in5, 0 + tbit.nz p6,p7 = in4, 0 adds r8 = 1f-1b,r8 ;; mov loc3 = psr diff -urN linux-2.4.0-test10/arch/ia64/kernel/palinfo.c linux-2.4.0-test10-lia/arch/ia64/kernel/palinfo.c --- linux-2.4.0-test10/arch/ia64/kernel/palinfo.c Fri Oct 13 12:05:29 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/palinfo.c Mon Oct 30 22:17:11 2000 @@ -16,7 +16,6 @@ * - as of 2.2.9/2.2.12, the following values are still wrong * PAL_VM_SUMMARY: key & rid sizes */ -#include #include #include #include diff -urN linux-2.4.0-test10/arch/ia64/kernel/pci-dma.c linux-2.4.0-test10-lia/arch/ia64/kernel/pci-dma.c --- linux-2.4.0-test10/arch/ia64/kernel/pci-dma.c Mon Oct 9 17:54:54 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/pci-dma.c Wed Nov 1 23:13:06 2000 @@ -125,12 +125,16 @@ BUG(); /* - * Find suitable number of IO TLB entries size that will fit this request and allocate a buffer - * from that IO TLB pool. + * Find suitable number of IO TLB entries size that will fit this request and + * allocate a buffer from that IO TLB pool. */ spin_lock_irqsave(&io_tlb_lock, flags); { wrap = index = ALIGN(io_tlb_index, stride); + + if (index >= io_tlb_nslabs) + index = 0; + do { /* * If we find a slot that indicates we have 'nslots' number of diff -urN linux-2.4.0-test10/arch/ia64/kernel/pci.c linux-2.4.0-test10-lia/arch/ia64/kernel/pci.c --- linux-2.4.0-test10/arch/ia64/kernel/pci.c Mon Aug 7 14:31:40 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/pci.c Wed Nov 15 17:58:20 2000 @@ -1,10 +1,8 @@ /* - * pci.c - Low-Level PCI Access in IA64 + * pci.c - Low-Level PCI Access in IA-64 * * Derived from bios32.c of i386 tree. - * */ - #include #include @@ -44,19 +42,16 @@ * This interrupt-safe spinlock protects all accesses to PCI * configuration space. */ - spinlock_t pci_lock = SPIN_LOCK_UNLOCKED; -struct pci_fixup pcibios_fixups[] = { { 0 } }; - -#define PCI_NO_CHECKS 0x400 -#define PCI_NO_PEER_FIXUP 0x800 - -static unsigned int pci_probe = PCI_NO_CHECKS; +struct pci_fixup pcibios_fixups[] = { + { 0 } +}; /* Macro to build a PCI configuration address to be passed as a parameter to SAL. */ -#define PCI_CONFIG_ADDRESS(dev, where) (((u64) dev->bus->number << 16) | ((u64) (dev->devfn & 0xff) << 8) | (where & 0xff)) +#define PCI_CONFIG_ADDRESS(dev, where) \ + (((u64) dev->bus->number << 16) | ((u64) (dev->devfn & 0xff) << 8) | (where & 0xff)) static int pci_conf_read_config_byte(struct pci_dev *dev, int where, u8 *value) @@ -109,8 +104,7 @@ return ia64_sal_pci_config_write(PCI_CONFIG_ADDRESS(dev, where), 4, value); } - -static struct pci_ops pci_conf = { +struct pci_ops pci_conf = { pci_conf_read_config_byte, pci_conf_read_config_word, pci_conf_read_config_dword, @@ -120,35 +114,17 @@ }; /* - * Try to find PCI BIOS. This will always work for IA64. - */ - -static struct pci_ops * __init -pci_find_bios(void) -{ - return &pci_conf; -} - -/* * Initialization. Uses the SAL interface */ - -#define PCI_BUSES_TO_SCAN 255 - void __init -pcibios_init(void) +pcibios_init (void) { - struct pci_ops *ops = NULL; +# define PCI_BUSES_TO_SCAN 255 int i; - if ((ops = pci_find_bios()) == NULL) { - printk("PCI: No PCI bus detected\n"); - return; - } - printk("PCI: Probing PCI hardware\n"); for (i = 0; i < PCI_BUSES_TO_SCAN; i++) - pci_scan_bus(i, ops, NULL); + pci_scan_bus(i, &pci_conf, NULL); platform_pci_fixup(); return; } @@ -157,16 +133,15 @@ * Called after each bus is probed, but before its children * are examined. */ - void __init -pcibios_fixup_bus(struct pci_bus *b) +pcibios_fixup_bus (struct pci_bus *b) { return; } void __init -pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) +pcibios_update_resource (struct pci_dev *dev, struct resource *root, + struct resource *res, int resource) { unsigned long where, size; u32 reg; @@ -181,7 +156,7 @@ } void __init -pcibios_update_irq(struct pci_dev *dev, int irq) +pcibios_update_irq (struct pci_dev *dev, int irq) { pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); @@ -204,18 +179,16 @@ return 0; } +void +pcibios_align_resource (void *data, struct resource *res, unsigned long size) +{ +} + /* * PCI BIOS setup, always defaults to SAL interface */ - char * __init -pcibios_setup(char *str) +pcibios_setup (char *str) { - pci_probe = PCI_NO_CHECKS; return NULL; -} - -void -pcibios_align_resource (void *data, struct resource *res, unsigned long size) -{ } diff -urN linux-2.4.0-test10/arch/ia64/kernel/perfmon.c linux-2.4.0-test10-lia/arch/ia64/kernel/perfmon.c --- linux-2.4.0-test10/arch/ia64/kernel/perfmon.c Mon Oct 9 17:54:54 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/perfmon.c Mon Oct 30 22:37:23 2000 @@ -4,18 +4,20 @@ * * Originaly Written by Ganesh Venkitachalam, IBM Corp. * Modifications by David Mosberger-Tang, Hewlett-Packard Co. + * Modifications by Stephane Eranian, Hewlett-Packard Co. * Copyright (C) 1999 Ganesh Venkitachalam * Copyright (C) 1999 David Mosberger-Tang + * Copyright (C) 2000 Stephane Eranian */ #include + #include #include #include #include #include #include -#include #include #include @@ -58,19 +60,51 @@ #define MAX_PERF_COUNTER 4 /* true for Itanium, at least */ #define PMU_FIRST_COUNTER 4 /* first generic counter */ -#define WRITE_PMCS_AND_START 0xa0 -#define WRITE_PMCS 0xa1 -#define READ_PMDS 0xa2 -#define STOP_PMCS 0xa3 +#define PFM_WRITE_PMCS 0xa0 +#define PFM_WRITE_PMDS 0xa1 +#define PFM_READ_PMDS 0xa2 +#define PFM_STOP 0xa3 +#define PFM_START 0xa4 +#define PFM_ENABLE 0xa5 /* unfreeze only */ +#define PFM_DISABLE 0xa6 /* freeze only */ +/* + * Those 2 are just meant for debugging. I considered using sysctl() for + * that but it is a little bit too pervasive. This solution is at least + * self-contained. + */ +#define PFM_DEBUG_ON 0xe0 +#define PFM_DEBUG_OFF 0xe1 + +#ifdef CONFIG_SMP +#define cpu_is_online(i) (cpu_online_map & (1UL << i)) +#else +#define cpu_is_online(i) 1 +#endif +#define PMC_IS_IMPL(i) (pmu_conf.impl_regs[i>>6] & (1<< (i&~(64-1)))) +#define PMD_IS_IMPL(i) (pmu_conf.impl_regs[4+(i>>6)] & (1<< (i&~(64-1)))) +#define PMD_IS_COUNTER(i) (i>=PMU_FIRST_COUNTER && i < (PMU_FIRST_COUNTER+pmu_conf.max_counters)) +#define PMC_IS_COUNTER(i) (i>=PMU_FIRST_COUNTER && i < (PMU_FIRST_COUNTER+pmu_conf.max_counters)) /* * this structure needs to be enhanced */ typedef struct { + unsigned long pfr_reg_num; /* which register */ + unsigned long pfr_reg_value; /* configuration (PMC) or initial value (PMD) */ + unsigned long pfr_reg_reset; /* reset value on overflow (PMD) */ + void *pfr_smpl_buf; /* pointer to user buffer for EAR/BTB */ + unsigned long pfr_smpl_size; /* size of user buffer for EAR/BTB */ + pid_t pfr_notify_pid; /* process to notify */ + int pfr_notify_sig; /* signal for notification, 0=no notification */ +} perfmon_req_t; + +#if 0 +typedef struct { unsigned long pmu_reg_data; /* generic PMD register */ unsigned long pmu_reg_num; /* which register number */ } perfmon_reg_t; +#endif /* * This structure is initialize at boot time and contains @@ -78,86 +112,141 @@ * by PAL */ typedef struct { - unsigned long perf_ovfl_val; /* overflow value for generic counters */ - unsigned long max_pmc; /* highest PMC */ - unsigned long max_pmd; /* highest PMD */ - unsigned long max_counters; /* number of generic counter pairs (PMC/PMD) */ + unsigned long perf_ovfl_val; /* overflow value for generic counters */ + unsigned long max_counters; /* upper limit on counter pair (PMC/PMD) */ + unsigned long impl_regs[16]; /* buffer used to hold implememted PMC/PMD mask */ } pmu_config_t; -/* XXX will go static when ptrace() is cleaned */ -unsigned long perf_ovfl_val; /* overflow value for generic counters */ - static pmu_config_t pmu_conf; +/* for debug only */ +static unsigned long pfm_debug=1; /* 0= nodebug, >0= debug output on */ +#define DBprintk(a) {\ + if (pfm_debug >0) { printk a; } \ +} + /* - * could optimize to avoid cache conflicts in SMP + * could optimize to avoid cache line conflicts in SMP */ -unsigned long pmds[NR_CPUS][MAX_PERF_COUNTER]; +static struct task_struct *pmu_owners[NR_CPUS]; -asmlinkage unsigned long -sys_perfmonctl (int cmd, int count, void *ptr, long arg4, long arg5, long arg6, long arg7, long arg8, long stack) +static int +do_perfmonctl (struct task_struct *task, int cmd, int flags, perfmon_req_t *req, int count, struct pt_regs *regs) { - struct pt_regs *regs = (struct pt_regs *) &stack; - perfmon_reg_t tmp, *cptr = ptr; - unsigned long cnum; + perfmon_req_t tmp; int i; switch (cmd) { - case WRITE_PMCS: /* Writes to PMC's and clears PMDs */ - case WRITE_PMCS_AND_START: /* Also starts counting */ + case PFM_WRITE_PMCS: + /* we don't quite support this right now */ + if (task != current) return -EINVAL; + + if (!access_ok(VERIFY_READ, req, sizeof(struct perfmon_req_t)*count)) return -EFAULT; + + for (i = 0; i < count; i++, req++) { + copy_from_user(&tmp, req, sizeof(tmp)); + + /* XXX needs to check validity of the data maybe */ + + if (!PMC_IS_IMPL(tmp.pfr_reg_num)) { + DBprintk((__FUNCTION__ " invalid pmc[%ld]\n", tmp.pfr_reg_num)); + return -EINVAL; + } + + /* XXX: for counters, need to some checks */ + if (PMC_IS_COUNTER(tmp.pfr_reg_num)) { + current->thread.pmu_counters[tmp.pfr_reg_num - PMU_FIRST_COUNTER].sig = tmp.pfr_notify_sig; + current->thread.pmu_counters[tmp.pfr_reg_num - PMU_FIRST_COUNTER].pid = tmp.pfr_notify_pid; + + DBprintk((__FUNCTION__" setting PMC[%ld] send sig %d to %d\n",tmp.pfr_reg_num, tmp.pfr_notify_sig, tmp.pfr_notify_pid)); + } + ia64_set_pmc(tmp.pfr_reg_num, tmp.pfr_reg_value); + + DBprintk((__FUNCTION__" setting PMC[%ld]=0x%lx\n", tmp.pfr_reg_num, tmp.pfr_reg_value)); + } + /* + * we have to set this here event hough we haven't necessarily started monitoring + * because we may be context switched out + */ + current->thread.flags |= IA64_THREAD_PM_VALID; + break; + + case PFM_WRITE_PMDS: + /* we don't quite support this right now */ + if (task != current) return -EINVAL; + + if (!access_ok(VERIFY_READ, req, sizeof(struct perfmon_req_t)*count)) return -EFAULT; + + for (i = 0; i < count; i++, req++) { + copy_from_user(&tmp, req, sizeof(tmp)); + + if (!PMD_IS_IMPL(tmp.pfr_reg_num)) return -EINVAL; + + /* update virtualized (64bits) counter */ + if (PMD_IS_COUNTER(tmp.pfr_reg_num)) { + current->thread.pmu_counters[tmp.pfr_reg_num - PMU_FIRST_COUNTER].val = tmp.pfr_reg_value & ~pmu_conf.perf_ovfl_val; + current->thread.pmu_counters[tmp.pfr_reg_num - PMU_FIRST_COUNTER].rval = tmp.pfr_reg_reset; + } + /* writes to unimplemented part is ignored, so this is safe */ + ia64_set_pmd(tmp.pfr_reg_num, tmp.pfr_reg_value); + /* to go away */ + ia64_srlz_d(); + DBprintk((__FUNCTION__" setting PMD[%ld]: pmod.val=0x%lx pmd=0x%lx rval=0x%lx\n", tmp.pfr_reg_num, current->thread.pmu_counters[tmp.pfr_reg_num - PMU_FIRST_COUNTER].val, ia64_get_pmd(tmp.pfr_reg_num),current->thread.pmu_counters[tmp.pfr_reg_num - PMU_FIRST_COUNTER].rval)); + } + /* + * we have to set this here event hough we haven't necessarily started monitoring + * because we may be context switched out + */ + current->thread.flags |= IA64_THREAD_PM_VALID; + break; + + case PFM_START: + /* we don't quite support this right now */ + if (task != current) return -EINVAL; - if (!access_ok(VERIFY_READ, cptr, sizeof(struct perfmon_reg_t)*count)) - return -EFAULT; + pmu_owners[smp_processor_id()] = current; - for (i = 0; i < count; i++, cptr++) { + /* will start monitoring right after rfi */ + ia64_psr(regs)->up = 1; - copy_from_user(&tmp, cptr, sizeof(tmp)); + /* + * mark the state as valid. + * this will trigger save/restore at context switch + */ + current->thread.flags |= IA64_THREAD_PM_VALID; - /* XXX need to check validity of pmu_reg_num and perhaps data!! */ + ia64_set_pmc(0, 0); - if (tmp.pmu_reg_num > pmu_conf.max_pmc || tmp.pmu_reg_num == 0) return -EFAULT; + break; - ia64_set_pmc(tmp.pmu_reg_num, tmp.pmu_reg_data); + case PFM_ENABLE: + /* we don't quite support this right now */ + if (task != current) return -EINVAL; - /* to go away */ - if (tmp.pmu_reg_num >= PMU_FIRST_COUNTER && tmp.pmu_reg_num < PMU_FIRST_COUNTER+pmu_conf.max_counters) { - ia64_set_pmd(tmp.pmu_reg_num, 0); - pmds[smp_processor_id()][tmp.pmu_reg_num - PMU_FIRST_COUNTER] = 0; + pmu_owners[smp_processor_id()] = current; - printk(__FUNCTION__" setting PMC/PMD[%ld] es=0x%lx pmd[%ld]=%lx\n", tmp.pmu_reg_num, (tmp.pmu_reg_data>>8) & 0x7f, tmp.pmu_reg_num, ia64_get_pmd(tmp.pmu_reg_num)); - } else - printk(__FUNCTION__" setting PMC[%ld]=0x%lx\n", tmp.pmu_reg_num, tmp.pmu_reg_data); - } - - if (cmd == WRITE_PMCS_AND_START) { -#if 0 -/* irrelevant with user monitors */ - local_irq_save(flags); - - dcr = ia64_get_dcr(); - dcr |= IA64_DCR_PP; - ia64_set_dcr(dcr); - - local_irq_restore(flags); -#endif + /* + * mark the state as valid. + * this will trigger save/restore at context switch + */ + current->thread.flags |= IA64_THREAD_PM_VALID; + /* simply unfreeze */ ia64_set_pmc(0, 0); + break; - /* will start monitoring right after rfi */ - ia64_psr(regs)->up = 1; - } - /* - * mark the state as valid. - * this will trigger save/restore at context switch - */ - current->thread.flags |= IA64_THREAD_PM_VALID; - break; - - case READ_PMDS: - if (count <= 0 || count > MAX_PERF_COUNTER) - return -EINVAL; - if (!access_ok(VERIFY_WRITE, cptr, sizeof(struct perfmon_reg_t)*count)) - return -EFAULT; + case PFM_DISABLE: + /* we don't quite support this right now */ + if (task != current) return -EINVAL; + + /* simply unfreeze */ + ia64_set_pmc(0, 1); + ia64_srlz_d(); + break; + + case PFM_READ_PMDS: + if (!access_ok(VERIFY_READ, req, sizeof(struct perfmon_req_t)*count)) return -EFAULT; + if (!access_ok(VERIFY_WRITE, req, sizeof(struct perfmon_req_t)*count)) return -EFAULT; /* This looks shady, but IMHO this will work fine. This is * the sequence that I could come up with to avoid races @@ -187,16 +276,31 @@ * is the irq_save/restore needed? */ + for (i = 0; i < count; i++, req++) { + unsigned long val=0; - /* XXX: This needs to change to read more than just the counters */ - for (i = 0, cnum = PMU_FIRST_COUNTER;i < count; i++, cnum++, cptr++) { + copy_from_user(&tmp, req, sizeof(tmp)); - tmp.pmu_reg_data = (pmds[smp_processor_id()][i] - + (ia64_get_pmd(cnum) & pmu_conf.perf_ovfl_val)); + if (!PMD_IS_IMPL(tmp.pfr_reg_num)) return -EINVAL; - tmp.pmu_reg_num = cnum; + if (PMD_IS_COUNTER(tmp.pfr_reg_num)) { + if (task == current){ + val = ia64_get_pmd(tmp.pfr_reg_num) & pmu_conf.perf_ovfl_val; + } else { + val = task->thread.pmd[tmp.pfr_reg_num - PMU_FIRST_COUNTER] & pmu_conf.perf_ovfl_val; + } + val += task->thread.pmu_counters[tmp.pfr_reg_num - PMU_FIRST_COUNTER].val; + } else { + /* for now */ + if (task != current) return -EINVAL; + + val = ia64_get_pmd(tmp.pfr_reg_num); + } + tmp.pfr_reg_value = val; - if (copy_to_user(cptr, &tmp, sizeof(tmp))) return -EFAULT; +DBprintk((__FUNCTION__" reading PMD[%ld]=0x%lx\n", tmp.pfr_reg_num, val)); + + if (copy_to_user(req, &tmp, sizeof(tmp))) return -EFAULT; } #if 0 /* irrelevant with user monitors */ @@ -209,11 +313,18 @@ #endif break; - case STOP_PMCS: + case PFM_STOP: + /* we don't quite support this right now */ + if (task != current) return -EINVAL; + ia64_set_pmc(0, 1); ia64_srlz_d(); - for (i = 0; i < MAX_PERF_COUNTER; ++i) - ia64_set_pmc(4+i, 0); + + ia64_psr(regs)->up = 0; + + current->thread.flags &= ~IA64_THREAD_PM_VALID; + + pmu_owners[smp_processor_id()] = NULL; #if 0 /* irrelevant with user monitors */ @@ -225,48 +336,140 @@ ia64_psr(regs)->up = 0; #endif - current->thread.flags &= ~(IA64_THREAD_PM_VALID); - break; + case PFM_DEBUG_ON: + printk(__FUNCTION__" debuggin on\n"); + pfm_debug = 1; + break; + + case PFM_DEBUG_OFF: + printk(__FUNCTION__" debuggin off\n"); + pfm_debug = 0; + break; + default: + DBprintk((__FUNCTION__" UNknown command 0x%x\n", cmd)); return -EINVAL; break; } return 0; } -static inline void -update_counters (void) +asmlinkage int +sys_perfmonctl (int pid, int cmd, int flags, perfmon_req_t *req, int count, long arg6, long arg7, long arg8, long stack) { - unsigned long mask, i, cnum, val; + struct pt_regs *regs = (struct pt_regs *) &stack; + struct task_struct *child = current; + int ret; - mask = ia64_get_pmc(0) >> 4; - for (i = 0, cnum = PMU_FIRST_COUNTER ; i < pmu_conf.max_counters; cnum++, i++, mask >>= 1) { + if (pid != current->pid) { + read_lock(&tasklist_lock); + { + child = find_task_by_pid(pid); + if (child) + get_task_struct(child); + } + if (!child) { + read_unlock(&tasklist_lock); + return -ESRCH; + } + /* + * XXX: need to do more checking here + */ + if (child->state != TASK_ZOMBIE) { + DBprintk((__FUNCTION__" warning process %d not in stable state %ld\n", pid, child->state)); + } + } + ret = do_perfmonctl(child, cmd, flags, req, count, regs); + if (child != current) read_unlock(&tasklist_lock); - val = mask & 0x1 ? pmu_conf.perf_ovfl_val + 1 : 0; + return ret; +} - if (mask & 0x1) - printk(__FUNCTION__ " PMD%ld overflowed pmd=%lx pmod=%lx\n", cnum, ia64_get_pmd(cnum), pmds[smp_processor_id()][i]); - /* since we got an interrupt, might as well clear every pmd. */ - val += ia64_get_pmd(cnum) & pmu_conf.perf_ovfl_val; +static inline int +update_counters (u64 pmc0) +{ + unsigned long mask, i, cnum; + struct thread_struct *th; + struct task_struct *ta; + + if (pmu_owners[smp_processor_id()] == NULL) { + DBprintk((__FUNCTION__" Spurious overflow interrupt: PMU not owned\n")); + return 0; + } + + /* + * It is never safe to access the task for which the overflow interrupt is destinated + * using the current variable as the interrupt may occur in the middle of a context switch + * where current does not hold the task that is running yet. + * + * For monitoring, however, we do need to get access to the task which caused the overflow + * to account for overflow on the counters. + * We accomplish this by maintaining a current owner of the PMU per CPU. During context + * switch the ownership is changed in a way such that the reflected owner is always the + * valid one, i.e. the one that caused the interrupt. + */ + ta = pmu_owners[smp_processor_id()]; + th = &pmu_owners[smp_processor_id()]->thread; - printk(__FUNCTION__ " adding val=%lx to pmod[%ld]=%lx \n", val, i, pmds[smp_processor_id()][i]); + /* + * Don't think this could happen given first test. Keep as sanity check + */ + if ((th->flags & IA64_THREAD_PM_VALID) == 0) { + DBprintk((__FUNCTION__" Spurious overflow interrupt: process %d not using perfmon\n", ta->pid)); + return 0; + } + + /* + * if PMU not frozen: spurious from previous context + * if PMC[0] = 0x1 : frozen but no overflow reported: leftover from previous context + * + * in either case we don't touch the state upon return from handler + */ + if ((pmc0 & 0x1) == 0 || pmc0 == 0x1) { + DBprintk((__FUNCTION__" Spurious overflow interrupt: process %d freeze=0\n",ta->pid)); + return 0; + } - pmds[smp_processor_id()][i] += val; + mask = pmc0 >> 4; - ia64_set_pmd(cnum, 0); + for (i = 0, cnum = PMU_FIRST_COUNTER; i < pmu_conf.max_counters; cnum++, i++, mask >>= 1) { + + if (mask & 0x1) { + DBprintk((__FUNCTION__ " PMD[%ld] overflowed pmd=0x%lx pmod.val=0x%lx\n", cnum, ia64_get_pmd(cnum), th->pmu_counters[i].val)); + + /* + * Because we somtimes (EARS/BTB) reset to a specific value, we cannot simply use + * val to count the number of times we overflowed. Otherwise we would loose the value + * current in the PMD (which can be >0). So to make sure we don't loose + * the residual counts we set val to contain full 64bits value of the counter. + */ + th->pmu_counters[i].val += 1+pmu_conf.perf_ovfl_val+(ia64_get_pmd(cnum) &pmu_conf.perf_ovfl_val); + + /* writes to upper part are ignored, so this is safe */ + ia64_set_pmd(cnum, th->pmu_counters[i].rval); + + DBprintk((__FUNCTION__ " pmod[%ld].val=0x%lx pmd=0x%lx\n", i, th->pmu_counters[i].val, ia64_get_pmd(cnum)&pmu_conf.perf_ovfl_val)); + + if (th->pmu_counters[i].pid != 0 && th->pmu_counters[i].sig>0) { + DBprintk((__FUNCTION__ " shouild notify process %d with signal %d\n",th->pmu_counters[i].pid, th->pmu_counters[i].sig)); + } + } } + return 1; } static void perfmon_interrupt (int irq, void *arg, struct pt_regs *regs) { - update_counters(); - ia64_set_pmc(0, 0); - ia64_srlz_d(); + /* unfreeze if not spurious */ + if ( update_counters(ia64_get_pmc(0)) ) { + ia64_set_pmc(0, 0); + ia64_srlz_d(); + } } static struct irqaction perfmon_irqaction = { @@ -280,9 +483,13 @@ { char *p = page; u64 pmc0 = ia64_get_pmc(0); + int i; - p += sprintf(p, "PMC[0]=%lx\n", pmc0); - + p += sprintf(p, "PMC[0]=%lx\nPerfmon debug: %s\n", pmc0, pfm_debug ? "On" : "Off"); + for(i=0; i < NR_CPUS; i++) { + if (cpu_is_online(i)) + p += sprintf(p, "CPU%d.PMU %d\n", i, pmu_owners[i] ? pmu_owners[i]->pid: -1); + } return p - page; } @@ -308,7 +515,6 @@ perfmon_init (void) { pal_perf_mon_info_u_t pm_info; - u64 pm_buffer[16]; s64 status; irq_desc[PERFMON_IRQ].status |= IRQ_PER_CPU; @@ -320,15 +526,13 @@ printk("perfmon: Initialized vector to %u\n",PERFMON_IRQ); - if ((status=ia64_pal_perf_mon_info(pm_buffer, &pm_info)) != 0) { + if ((status=ia64_pal_perf_mon_info(pmu_conf.impl_regs, &pm_info)) != 0) { printk(__FUNCTION__ " pal call failed (%ld)\n", status); return; } - pmu_conf.perf_ovfl_val = perf_ovfl_val = (1L << pm_info.pal_perf_mon_info_s.width) - 1; + pmu_conf.perf_ovfl_val = (1L << pm_info.pal_perf_mon_info_s.width) - 1; /* XXX need to use PAL instead */ - pmu_conf.max_pmc = 13; - pmu_conf.max_pmd = 17; pmu_conf.max_counters = pm_info.pal_perf_mon_info_s.generic; printk("perfmon: Counters are %d bits\n", pm_info.pal_perf_mon_info_s.width); @@ -347,36 +551,137 @@ ia64_srlz_d(); } +/* + * XXX: for system wide this function MUST never be called + */ void -ia64_save_pm_regs (struct thread_struct *t) +ia64_save_pm_regs (struct task_struct *ta) { - int i; + struct thread_struct *t = &ta->thread; + u64 pmc0, psr; + int i,j; + + /* + * We must maek sure that we don't loose any potential overflow + * interrupt while saving PMU context. In this code, external + * interrupts are always enabled. + */ + + /* + * save current PSR: needed because we modify it + */ + __asm__ __volatile__ ("mov %0=psr;;": "=r"(psr) :: "memory"); + + /* + * stop monitoring: + * This is the only way to stop monitoring without destroying overflow + * information in PMC[0..3]. + * This is the last instruction which can cause overflow when monitoring + * in kernel. + * By now, we could still have an overflow interrupt in flight. + */ + __asm__ __volatile__ ("rsm psr.up;;"::: "memory"); + + /* + * read current overflow status: + * + * We may be reading stale information at this point, if we got interrupt + * just before the read(pmc0) but that's all right. However, if we did + * not get the interrupt before, this read reflects LAST state. + * + */ + pmc0 = ia64_get_pmc(0); + /* + * freeze PMU: + * + * This destroys the overflow information. This is required to make sure + * next process does not start with monitoring on if not requested + * (PSR.up may not be enough). + * + * We could still get an overflow interrupt by now. However the handler + * will not do anything if is sees PMC[0].fr=1 but no overflow bits + * are set. So PMU will stay in frozen state. This implies that pmc0 + * will still be holding the correct unprocessed information. + * + */ ia64_set_pmc(0, 1); ia64_srlz_d(); + + /* + * check for overflow bits set: + * + * If pmc0 reports PMU frozen, this means we have a pending overflow, + * therefore we invoke the handler. Handler is reentrant with regards + * to PMC[0] so it is safe to call it twice. + * + * IF pmc0 reports overflow, we need to reread current PMC[0] value + * in case the handler was invoked right after the first pmc0 read. + * it is was not invoked then pmc0==PMC[0], otherwise it's been invoked + * and overflow information has been processed, so we don't need to call. + * + * Test breakdown: + * - pmc0 & ~0x1: test if overflow happened + * - second part: check if current register reflects this as well. + * + * NOTE: testing for pmc0 & 0x1 is not enough has it would trigger call + * when PM_VALID and PMU.fr which is common when setting up registers + * just before actually starting monitors. + * + */ + if ((pmc0 & ~0x1) && ((pmc0=ia64_get_pmc(0)) &~0x1) ) { + printk(__FUNCTION__" Warning: pmc[0]=0x%lx\n", pmc0); + update_counters(pmc0); + /* + * XXX: not sure that's enough. the next task may still get the + * interrupt. + */ + } + + /* + * restore PSR for context switch to save + */ + __asm__ __volatile__ ("mov psr.l=%0;;"::"r"(psr): "memory"); + /* * XXX: this will need to be extended beyong just counters */ - for (i=0; i< IA64_NUM_PM_REGS; i++) { - t->pmd[i] = ia64_get_pmd(4+i); - t->pmod[i] = pmds[smp_processor_id()][i]; - t->pmc[i] = ia64_get_pmc(4+i); + for (i=0,j=4; i< IA64_NUM_PMD_COUNTERS; i++,j++) { + t->pmd[i] = ia64_get_pmd(j); + t->pmc[i] = ia64_get_pmc(j); } + /* + * PMU is frozen, PMU context is saved: nobody owns the PMU on this CPU + * At this point, we should not receive any pending interrupt from the + * 'switched out' task + */ + pmu_owners[smp_processor_id()] = NULL; } void -ia64_load_pm_regs (struct thread_struct *t) +ia64_load_pm_regs (struct task_struct *ta) { - int i; + struct thread_struct *t = &ta->thread; + int i,j; + + /* + * we first restore ownership of the PMU to the 'soon to be current' + * context. This way, if, as soon as we unfreeze the PMU at the end + * of this function, we get an interrupt, we attribute it to the correct + * task + */ + pmu_owners[smp_processor_id()] = ta; /* * XXX: this will need to be extended beyong just counters */ - for (i=0; i< IA64_NUM_PM_REGS ; i++) { - ia64_set_pmd(4+i, t->pmd[i]); - pmds[smp_processor_id()][i] = t->pmod[i]; - ia64_set_pmc(4+i, t->pmc[i]); + for (i=0,j=4; i< IA64_NUM_PMD_COUNTERS; i++,j++) { + ia64_set_pmd(j, t->pmd[i]); + ia64_set_pmc(j, t->pmc[i]); } + /* + * unfreeze PMU + */ ia64_set_pmc(0, 0); ia64_srlz_d(); } diff -urN linux-2.4.0-test10/arch/ia64/kernel/process.c linux-2.4.0-test10-lia/arch/ia64/kernel/process.c --- linux-2.4.0-test10/arch/ia64/kernel/process.c Mon Oct 9 17:54:54 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/process.c Mon Oct 30 22:38:03 2000 @@ -164,7 +164,7 @@ ia64_save_debug_regs(&task->thread.dbr[0]); #ifdef CONFIG_PERFMON if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0) - ia64_save_pm_regs(&task->thread); + ia64_save_pm_regs(task); #endif if (IS_IA32_PROCESS(ia64_task_regs(task))) ia32_save_state(&task->thread); @@ -177,7 +177,7 @@ ia64_load_debug_regs(&task->thread.dbr[0]); #ifdef CONFIG_PERFMON if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0) - ia64_load_pm_regs(&task->thread); + ia64_load_pm_regs(task); #endif if (IS_IA32_PROCESS(ia64_task_regs(task))) ia32_load_state(&task->thread); @@ -299,6 +299,14 @@ # define THREAD_FLAGS_TO_SET 0 p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR) | THREAD_FLAGS_TO_SET); +#ifdef CONFIG_IA32_SUPPORT + /* + * If we're cloning an IA32 task then save the IA32 extra + * state from the current task to the new task + */ + if (IS_IA32_PROCESS(ia64_task_regs(current))) + ia32_save_state(&p->thread); +#endif return 0; } @@ -554,7 +562,7 @@ * we garantee no race. this call we also stop * monitoring */ - ia64_save_pm_regs(¤t->thread); + ia64_save_pm_regs(current); /* * make sure that switch_to() will not save context again */ diff -urN linux-2.4.0-test10/arch/ia64/kernel/ptrace.c linux-2.4.0-test10-lia/arch/ia64/kernel/ptrace.c --- linux-2.4.0-test10/arch/ia64/kernel/ptrace.c Mon Oct 9 17:54:54 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/ptrace.c Wed Nov 15 17:58:36 2000 @@ -617,7 +617,6 @@ struct switch_stack *sw; struct unw_frame_info info; struct pt_regs *pt; - unsigned long pmd_tmp; pt = ia64_task_regs(child); sw = (struct switch_stack *) (child->thread.ksp + 16); @@ -794,11 +793,7 @@ addr); return -1; } - } else -#ifdef CONFIG_PERFMON - if (addr < PT_PMD) -#endif - { + } else { /* access debug registers */ if (!(child->thread.flags & IA64_THREAD_DBG_VALID)) { @@ -820,33 +815,14 @@ } ptr += regnum; - } -#ifdef CONFIG_PERFMON - else { - /* - * XXX: will eventually move back to perfmonctl() - */ - unsigned long pmd = (addr - PT_PMD) >> 3; - extern unsigned long perf_ovfl_val; - - /* we just use ptrace to read */ - if (write_access) return -1; - - if (pmd > 3) { - printk("ptrace: rejecting access to PMD[%ld] address 0x%lx\n", pmd, addr); - return -1; - } - /* - * We always need to mask upper 32bits of pmd because value is random - */ - pmd_tmp = child->thread.pmod[pmd]+(child->thread.pmd[pmd]& perf_ovfl_val); - - /*printk(__FUNCTION__" child=%d reading pmd[%ld]=%lx\n", child->pid, pmd, pmd_tmp);*/ - - ptr = &pmd_tmp; + if (write_access) + /* don't let the user set kernel-level breakpoints... */ + *ptr = *data & ~(7UL << 56); + else + *data = *ptr; + return 0; } -#endif if (write_access) *ptr = *data; else @@ -861,7 +837,6 @@ { unsigned long *ptr = NULL, *rbs, *bspstore, ndirty, regnum; struct switch_stack *sw; - unsigned long pmd_tmp; struct pt_regs *pt; if ((addr & 0x7) != 0) @@ -977,11 +952,7 @@ /* disallow accessing anything else... */ return -1; } - } else -#ifdef CONFIG_PERFMON - if (addr < PT_PMD) -#endif - { + } else { /* access debug registers */ @@ -1002,34 +973,14 @@ return -1; ptr += regnum; - } -#ifdef CONFIG_PERFMON - else { - /* - * XXX: will eventually move back to perfmonctl() - */ - unsigned long pmd = (addr - PT_PMD) >> 3; - extern unsigned long perf_ovfl_val; - /* we just use ptrace to read */ - if (write_access) return -1; - - if (pmd > 3) { - printk("ptrace: rejecting access to PMD[%ld] address 0x%lx\n", pmd, addr); - return -1; - } - - /* - * We always need to mask upper 32bits of pmd because value is random - */ - pmd_tmp = child->thread.pmod[pmd]+(child->thread.pmd[pmd]& perf_ovfl_val); - - /*printk(__FUNCTION__" child=%d reading pmd[%ld]=%lx\n", child->pid, pmd, pmd_tmp);*/ - - ptr = &pmd_tmp; + if (write_access) + /* don't let the user set kernel-level breakpoints... */ + *ptr = *data & ~(7UL << 56); + else + *data = *ptr; + return 0; } -#endif - if (write_access) *ptr = *data; else @@ -1107,7 +1058,7 @@ goto out_tsk; if (child->state != TASK_STOPPED) { - if (request != PTRACE_KILL && request != PTRACE_PEEKUSR) + if (request != PTRACE_KILL) goto out_tsk; } diff -urN linux-2.4.0-test10/arch/ia64/kernel/sal.c linux-2.4.0-test10-lia/arch/ia64/kernel/sal.c --- linux-2.4.0-test10/arch/ia64/kernel/sal.c Mon Oct 9 17:54:54 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/sal.c Wed Nov 15 17:58:45 2000 @@ -104,9 +104,11 @@ if (strncmp(systab->signature, "SST_", 4) != 0) printk("bad signature in system table!"); - printk("SAL v%u.%02u: ia32bios=%s, oem=%.32s, product=%.32s\n", + /* + * revisions are coded in BCD, so %x does the job for us + */ + printk("SAL v%x.%02x: oem=%.32s, product=%.32s\n", systab->sal_rev_major, systab->sal_rev_minor, - systab->ia32_bios_present ? "present" : "absent", systab->oem_id, systab->product_id); min = ~0UL; diff -urN linux-2.4.0-test10/arch/ia64/kernel/setup.c linux-2.4.0-test10-lia/arch/ia64/kernel/setup.c --- linux-2.4.0-test10/arch/ia64/kernel/setup.c Mon Oct 9 17:54:55 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/setup.c Wed Nov 15 22:02:05 2000 @@ -408,6 +408,8 @@ { extern void __init ia64_rid_init (void); extern void __init ia64_tlb_init (void); + pal_vm_info_2_u_t vmi; + unsigned int max_ctx; identify_cpu(&my_cpu_data); @@ -415,15 +417,12 @@ memset(ia64_task_regs(current), 0, sizeof(struct pt_regs)); /* - * Initialize default control register to defer speculative - * faults. On a speculative load, we want to defer access - * right, key miss, and key permission faults. We currently - * do NOT defer TLB misses, page-not-present, access bit, or - * debug faults but kernel code should not rely on any - * particular setting of these bits. - ia64_set_dcr(IA64_DCR_DR | IA64_DCR_DK | IA64_DCR_DX | IA64_DCR_PP); + * Initialize default control register to defer all speculative faults. The + * kernel MUST NOT depend on a particular setting of these bits (in other words, + * the kernel must have recovery code for all speculative accesses). */ - ia64_set_dcr(IA64_DCR_DR | IA64_DCR_DK | IA64_DCR_DX ); + ia64_set_dcr( IA64_DCR_DM | IA64_DCR_DP | IA64_DCR_DK | IA64_DCR_DX | IA64_DCR_DR + | IA64_DCR_DA | IA64_DCR_DD); #ifndef CONFIG_SMP ia64_set_fpu_owner(0); /* initialize ar.k5 */ #endif @@ -444,4 +443,17 @@ #ifdef CONFIG_SMP normal_xtp(); #endif + + /* set ia64_ctx.max_rid to the maximum RID that is supported by all CPUs: */ + if (ia64_pal_vm_summary(NULL, &vmi) == 0) + max_ctx = (1U << (vmi.pal_vm_info_2_s.rid_size - 3)) - 1; + else { + printk("ia64_rid_init: PAL VM summary failed, assuming 18 RID bits\n"); + max_ctx = (1U << 15) - 1; /* use architected minimum */ + } + while (max_ctx < ia64_ctx.max_ctx) { + unsigned int old = ia64_ctx.max_ctx; + if (cmpxchg(&ia64_ctx.max_ctx, old, max_ctx) == old) + break; + } } diff -urN linux-2.4.0-test10/arch/ia64/kernel/signal.c linux-2.4.0-test10-lia/arch/ia64/kernel/signal.c --- linux-2.4.0-test10/arch/ia64/kernel/signal.c Mon Oct 9 17:54:55 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/signal.c Wed Nov 15 18:03:14 2000 @@ -91,7 +91,7 @@ scr->pt.r10 = -1; } while (1) { - set_current_state(TASK_INTERRUPTIBLE); + current->state = TASK_INTERRUPTIBLE; schedule(); if (ia64_do_signal(&oldset, scr, 1)) return -EINTR; @@ -499,9 +499,10 @@ /* Let the debugger run. */ current->exit_code = signr; current->thread.siginfo = &info; - set_current_state(TASK_STOPPED); + current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); + signr = current->exit_code; current->thread.siginfo = 0; @@ -557,7 +558,7 @@ /* FALLTHRU */ case SIGSTOP: - set_current_state(TASK_STOPPED); + current->state = TASK_STOPPED; current->exit_code = signr; if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) diff -urN linux-2.4.0-test10/arch/ia64/kernel/smp.c linux-2.4.0-test10-lia/arch/ia64/kernel/smp.c --- linux-2.4.0-test10/arch/ia64/kernel/smp.c Mon Oct 9 17:54:55 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/smp.c Wed Nov 15 18:04:37 2000 @@ -11,6 +11,8 @@ * 00/03/31 Rohit Seth Fixes for Bootstrap Processor & cpu_online_map * now gets done here (instead of setup.c) * 99/10/05 davidm Update to bring it in sync with new command-line processing scheme. + * 10/13/00 Goutham Rao Updated smp_call_function and + * smp_call_function_single to resend IPI on timeouts */ #define __KERNEL_SYSCALLS__ @@ -30,6 +32,7 @@ #include #include #include +#include #include #include @@ -276,7 +279,7 @@ return; set_bit(op, &ipi_op[dest_cpu]); - ipi_send(dest_cpu, IPI_IRQ, IA64_IPI_DM_INT, 0); + platform_send_ipi(dest_cpu, IPI_IRQ, IA64_IPI_DM_INT, 0); } static inline void @@ -358,6 +361,7 @@ if (pointer_lock(&smp_call_function_data, &data, retry)) return -EBUSY; +resend: /* Send a message to all other CPUs and wait for them to respond */ send_IPI_single(cpuid, IPI_CALL_FUNC); @@ -366,8 +370,12 @@ while ((atomic_read(&data.unstarted_count) > 0) && time_before(jiffies, timeout)) barrier(); if (atomic_read(&data.unstarted_count) > 0) { +#if (defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) || defined(CONFIG_ITANIUM_BSTEP_SPECIFIC)) + goto resend; +#else smp_call_function_data = NULL; return -ETIMEDOUT; +#endif } if (wait) while (atomic_read(&data.unfinished_count) > 0) @@ -411,13 +419,23 @@ /* Send a message to all other CPUs and wait for them to respond */ send_IPI_allbutself(IPI_CALL_FUNC); +retry: /* Wait for response */ timeout = jiffies + HZ; while ((atomic_read(&data.unstarted_count) > 0) && time_before(jiffies, timeout)) barrier(); if (atomic_read(&data.unstarted_count) > 0) { +#if (defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) || defined(CONFIG_ITANIUM_BSTEP_SPECIFIC)) + int i; + for (i = 0; i < smp_num_cpus; i++) { + if (i != smp_processor_id()) + platform_send_ipi(i, IPI_IRQ, IA64_IPI_DM_INT, 0); + } + goto retry; +#else smp_call_function_data = NULL; return -ETIMEDOUT; +#endif } if (wait) while (atomic_read(&data.unfinished_count) > 0) @@ -569,7 +587,7 @@ cpu_now_booting = cpu; /* Kick the AP in the butt */ - ipi_send(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0); + platform_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0); /* wait up to 10s for the AP to start */ for (timeout = 0; timeout < 100000; timeout++) { diff -urN linux-2.4.0-test10/arch/ia64/kernel/smpboot.c linux-2.4.0-test10-lia/arch/ia64/kernel/smpboot.c --- linux-2.4.0-test10/arch/ia64/kernel/smpboot.c Fri Oct 13 12:05:29 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/smpboot.c Mon Oct 30 22:17:11 2000 @@ -4,6 +4,8 @@ * Application processor startup code, moved from smp.c to better support kernel profile */ +#include + #include #include #include diff -urN linux-2.4.0-test10/arch/ia64/kernel/traps.c linux-2.4.0-test10-lia/arch/ia64/kernel/traps.c --- linux-2.4.0-test10/arch/ia64/kernel/traps.c Mon Oct 9 17:54:55 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/traps.c Mon Oct 30 22:40:14 2000 @@ -544,7 +544,7 @@ case 46: printk("Unexpected IA-32 intercept trap (Trap 46)\n"); - printk(" iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx\n", regs->cr_iip, ifa, isr); + printk(" iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx, iim - 0x%lx\n", regs->cr_iip, ifa, isr, iim); force_sig(SIGSEGV, current); return; diff -urN linux-2.4.0-test10/arch/ia64/kernel/unaligned.c linux-2.4.0-test10-lia/arch/ia64/kernel/unaligned.c --- linux-2.4.0-test10/arch/ia64/kernel/unaligned.c Mon Oct 9 17:54:55 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/unaligned.c Wed Nov 15 18:08:22 2000 @@ -572,7 +572,8 @@ */ if (regnum == 0) { *val = 0; - *nat = 0; + if (nat) + *nat = 0; return; } @@ -1563,9 +1564,13 @@ DPRINT(("ret=%d\n", ret)); if (ret) { - lock_kernel(); - force_sig(SIGSEGV, current); - unlock_kernel(); + struct siginfo si; + + si.si_signo = SIGBUS; + si.si_errno = 0; + si.si_code = BUS_ADRALN; + si.si_addr = (void *) ifa; + force_sig_info(SIGBUS, &si, current); } else { /* * given today's architecture this case is not likely to happen diff -urN linux-2.4.0-test10/arch/ia64/kernel/unwind.c linux-2.4.0-test10-lia/arch/ia64/kernel/unwind.c --- linux-2.4.0-test10/arch/ia64/kernel/unwind.c Mon Oct 9 17:54:55 2000 +++ linux-2.4.0-test10-lia/arch/ia64/kernel/unwind.c Wed Nov 15 22:08:29 2000 @@ -46,16 +46,6 @@ #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define p5 5 -/* - * The unwind tables are supposed to be sorted, but the GNU toolchain - * currently fails to produce a sorted table in the presence of - * functions that go into sections other than .text. For example, the - * kernel likes to put initialization code into .text.init, which - * messes up the sort order. Hopefully, this will get fixed sometime - * soon. --davidm 00/05/23 - */ -#define UNWIND_TABLE_SORT_BUG - #define UNW_LOG_CACHE_SIZE 7 /* each unw_script is ~256 bytes in size */ #define UNW_CACHE_SIZE (1 << UNW_LOG_CACHE_SIZE) @@ -1964,23 +1954,6 @@ { struct unw_table_entry *start = table_start, *end = table_end; -#ifdef UNWIND_TABLE_SORT_BUG - { - struct unw_table_entry *e1, *e2, tmp; - - /* stupid bubble sort... */ - - for (e1 = start; e1 < end; ++e1) { - for (e2 = e1 + 1; e2 < end; ++e2) { - if (e2->start_offset < e1->start_offset) { - tmp = *e1; - *e1 = *e2; - *e2 = tmp; - } - } - } - } -#endif table->name = name; table->segment_base = segment_base; table->gp = gp; @@ -2023,8 +1996,8 @@ void unw_remove_unwind_table (void *handle) { - struct unw_table *table, *prevt; - struct unw_script *tmp, *prev; + struct unw_table *table, *prev; + struct unw_script *tmp; unsigned long flags; long index; @@ -2043,41 +2016,35 @@ { /* first, delete the table: */ - for (prevt = (struct unw_table *) &unw.tables; prevt; prevt = prevt->next) - if (prevt->next == table) + for (prev = (struct unw_table *) &unw.tables; prev; prev = prev->next) + if (prev->next == table) break; - if (!prevt) { + if (!prev) { dprintk("unwind: failed to find unwind table %p\n", (void *) table); spin_unlock_irqrestore(&unw.lock, flags); return; } - prevt->next = table->next; + prev->next = table->next; + } + spin_unlock_irqrestore(&unw.lock, flags); - /* next, remove hash table entries for this table */ + /* next, remove hash table entries for this table */ - for (index = 0; index <= UNW_HASH_SIZE; ++index) { - if (unw.hash[index] >= UNW_CACHE_SIZE) - continue; + for (index = 0; index <= UNW_HASH_SIZE; ++index) { + tmp = unw.cache + unw.hash[index]; + if (unw.hash[index] >= UNW_CACHE_SIZE + || tmp->ip < table->start || tmp->ip >= table->end) + continue; - tmp = unw.cache + unw.hash[index]; - prev = 0; - while (1) { - write_lock(&tmp->lock); - { - if (tmp->ip >= table->start && tmp->ip < table->end) { - if (prev) - prev->coll_chain = tmp->coll_chain; - else - unw.hash[index] = -1; - tmp->ip = 0; - } else - prev = tmp; - } - write_unlock(&tmp->lock); + write_lock(&tmp->lock); + { + if (tmp->ip >= table->start && tmp->ip < table->end) { + unw.hash[index] = tmp->coll_chain; + tmp->ip = 0; } } + write_unlock(&tmp->lock); } - spin_unlock_irqrestore(&unw.lock, flags); kfree(table); } diff -urN linux-2.4.0-test10/arch/ia64/lib/copy_user.S linux-2.4.0-test10-lia/arch/ia64/lib/copy_user.S --- linux-2.4.0-test10/arch/ia64/lib/copy_user.S Fri Jul 14 16:08:12 2000 +++ linux-2.4.0-test10-lia/arch/ia64/lib/copy_user.S Mon Oct 30 23:45:16 2000 @@ -65,6 +65,12 @@ // // local registers // +#define t1 r2 // rshift in bytes +#define t2 r3 // lshift in bytes +#define rshift r14 // right shift in bits +#define lshift r15 // left shift in bits +#define word1 r16 +#define word2 r17 #define cnt r18 #define len2 r19 #define saved_lc r20 @@ -134,6 +140,190 @@ br.ret.sptk.few rp // end of short memcpy // + // Not 8-byte aligned + // +diff_align_copy_user: + // At this point we know we have more than 16 bytes to copy + // and also that src and dest do _not_ have the same alignment. + and src2=0x7,src1 // src offset + and dst2=0x7,dst1 // dst offset + ;; + // The basic idea is that we copy byte-by-byte at the head so + // that we can reach 8-byte alignment for both src1 and dst1. + // Then copy the body using software pipelined 8-byte copy, + // shifting the two back-to-back words right and left, then copy + // the tail by copying byte-by-byte. + // + // Fault handling. If the byte-by-byte at the head fails on the + // load, then restart and finish the pipleline by copying zeros + // to the dst1. Then copy zeros for the rest of dst1. + // If 8-byte software pipeline fails on the load, do the same as + // failure_in3 does. If the byte-by-byte at the tail fails, it is + // handled simply by failure_in_pipe1. + // + // The case p14 represents the source has more bytes in the + // the first word (by the shifted part), whereas the p15 needs to + // copy some bytes from the 2nd word of the source that has the + // tail of the 1st of the destination. + // + + // + // Optimization. If dst1 is 8-byte aligned (not rarely), we don't need + // to copy the head to dst1, to start 8-byte copy software pipleline. + // We know src1 is not 8-byte aligned in this case. + // + cmp.eq p14,p15=r0,dst2 +(p15) br.cond.spnt.few 1f + ;; + sub t1=8,src2 + mov t2=src2 + ;; + shl rshift=t2,3 + sub len1=len,t1 // set len1 + ;; + sub lshift=64,rshift + ;; + br.cond.spnt.few word_copy_user + ;; +1: + cmp.leu p14,p15=src2,dst2 + sub t1=dst2,src2 + ;; + .pred.rel "mutex", p14, p15 +(p14) sub word1=8,src2 // (8 - src offset) +(p15) sub t1=r0,t1 // absolute value +(p15) sub word1=8,dst2 // (8 - dst offset) + ;; + // For the case p14, we don't need to copy the shifted part to + // the 1st word of destination. + sub t2=8,t1 +(p14) sub word1=word1,t1 + ;; + sub len1=len,word1 // resulting len +(p15) shl rshift=t1,3 // in bits +(p14) shl rshift=t2,3 + ;; +(p14) sub len1=len1,t1 + adds cnt=-1,word1 + ;; + sub lshift=64,rshift + mov ar.ec=PIPE_DEPTH + mov pr.rot=1<<16 // p16=true all others are false + mov ar.lc=cnt + ;; +2: + EX(failure_in_pipe2,(p16) ld1 val1[0]=[src1],1) + ;; + EX(failure_out,(EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1) + br.ctop.dptk.few 2b + ;; + clrrrb + ;; +word_copy_user: + cmp.gtu p9,p0=16,len1 +(p9) br.cond.spnt.few 4f // if (16 > len1) skip 8-byte copy + ;; + shr.u cnt=len1,3 // number of 64-bit words + ;; + adds cnt=-1,cnt + ;; + .pred.rel "mutex", p14, p15 +(p14) sub src1=src1,t2 +(p15) sub src1=src1,t1 + // + // Now both src1 and dst1 point to an 8-byte aligned address. And + // we have more than 8 bytes to copy. + // + mov ar.lc=cnt + mov ar.ec=PIPE_DEPTH + mov pr.rot=1<<16 // p16=true all others are false + ;; +3: + // + // The pipleline consists of 3 stages: + // 1 (p16): Load a word from src1 + // 2 (EPI_1): Shift right pair, saving to tmp + // 3 (EPI): Store tmp to dst1 + // + // To make it simple, use at least 2 (p16) loops to set up val1[n] + // because we need 2 back-to-back val1[] to get tmp. + // Note that this implies EPI_2 must be p18 or greater. + // + +#define EPI_1 p[PIPE_DEPTH-2] +#define SWITCH(pred, shift) cmp.eq pred,p0=shift,rshift +#define CASE(pred, shift) \ + (pred) br.cond.spnt.few copy_user_bit##shift +#define BODY(rshift) \ +copy_user_bit##rshift: \ +1: \ + EX(failure_out,(EPI) st8 [dst1]=tmp,8); \ +(EPI_1) shrp tmp=val1[PIPE_DEPTH-3],val1[PIPE_DEPTH-2],rshift; \ + EX(failure_in2,(p16) ld8 val1[0]=[src1],8); \ + br.ctop.dptk.few 1b; \ + ;; \ + br.cond.spnt.few .diff_align_do_tail + + // + // Since the instruction 'shrp' requires a fixed 128-bit value + // specifying the bits to shift, we need to provide 7 cases + // below. + // + SWITCH(p6, 8) + SWITCH(p7, 16) + SWITCH(p8, 24) + SWITCH(p9, 32) + SWITCH(p10, 40) + SWITCH(p11, 48) + SWITCH(p12, 56) + ;; + CASE(p6, 8) + CASE(p7, 16) + CASE(p8, 24) + CASE(p9, 32) + CASE(p10, 40) + CASE(p11, 48) + CASE(p12, 56) + ;; + BODY(8) + BODY(16) + BODY(24) + BODY(32) + BODY(40) + BODY(48) + BODY(56) + ;; +.diff_align_do_tail: + .pred.rel "mutex", p14, p15 +(p14) sub src1=src1,t1 +(p14) adds dst1=-8,dst1 +(p15) sub dst1=dst1,t1 + ;; +4: + // Tail correction. + // + // The problem with this piplelined loop is that the last word is not + // loaded and thus parf of the last word written is not correct. + // To fix that, we simply copy the tail byte by byte. + + sub len1=endsrc,src1,1 + clrrrb + ;; + mov ar.ec=PIPE_DEPTH + mov pr.rot=1<<16 // p16=true all others are false + mov ar.lc=len1 + ;; +5: + EX(failure_in_pipe1,(p16) ld1 val1[0]=[src1],1) + + EX(failure_out,(EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1) + br.ctop.dptk.few 5b + ;; + mov pr=saved_pr,0xffffffffffff0000 + mov ar.pfs=saved_pfs + br.ret.dptk.few rp + + // // Beginning of long mempcy (i.e. > 16 bytes) // long_copy_user: @@ -142,7 +332,7 @@ ;; cmp.eq p10,p8=r0,tmp mov len1=len // copy because of rotation -(p8) br.cond.dpnt.few 1b // XXX Fixme. memcpy_diff_align +(p8) br.cond.dpnt.few diff_align_copy_user ;; // At this point we know we have more than 16 bytes to copy // and also that both src and dest have the same alignment @@ -267,6 +457,21 @@ mov ar.pfs=saved_pfs br.ret.dptk.few rp + // + // This is the case where the byte by byte copy fails on the load + // when we copy the head. We need to finish the pipeline and copy + // zeros for the rest of the destination. Since this happens + // at the top we still need to fill the body and tail. +failure_in_pipe2: + sub ret0=endsrc,src1 // number of bytes to zero, i.e. not copied +2: +(p16) mov val1[0]=r0 +(EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1 + br.ctop.dptk.few 2b + ;; + sub len=enddst,dst1,1 // precompute len + br.cond.dptk.few failure_in1bis + ;; // // Here we handle the head & tail part when we check for alignment. @@ -395,6 +600,23 @@ mov ar.pfs=saved_pfs br.ret.dptk.few rp +failure_in2: + sub ret0=endsrc,src1 // number of bytes to zero, i.e. not copied + ;; +3: +(p16) mov val1[0]=r0 +(EPI) st8 [dst1]=val1[PIPE_DEPTH-1],8 + br.ctop.dptk.few 3b + ;; + cmp.ne p6,p0=dst1,enddst // Do we need to finish the tail ? + sub len=enddst,dst1,1 // precompute len +(p6) br.cond.dptk.few failure_in1bis + ;; + mov pr=saved_pr,0xffffffffffff0000 + mov ar.lc=saved_lc + mov ar.pfs=saved_pfs + br.ret.dptk.few rp + // // handling of failures on stores: that's the easy part // diff -urN linux-2.4.0-test10/arch/ia64/lib/memcpy.S linux-2.4.0-test10-lia/arch/ia64/lib/memcpy.S --- linux-2.4.0-test10/arch/ia64/lib/memcpy.S Fri Aug 11 19:09:06 2000 +++ linux-2.4.0-test10-lia/arch/ia64/lib/memcpy.S Wed Nov 1 23:14:24 2000 @@ -17,17 +17,31 @@ #include +#if defined(CONFIG_ITANIUM_B0_SPECIFIC) || defined(CONFIG_ITANIUM_B1_SPECIFIC) +# define BRP(args...) nop.b 0 +#else +# define BRP(args...) brp.loop.imp args +#endif + GLOBAL_ENTRY(bcopy) .regstk 3,0,0,0 mov r8=in0 mov in0=in1 ;; mov in1=r8 + // gas doesn't handle control flow across procedures, so it doesn't + // realize that a stop bit is needed before the "alloc" instruction + // below +{ + nop.m 0 + nop.f 0 + nop.i 0 +} ;; END(bcopy) // FALL THROUGH GLOBAL_ENTRY(memcpy) -# define MEM_LAT 2 /* latency to L1 cache */ +# define MEM_LAT 21 /* latency to memory */ # define dst r2 # define src r3 @@ -57,20 +71,17 @@ UNW(.prologue) UNW(.save ar.pfs, saved_pfs) alloc saved_pfs=ar.pfs,3,Nrot,0,Nrot -#if !(defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) || defined(CONFIG_ITANIUM_BSTEP_SPECIFIC)) - lfetch [in1] -#else - nop.m 0 -#endif + UNW(.save ar.lc, saved_lc) + mov saved_lc=ar.lc or t0=in0,in1 ;; or t0=t0,in2 - UNW(.save ar.lc, saved_lc) - mov saved_lc=ar.lc UNW(.save pr, saved_pr) mov saved_pr=pr + UNW(.body) + cmp.eq p6,p0=in2,r0 // zero length? mov retval=in0 // return dst (p6) br.ret.spnt.many rp // zero length, return immediately @@ -83,7 +94,6 @@ adds cnt=-1,cnt // br.ctop is repeat/until cmp.gtu p7,p0=16,in2 // copying less than 16 bytes? - UNW(.body) mov ar.ec=N ;; @@ -98,10 +108,17 @@ ;; .rotr val[N] .rotp p[N] -1: + .align 32 +1: { .mib (p[0]) ld8 val[0]=[src],8 + nop.i 0 + BRP(1b, 2f) +} +2: { .mfb (p[N-1])st8 [dst]=val[N-1],8 + nop.f 0 br.ctop.dptk.few 1b +} ;; mov ar.lc=saved_lc mov pr=saved_pr,-1 @@ -118,6 +135,7 @@ memcpy_short: adds cnt=-1,in2 // br.ctop is repeat/until mov ar.ec=MEM_LAT + BRP(1f, 2f) ;; mov ar.lc=cnt ;; @@ -125,12 +143,17 @@ * It is faster to put a stop bit in the loop here because it makes * the pipeline shorter (and latency is what matters on short copies). */ -1: + .align 32 +1: { .mib (p[0]) ld1 val[0]=[src],1 - ;; + nop.i 0 + BRP(1b, 2f) +} ;; +2: { .mfb (p[MEM_LAT-1])st1 [dst]=val[MEM_LAT-1],1 + nop.f 0 br.ctop.dptk.few 1b - ;; +} ;; mov ar.lc=saved_lc mov pr=saved_pr,-1 mov ar.pfs=saved_pfs @@ -251,17 +274,16 @@ .align 64 #define COPY(shift,index) \ - 1: \ - { .mfi \ + 1: { .mib \ (p[0]) ld8 val[0]=[src2],8; \ - nop.f 0; \ (p[MEM_LAT+3]) shrp w[0]=val[MEM_LAT+3],val[MEM_LAT+4-index],shift; \ - }; \ - { .mbb \ + BRP(1b, 2f) \ + }; \ + 2: { .mfb \ (p[MEM_LAT+4]) st8 [dst]=w[1],8; \ - nop.b 0; \ + nop.f 0; \ br.ctop.dptk.few 1b; \ - }; \ + }; \ ;; \ ld8 val[N-1]=[src_end]; /* load last word (may be same as val[N]) */ \ ;; \ diff -urN linux-2.4.0-test10/arch/ia64/mm/init.c linux-2.4.0-test10-lia/arch/ia64/mm/init.c --- linux-2.4.0-test10/arch/ia64/mm/init.c Mon Oct 9 17:54:56 2000 +++ linux-2.4.0-test10-lia/arch/ia64/mm/init.c Wed Nov 15 18:39:03 2000 @@ -305,7 +305,7 @@ return 0; } flush_page_to_ram(page); - set_pte(pte, page_pte_prot(page, PAGE_GATE)); + set_pte(pte, mk_pte(page, PAGE_GATE)); /* no need for flush_tlb */ return page; } @@ -423,6 +423,17 @@ extern char __start_gate_section[]; long reserved_pages, codesize, datasize, initsize; +#ifdef CONFIG_SWIOTLB + { + /* + * This needs to be called _after_ the command line has been parsed but + * _before_ any drivers that may need the sw I/O TLB are initialized or + * bootmem has been freed. + */ + extern void setup_swiotlb (void); + setup_swiotlb(); + } +#endif if (!mem_map) BUG(); diff -urN linux-2.4.0-test10/arch/ia64/mm/tlb.c linux-2.4.0-test10-lia/arch/ia64/mm/tlb.c --- linux-2.4.0-test10/arch/ia64/mm/tlb.c Fri Aug 11 19:09:06 2000 +++ linux-2.4.0-test10-lia/arch/ia64/mm/tlb.c Wed Nov 15 22:08:44 2000 @@ -6,6 +6,8 @@ * * 08/02/00 A. Mallick * Modified RID allocation for SMP + * Goutham Rao + * IPI based ptc implementation and A-step IPI implementation. */ #include #include @@ -17,6 +19,7 @@ #include #include #include +#include #define SUPPORTED_PGBITS ( \ 1 << _PAGE_SIZE_256M | \ @@ -33,15 +36,10 @@ struct ia64_ctx ia64_ctx = { lock: SPIN_LOCK_UNLOCKED, next: 1, - limit: (1UL << IA64_HW_CONTEXT_BITS) + limit: (1 << 15) - 1, /* start out with the safe (architected) limit */ + max_ctx: ~0U }; - /* - * Put everything in a struct so we avoid the global offset table whenever - * possible. - */ -ia64_ptce_info_t ia64_ptce_info; - /* * Seralize usage of ptc.g */ @@ -99,9 +97,22 @@ /* * Wait for other CPUs to finish purging entries. */ +#if (defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) || defined(CONFIG_ITANIUM_BSTEP_SPECIFIC)) + { + unsigned long start = ia64_get_itc(); + while (atomic_read(&flush_cpu_count) > 0) { + if ((ia64_get_itc() - start) > 40000UL) { + atomic_set(&flush_cpu_count, smp_num_cpus - 1); + smp_send_flush_tlb(); + start = ia64_get_itc(); + } + } + } +#else while (atomic_read(&flush_cpu_count)) { /* Nothing */ } +#endif if (!(flags & IA64_PSR_I)) { local_irq_disable(); ia64_set_tpr(saved_tpr); @@ -117,12 +128,12 @@ void wrap_mmu_context (struct mm_struct *mm) { + unsigned long tsk_context, max_ctx = ia64_ctx.max_ctx; struct task_struct *tsk; - unsigned long tsk_context; - if (ia64_ctx.next >= (1UL << IA64_HW_CONTEXT_BITS)) + if (ia64_ctx.next > max_ctx) ia64_ctx.next = 300; /* skip daemons */ - ia64_ctx.limit = (1UL << IA64_HW_CONTEXT_BITS); + ia64_ctx.limit = max_ctx + 1; /* * Scan all the task's mm->context and set proper safe range @@ -137,9 +148,9 @@ if (tsk_context == ia64_ctx.next) { if (++ia64_ctx.next >= ia64_ctx.limit) { /* empty range: reset the range limit and start over */ - if (ia64_ctx.next >= (1UL << IA64_HW_CONTEXT_BITS)) + if (ia64_ctx.next > max_ctx) ia64_ctx.next = 300; - ia64_ctx.limit = (1UL << IA64_HW_CONTEXT_BITS); + ia64_ctx.limit = max_ctx + 1; goto repeat; } } @@ -153,12 +164,13 @@ void __flush_tlb_all (void) { - unsigned long i, j, flags, count0, count1, stride0, stride1, addr = ia64_ptce_info.base; + unsigned long i, j, flags, count0, count1, stride0, stride1, addr; - count0 = ia64_ptce_info.count[0]; - count1 = ia64_ptce_info.count[1]; - stride0 = ia64_ptce_info.stride[0]; - stride1 = ia64_ptce_info.stride[1]; + addr = my_cpu_data.ptce_base; + count0 = my_cpu_data.ptce_count[0]; + count1 = my_cpu_data.ptce_count[1]; + stride0 = my_cpu_data.ptce_stride[0]; + stride1 = my_cpu_data.ptce_stride[1]; local_irq_save(flags); for (i = 0; i < count0; ++i) { @@ -230,6 +242,14 @@ void __init ia64_tlb_init (void) { - ia64_get_ptce(&ia64_ptce_info); + ia64_ptce_info_t ptce_info; + + ia64_get_ptce(&ptce_info); + my_cpu_data.ptce_base = ptce_info.base; + my_cpu_data.ptce_count[0] = ptce_info.count[0]; + my_cpu_data.ptce_count[1] = ptce_info.count[1]; + my_cpu_data.ptce_stride[0] = ptce_info.stride[0]; + my_cpu_data.ptce_stride[1] = ptce_info.stride[1]; + __flush_tlb_all(); /* nuke left overs from bootstrapping... */ } diff -urN linux-2.4.0-test10/arch/ia64/sn/Makefile linux-2.4.0-test10-lia/arch/ia64/sn/Makefile --- linux-2.4.0-test10/arch/ia64/sn/Makefile Thu Mar 30 16:56:04 2000 +++ linux-2.4.0-test10-lia/arch/ia64/sn/Makefile Wed Nov 15 19:11:39 2000 @@ -5,14 +5,14 @@ # Copyright (C) Srinivasa Thirumalachar (sprasad@engr.sgi.com) # -CFLAGS := $(CFLAGS) -DCONFIG_SGI_SN1 -DSN1 -DSN -DSOFTSDV \ - -DLANGUAGE_C=1 -D_LANGUAGE_C=1 -AFLAGS := $(AFLAGS) -DCONFIG_SGI_SN1 -DSN1 -DSOFTSDV +CFLAGS += -DCONFIG_SGI_SN1 -DSN1 -DSN -DSOFTSDV -DLANGUAGE_C=1 \ + -D_LANGUAGE_C=1 +AFLAGS += -DCONFIG_SGI_SN1 -DSN1 -DSOFTSDV .S.s: - $(CPP) $(AFLAGS) -o $*.s $< + $(CPP) $(AFLAGS) $(AFLAGS_KERNEL) -o $*.s $< .S.o: - $(CC) $(AFLAGS) -c -o $*.o $< + $(CC) $(AFLAGS) $(AFLAGS_KERNEL) -c -o $*.o $< all: sn.a diff -urN linux-2.4.0-test10/arch/ia64/sn/fprom/Makefile linux-2.4.0-test10-lia/arch/ia64/sn/fprom/Makefile --- linux-2.4.0-test10/arch/ia64/sn/fprom/Makefile Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/fprom/Makefile Wed Nov 15 19:11:39 2000 @@ -0,0 +1,41 @@ +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 2000 Silicon Graphics, Inc. +# Copyright (C) Jack Steiner (steiner@sgi.com) +# + +TOPDIR=../../../.. +HPATH = $(TOPDIR)/include + +CROSS_COMPILE = + +AS =$(CROSS_COMPILE)as +LD =$(CROSS_COMPILE)ld +CC =$(CROSS_COMPILE)gcc -D__KERNEL__ -I$(HPATH) -D__LP64__ + +LIB = ../../lib/lib.a + +CPPFLAGS := -D__KERNEL__ -I$(HPATH) +CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -mconstant-gp +AFLAGS := $(CPPFLAGS) -mconstant-gp + + +OBJ=fpromasm.o main.o fw-emu.o fpmem.o + +fprom: $(OBJ) + $(LD) -static -Tfprom.lds -o fprom $(OBJ) $(LIB) + +.S.o: + $(CC) -D__ASSEMBLY__ $(AFLAGS) $(AFLAGS_KERNEL) -c -o $*.o $< +.c.o: + $(CC) $(CFLAGS) $(CFLAGS_KERNEL) -c -o $*.o $< + +clean: + rm -f *.o fprom + + +include $(TOPDIR)/Rules.make + diff -urN linux-2.4.0-test10/arch/ia64/sn/fprom/README linux-2.4.0-test10-lia/arch/ia64/sn/fprom/README --- linux-2.4.0-test10/arch/ia64/sn/fprom/README Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/fprom/README Wed Nov 15 19:11:39 2000 @@ -0,0 +1,85 @@ +This directory contains the files required to build +the fake PROM image that is currently being used to +boot IA64 kernels running under the SGI Medusa kernel. + +The FPROM currently provides the following functions: + + - PAL emulation for all PAL calls we've made so far. + - SAL emulation for all SAL calls we've made so far. + - EFI emulation for all EFI calls we've made so far. + - builds the "ia64_bootparam" structure that is + passed to the kernel from SAL. This structure + shows the cpu & memory configurations. + - supports medusa boottime options for changing + the number of cpus present + - supports medusa boottime options for changing + the memory configuration. + + + +At some point, this fake PROM will be replaced by the +real PROM. + + + + +To build a fake PROM, cd to this directory & type: + + make + +This will (or should) build a fake PROM named "fprom". + + + + +Use this fprom image when booting the Medusa simulator. The +control file used to boot Medusa should include the +following lines: + + load fprom + load vmlinux + sr pc 0x100000 + sr g 9
#(currently 0xe000000000520000) + +NOTE: There is a script "runsim" in this directory that can be used to +simplify setting up an environment for running under Medusa. + + + + +The following parameters may be passed to the fake PROM to +control the PAL/SAL/EFI parameters passed to the kernel: + + GR[8] = # of cpus + GR[9] = address of primary entry point into the kernel + GR[20] = memory configuration for node 0 + GR[21] = memory configuration for node 1 + GR[22] = memory configuration for node 2 + GR[23] = memory configuration for node 3 + + +Registers GR[20] - GR[23] contain information to specify the +amount of memory present on nodes 0-3. + + - if nothing is specified (all registers are 0), the configuration + defaults to 8 MB on node 0. + + - a mem config entry for node N is passed in GR[20+N] + + - a mem config entry consists of 8 hex digits. Each digit gives the + amount of physical memory available on the node starting at + 1GB*, where dn is the digit number. The amount of memory + is 8MB*2**. (If = 0, the memory size is 0). + + SN1 doesnt support dimms this small but small memory systems + boot faster on Medusa. + + + +An example helps a lot. The following specifies that node 0 has +physical memory 0 to 8MB and 1GB to 1GB+32MB, and that node 1 has +64MB starting at address 0 of the node which is 8GB. + + gr[20] = 0x21 # 0 to 8MB, 1GB to 1GB+32MB + gr[21] = 0x4 # 8GB to 8GB+64MB + diff -urN linux-2.4.0-test10/arch/ia64/sn/fprom/fpmem.c linux-2.4.0-test10-lia/arch/ia64/sn/fprom/fpmem.c --- linux-2.4.0-test10/arch/ia64/sn/fprom/fpmem.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/fprom/fpmem.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,200 @@ +/* + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Jack Steiner (steiner@sgi.com) + */ + + +/* + * FPROM EFI memory descriptor build routines + * + * - Routines to build the EFI memory descriptor map + * - Should also be usable by the SGI SN1 prom to convert + * klconfig to efi_memmap + */ + +#include +#include "fpmem.h" + +/* + * args points to a layout in memory like this + * + * 32 bit 32 bit + * + * numnodes numcpus + * + * 16 bit 16 bit 32 bit + * nasid0 cpuconf membankdesc0 + * nasid1 cpuconf membankdesc1 + * . + * . + * . + * . + * . + */ + +sn_memmap_t *sn_memmap ; +sn_config_t *sn_config ; + +/* + * There is a hole in the node 0 address space. Dont put it + * in the memory map + */ +#define NODE0_HOLE_SIZE (20*MB) +#define NODE0_HOLE_END (4UL*GB) + +#define MB (1024*1024) +#define GB (1024*MB) +#define KERNEL_SIZE (12*MB) +#define PROMRESERVED_SIZE (1*MB) +#define MD_BANK_SHFT 30 + +#define TO_NODE(_n, _x) (((long)_n<<33L) | (long)_x) + +/* + * For SN, this may not take an arg and gets the numnodes from + * the prom variable or by traversing klcfg or promcfg + */ +int +GetNumNodes(void) +{ + return sn_config->nodes; +} + +int +GetNumCpus(void) +{ + return sn_config->cpus; +} + +/* For SN1, get the index th nasid */ + +int +GetNasid(int index) +{ + return sn_memmap[index].nasid ; +} + +node_memmap_t +GetMemBankInfo(int index) +{ + return sn_memmap[index].node_memmap ; +} + +int +IsCpuPresent(int cnode, int cpu) +{ + return sn_memmap[cnode].cpuconfig & (1<type = type; + md->phys_addr = paddr; + md->virt_addr = 0; + md->num_pages = numbytes >> 12; + md->attribute = EFI_MEMORY_WB; +} + +int +build_efi_memmap(void *md, int mdsize) +{ + int numnodes = GetNumNodes() ; + int cnode,bank ; + int nasid ; + node_memmap_t membank_info ; + int bsize; + int count = 0 ; + long paddr, hole, numbytes; + + + for (cnode=0;cnode + +typedef struct sn_memmap_s +{ + short nasid ; + short cpuconfig; + node_memmap_t node_memmap ; +} sn_memmap_t ; + +typedef struct sn_config_s +{ + int cpus; + int nodes; + sn_memmap_t memmap[1]; /* start of array */ +} sn_config_t; + + +extern void build_init(unsigned long); +extern int build_efi_memmap(void *, int); +extern int GetNumNodes(void); +extern int GetNumCpus(void); +extern int IsCpuPresent(int, int); +extern int GetNasid(int); diff -urN linux-2.4.0-test10/arch/ia64/sn/fprom/fprom.lds linux-2.4.0-test10-lia/arch/ia64/sn/fprom/fprom.lds --- linux-2.4.0-test10/arch/ia64/sn/fprom/fprom.lds Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/fprom/fprom.lds Wed Nov 15 19:11:39 2000 @@ -0,0 +1,96 @@ + +OUTPUT_FORMAT("elf64-ia64-little") +OUTPUT_ARCH(ia64) +ENTRY(_start) +SECTIONS +{ + v = 0x0000000000000000 ; /* this symbol is here to make debugging with kdb easier... */ + + . = (0x000000000000000 + 0x100000) ; + + _text = .; + .text : AT(ADDR(.text) - 0x0000000000000000 ) + { + *(__ivt_section) + /* these are not really text pages, but the zero page needs to be in a fixed location: */ + *(__special_page_section) + __start_gate_section = .; + *(__gate_section) + __stop_gate_section = .; + *(.text) + } + + /* Global data */ + _data = .; + + .rodata : AT(ADDR(.rodata) - 0x0000000000000000 ) + { *(.rodata) } + .opd : AT(ADDR(.opd) - 0x0000000000000000 ) + { *(.opd) } + .data : AT(ADDR(.data) - 0x0000000000000000 ) + { *(.data) *(.gnu.linkonce.d*) CONSTRUCTORS } + + __gp = ALIGN (8) + 0x200000; + + .got : AT(ADDR(.got) - 0x0000000000000000 ) + { *(.got.plt) *(.got) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : AT(ADDR(.sdata) - 0x0000000000000000 ) + { *(.sdata) } + _edata = .; + _bss = .; + .sbss : AT(ADDR(.sbss) - 0x0000000000000000 ) + { *(.sbss) *(.scommon) } + .bss : AT(ADDR(.bss) - 0x0000000000000000 ) + { *(.bss) *(COMMON) } + . = ALIGN(64 / 8); + _end = .; + + /* Sections to be discarded */ + /DISCARD/ : { + *(.text.exit) + *(.data.exit) + } + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* These must appear regardless of . */ + /* Discard them for now since Intel SoftSDV cannot handle them. + .comment 0 : { *(.comment) } + .note 0 : { *(.note) } + */ + /DISCARD/ : { *(.comment) } + /DISCARD/ : { *(.note) } +} diff -urN linux-2.4.0-test10/arch/ia64/sn/fprom/fpromasm.S linux-2.4.0-test10-lia/arch/ia64/sn/fprom/fpromasm.S --- linux-2.4.0-test10/arch/ia64/sn/fprom/fpromasm.S Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/fprom/fpromasm.S Wed Nov 15 19:11:39 2000 @@ -0,0 +1,306 @@ +/* + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * (Code copied from or=ther files) + * Copyright (C) 1998-2000 Hewlett-Packard Co + * Copyright (C) 1998-2000 David Mosberger-Tang + * + * Copyright (C) 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Jack Steiner (steiner@sgi.com) + */ + + + +#define __ASSEMBLY__ 1 +#include "asm/processor.h" + +/* + * This file contains additional set up code that is needed to get going on + * Medusa. This code should disappear once real hw is available. + * + * On entry to this routine, the following register values are assumed: + * + * gr[8] - BSP cpu + * pr[9] - kernel entry address + * + * NOTE: + * This FPROM may be loaded/executed at an address different from the + * address that it was linked at. The FPROM is linked to run on node 0 + * at address 0x100000. If the code in loaded into another node, it + * must be loaded at offset 0x100000 of the node. In addition, the + * FPROM does the following things: + * - determine the base address of the node it is loaded on + * - add the node base to _gp. + * - add the node base to all addresses derived from "movl" + * instructions. (I couldnt get GPREL addressing to work) + * (maybe newer versions of the tools will support this) + * - scan the .got section and add the node base to all + * pointers in this section. + * - add the node base to all physical addresses in the + * SAL/PAL/EFI table built by the C code. (This is done + * in the C code - not here) + * - add the node base to the TLB entries for vmlinux + */ + +#define KERNEL_BASE 0xe000000000000000 +#define PAGESIZE_256M 28 + +/* + * ar.k0 gets set to IOPB_PA value, on 460gx chipset it should + * be 0x00000ffffc000000, but on snia we use the (inverse swizzled) + * IOSPEC_BASE value + */ +#define IOPB_PA 0x00000a0000000000 /* inv swizzle IOSPEC_BASE */ + +#define RR_RID 8 + + + +// ==================================================================================== + .text + .align 16 + .global _start + .proc _start +_start: + +// Setup psr and rse for system init + mov psr.l = r0 + invala + mov ar.rsc = r0 + loadrs + +// Set CALIAS size to zero. We dont use it. + movl r24=0x80000a0001000028 // BR_PI_CALIAS_SIZE + st8 [r24]=r0 + +// Isolate node number we are running on. + mov r6 = ip + shr r5 = r6,33 // r5 = node number + shl r6 = r5,33 // r6 = base memory address of node + +// Set & relocate gp. + movl r1= __gp // Add base memory address + add r1 = r1,r6 // Relocate to boot node + +// Lets figure out who we are & put it in the LID register. +// The BR_PI_SELF_CPU_NUM register gives us a value of 0-3. +// This identifies the cpu on the node. +// Merge the cpu number with the NASID to generate the LID. + movl r24=0x80000a0001000020 // BR_PI_SELF_CPU_NUM + ld8 r25=[r24] // Fetch PI_SELF + movl r27=0x80000a0001600000 // Fetch REVID to get local NASID + ld8 r27=[r27] + extr.u r27=r27,32,8 + shl r26=r25,16 // Align local cpu# to lid.eid + shl r27=r27,24 // Align NASID to lid.id + or r26=r26,r27 // build the LID + mov cr.lid=r26 // Now put in in the LID register + + movl r2=FPSR_DEFAULT + mov ar.fpsr=r2 + movl sp = bootstacke-16 + add sp = sp,r6 // Relocate to boot node + +// Save the NASID that we are loaded on. + movl r2=base_nasid // Save base_nasid for C code + add r2 = r2,r6 // Relocate to boot node + st8 [r2]=r5 // Uncond st8 - same on all cpus + +// Save the kernel entry address. It is passed in r9 on one of +// the cpus. + movl r2=bsp_entry_pc + cmp.ne p6,p0=r9,r0 + add r2 = r2,r6 // Relocate to boot node +(p6) st8 [r2]=r9 // Uncond st8 - same on all cpus + + +// The following can ONLY be done by 1 cpu. Lets set a lock - the +// cpu that gets it does the initilization. The rest just spin waiting +// til initilization is complete. + movl r22 = initlock + add r22 = r22,r6 // Relocate to boot node + mov r23 = 1 + xchg8 r23 = [r22],r23 + cmp.eq p6,p0 = 0,r23 +(p6) br.cond.spnt.few init +1: ld4 r23 = [r22] + cmp.eq p6,p0 = 1,r23 +(p6) br.cond.sptk 1b + br initx + +// Add base address of node memory to each pointer in the .got section. +init: movl r16 = _GLOBAL_OFFSET_TABLE_ + add r16 = r16,r6 // Relocate to boot node +1: ld8 r17 = [r16] + cmp.eq p6,p7=0,r17 +(p6) br.cond.sptk.few.clr 2f + add r17 = r17,r6 // Relocate to boot node + st8 [r16] = r17,8 + br 1b +2: + mov r23 = 2 // All done, release the spinning cpus + st4 [r22] = r23 +initx: + +// +// I/O-port space base address: +// + movl r2 = IOPB_PA + mov ar.k0 = r2 + + +// Now call main & pass it the current LID value. + alloc r0=ar.pfs,0,0,2,0 + mov r32=r26 + mov r33=r8 + br.call.sptk.few rp=fmain + +// Initialize Region Registers +// + mov r10 = r0 + mov r2 = (13<<2) + mov r3 = r0 +1: cmp4.gtu p6,p7 = 7, r3 + dep r10 = r3, r10, 61, 3 + dep r2 = r3, r2, RR_RID, 4 +(p7) dep r2 = 0, r2, 0, 1 +(p6) dep r2 = -1, r2, 0, 1 + mov rr[r10] = r2 + add r3 = 1, r3 + cmp4.gtu p6,p0 = 8, r3 +(p6) br.cond.sptk.few.clr 1b + +// +// Return value indicates if we are the BSP or AP. +// 1 = BSP, 0 = AP + mov cr.tpr=r0 + cmp.eq p6,p0=r8,r0 +(p6) br.cond.spnt slave + +// +// Initialize the protection key registers with only pkr[0] = valid. +// +// Should be initialized in accordance with the OS. +// + mov r2 = 1 + mov r3 = r0 + mov pkr[r3] = r2 + mov r2 = r0 + +1: add r3 = r3, r0, 1 // increment PKR + cmp.gtu p6, p0 = 16, r3 +(p6) mov pkr[r3] = r2 +(p6) br.cond.sptk.few.clr 1b + + mov ar.rnat = r0 // clear RNAT register + +// +// Setup system address translation for kernel +// +// Note: The setup of Kernel Virtual address space can be done by the +// C code of the boot loader. +// +// + +#define LINUX_PAGE_OFFSET 0xe000000000000000 +#define ITIR(key, ps) ((key<<8) | (ps<<2)) +#define ITRGR(ed,ar,ma) ((ed<<52) | (ar<<9) | (ma<<2) | 0x61) + +#define AR_RX 1 // RX permission +#define AR_RW 4 // RW permission +#define MA_WB 0 // WRITEBACK memory attribute + +#define TLB_PAGESIZE 28 // Use 256MB pages for now. + mov r16=r5 + +// +// text section +// + movl r2 = LINUX_PAGE_OFFSET;; // Set up IFA with VPN of linux + mov cr.ifa = r2 + movl r3 = ITIR(0,TLB_PAGESIZE);; // Set ITIR to default pagesize + mov cr.itir = r3 + + shl r4 = r16,33;; // physical addr of start of node + movl r5 = ITRGR(1,AR_RX,MA_WB);; // TLB attributes + or r10=r4,r5;; + + itr.i itr[r0] = r10 // Dropin ITR entry + +// +// data section +// + movl r2 = LINUX_PAGE_OFFSET;; // Set up IFA with VPN of linux + mov cr.ifa = r2 + movl r3 = ITIR(0,TLB_PAGESIZE);; // Set ITIR to default pagesize + mov cr.itir = r3 + + shl r4 = r16,33;; // physical addr of start of node + movl r5 = ITRGR(1,AR_RW,MA_WB);; // TLB attributes + or r10=r4,r5;; + + itr.d dtr[r0] = r10 // Dropin DTR entry + + + + +// +// Turn on address translation, interrupt collection, psr.ed, protection key. +// Interrupts (PSR.i) are still off here. +// + + movl r3 = ( IA64_PSR_BN | \ + IA64_PSR_AC | \ + IA64_PSR_IT | \ + IA64_PSR_DB | \ + IA64_PSR_DA | \ + IA64_PSR_RT | \ + IA64_PSR_DT | \ + IA64_PSR_IC \ + ) + ;; + mov cr.ipsr = r3 + +// +// Go to kernel C startup routines +// Need to do a "rfi" in order set "it" and "ed" bits in the PSR. +// This is the only way to set them. + + movl r2=bsp_entry_pc; + add r2 = r2,r6 // Relocate to boot node + ld8 r2=[r2] + mov cr.iip = r2 + srlz.d + rfi;; + .endp _start + +// Slave processors come here to spin til they get an interrupt. Then they launch themselves to +// the place ap_entry points. No initialization is necessary - the kernel makes no +// assumptions about state on this entry. +// Note: should verify that the interrupt we got was really the ap_wakeup +// interrupt but this should not be an issue on medusa +slave: + mov r8=cr.irr0 // Check for interrupt pending. + cmp.eq p6,p0=r8,r0 +(p6) br.cond.sptk slave + + mov r8=cr.ivr // Got one. Must read ivr to accept it + mov cr.eoi=r0 // must write eoi to clear + movl r8=ap_entry // now jump to kernel entry + add r8 = r8,r6 // Relocate to boot node + ld8 r9=[r8],8 + ld8 r1=[r8] + mov b0=r9 + br b0 + +// Here is the kernel stack used for the fake PROM + .bss + .align 16384 +bootstack: + .skip 16384 +bootstacke: +initlock: + data4 diff -urN linux-2.4.0-test10/arch/ia64/sn/fprom/fw-emu.c linux-2.4.0-test10-lia/arch/ia64/sn/fprom/fw-emu.c --- linux-2.4.0-test10/arch/ia64/sn/fprom/fw-emu.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/fprom/fw-emu.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,487 @@ +/* + * PAL & SAL emulation. + * + * Copyright (C) 1998-2000 Hewlett-Packard Co + * Copyright (C) 1998-2000 David Mosberger-Tang + * + * + * Copyright (C) 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Jack Steiner (steiner@sgi.com) + */ +#include + +#include +#include +#include +#include +#include +#include "fpmem.h" + +#define MB (1024*1024UL) +#define GB (MB*1024UL) + +#define FPROM_BUG() do {while (1);} while (0) +#define MAX_NODES 128 +#define MAX_LSAPICS 512 +#define MAX_CPUS 512 +#define MAX_CPUS_NODE 4 +#define CPUS_PER_NODE 4 +#define CPUS_PER_FSB 2 +#define CPUS_PER_FSB_MASK (CPUS_PER_FSB-1) + +#define NUM_EFI_DESCS 2 + +typedef union ia64_nasid_va { + struct { + unsigned long off : 33; /* intra-region offset */ + unsigned long nasid : 7; /* NASID */ + unsigned long off2 : 21; /* fill */ + unsigned long reg : 3; /* region number */ + } f; + unsigned long l; + void *p; +} ia64_nasid_va; + +typedef struct { + unsigned long pc; + unsigned long gp; +} func_ptr_t; + +#define IS_VIRTUAL_MODE() ({struct ia64_psr psr; asm("mov %0=psr" : "=r"(psr)); psr.dt;}) +#define ADDR_OF(p) (IS_VIRTUAL_MODE() ? ((void*)((long)(p)+PAGE_OFFSET)) : ((void*) (p))) +#define __fwtab_pa(n,x) ({ia64_nasid_va _v; _v.l = (long) (x); _v.f.nasid = (x) ? (n) : 0; _v.f.reg = 0; _v.l;}) + +/* + * The following variables are passed thru registersfrom the configuration file and + * are set via the _start function. + */ +long base_nasid; +long num_cpus; +long bsp_entry_pc=0; +long num_nodes; +long app_entry_pc; +int bsp_lid; +func_ptr_t ap_entry; + + +static char fw_mem[( sizeof(efi_system_table_t) + + sizeof(efi_runtime_services_t) + + NUM_EFI_DESCS*sizeof(efi_config_table_t) + + sizeof(struct ia64_sal_systab) + + sizeof(struct ia64_sal_desc_entry_point) + + sizeof(struct ia64_sal_desc_ap_wakeup) + + sizeof(acpi_rsdp_t) + + sizeof(acpi_rsdt_t) + + sizeof(acpi_sapic_t) + + MAX_LSAPICS*(sizeof(acpi_entry_lsapic_t)) + + (1+8*MAX_NODES)*(sizeof(efi_memory_desc_t)) + + sizeof(ia64_sal_desc_ptc_t) + + + MAX_NODES*sizeof(ia64_sal_ptc_domain_info_t) + + + MAX_CPUS*sizeof(ia64_sal_ptc_domain_proc_entry_t) + + + 1024)] __attribute__ ((aligned (8))); + +/* + * Very ugly, but we need this in the simulator only. Once we run on + * real hw, this can all go away. + */ +extern void pal_emulator_static (void); + +asm (" + .text + .proc pal_emulator_static +pal_emulator_static: + mov r8=-1 + cmp.eq p6,p7=6,r28 /* PAL_PTCE_INFO */ +(p7) br.cond.sptk.few 1f + ;; + mov r8=0 /* status = 0 */ + movl r9=0x500000000 /* tc.base */ + movl r10=0x0000000200000003 /* count[0], count[1] */ + movl r11=0x1000000000002000 /* stride[0], stride[1] */ + br.cond.sptk.few rp + +1: cmp.eq p6,p7=14,r28 /* PAL_FREQ_RATIOS */ +(p7) br.cond.sptk.few 1f + mov r8=0 /* status = 0 */ + movl r9 =0x100000064 /* proc_ratio (1/100) */ + movl r10=0x100000100 /* bus_ratio<<32 (1/256) */ + movl r11=0x10000000a /* itc_ratio<<32 (1/100) */ + +1: cmp.eq p6,p7=22,r28 /* PAL_MC_DRAIN */ +(p7) br.cond.sptk.few 1f + mov r8=0 + br.cond.sptk.few rp + +1: cmp.eq p6,p7=23,r28 /* PAL_MC_EXPECTED */ +(p7) br.cond.sptk.few 1f + mov r8=0 + br.cond.sptk.few rp + +1: br.cond.sptk.few rp + .endp pal_emulator_static\n"); + + +static efi_status_t +efi_get_time (efi_time_t *tm, efi_time_cap_t *tc) +{ + if (tm) { + memset(tm, 0, sizeof(*tm)); + tm->year = 2000; + tm->month = 2; + tm->day = 13; + tm->hour = 10; + tm->minute = 11; + tm->second = 12; + } + + if (tc) { + tc->resolution = 10; + tc->accuracy = 12; + tc->sets_to_zero = 1; + } + + return EFI_SUCCESS; +} + +static void +efi_reset_system (int reset_type, efi_status_t status, unsigned long data_size, efi_char16_t *data) +{ + while(1); /* Is there a pseudo-op to stop medusa */ +} + +static efi_status_t +efi_success (void) +{ + return EFI_SUCCESS; +} + +static efi_status_t +efi_unimplemented (void) +{ + return EFI_UNSUPPORTED; +} + +static long +sal_emulator (long index, unsigned long in1, unsigned long in2, + unsigned long in3, unsigned long in4, unsigned long in5, + unsigned long in6, unsigned long in7) +{ + register long r9 asm ("r9") = 0; + register long r10 asm ("r10") = 0; + register long r11 asm ("r11") = 0; + long status; + + /* + * Don't do a "switch" here since that gives us code that + * isn't self-relocatable. + */ + status = 0; + if (index == SAL_FREQ_BASE) { + switch (in1) { + case SAL_FREQ_BASE_PLATFORM: + r9 = 500000000; + break; + + case SAL_FREQ_BASE_INTERVAL_TIMER: + /* + * Is this supposed to be the cr.itc frequency + * or something platform specific? The SAL + * doc ain't exactly clear on this... + */ + r9 = 700000000; + break; + + case SAL_FREQ_BASE_REALTIME_CLOCK: + r9 = 1; + break; + + default: + status = -1; + break; + } + } else if (index == SAL_SET_VECTORS) { + if (in1 == SAL_VECTOR_OS_BOOT_RENDEZ) { + func_ptr_t *fp; + fp = ADDR_OF(&ap_entry); + fp->pc = in2; + fp->gp = in3; + } else { + status = -1; + } + ; + } else if (index == SAL_GET_STATE_INFO) { + ; + } else if (index == SAL_GET_STATE_INFO_SIZE) { + ; + } else if (index == SAL_CLEAR_STATE_INFO) { + ; + } else if (index == SAL_MC_RENDEZ) { + ; + } else if (index == SAL_MC_SET_PARAMS) { + ; + } else if (index == SAL_CACHE_FLUSH) { + ; + } else if (index == SAL_CACHE_INIT) { + ; + } else if (index == SAL_UPDATE_PAL) { + ; + } else { + status = -1; + } + asm volatile ("" :: "r"(r9), "r"(r10), "r"(r11)); + return status; +} + + +/* + * This is here to work around a bug in egcs-1.1.1b that causes the + * compiler to crash (seems like a bug in the new alias analysis code. + */ +void * +id (long addr) +{ + return (void *) addr; +} + + +/* + * Fix the addresses in a function pointer by adding base node address + * to pc & gp. + */ +void +fix_function_pointer(void *fp) +{ + func_ptr_t *_fp; + + _fp = fp; + _fp->pc = __fwtab_pa(base_nasid, _fp->pc); + _fp->gp = __fwtab_pa(base_nasid, _fp->gp); +} + + +void +sys_fw_init (const char *args, int arglen, int bsp) +{ + /* + * Use static variables to keep from overflowing the RSE stack + */ + static efi_system_table_t *efi_systab; + static efi_runtime_services_t *efi_runtime; + static efi_config_table_t *efi_tables; + static ia64_sal_desc_ptc_t *sal_ptc; + static ia64_sal_ptc_domain_info_t *sal_ptcdi; + static ia64_sal_ptc_domain_proc_entry_t *sal_ptclid; + static acpi_rsdp_t *acpi_systab; + static acpi_rsdt_t *acpi_rsdt; + static acpi_sapic_t *acpi_sapic; + static acpi_entry_lsapic_t *acpi_lsapic; + static struct ia64_sal_systab *sal_systab; + static efi_memory_desc_t *efi_memmap, *md; + static unsigned long *pal_desc, *sal_desc; + static struct ia64_sal_desc_entry_point *sal_ed; + static struct ia64_boot_param *bp; + static struct ia64_sal_desc_ap_wakeup *sal_apwake; + static unsigned char checksum = 0; + static char *cp, *cmd_line, *vendor; + static int mdsize, domain, last_domain ; + static int cnode, nasid, cpu, num_memmd, cpus_found; + + /* + * Pass the parameter base address to the build_efi_xxx routines. + */ + build_init(8LL*GB*base_nasid); + + num_nodes = GetNumNodes(); + num_cpus = GetNumCpus(); + + + memset(fw_mem, 0, sizeof(fw_mem)); + + pal_desc = (unsigned long *) &pal_emulator_static; + sal_desc = (unsigned long *) &sal_emulator; + fix_function_pointer(&pal_emulator_static); + fix_function_pointer(&sal_emulator); + + /* Align this to 16 bytes, probably EFI does this */ + mdsize = (sizeof(efi_memory_desc_t) + 15) & ~15 ; + + cp = fw_mem; + efi_systab = (void *) cp; cp += sizeof(*efi_systab); + efi_runtime = (void *) cp; cp += sizeof(*efi_runtime); + efi_tables = (void *) cp; cp += NUM_EFI_DESCS*sizeof(*efi_tables); + sal_systab = (void *) cp; cp += sizeof(*sal_systab); + sal_ed = (void *) cp; cp += sizeof(*sal_ed); + sal_ptc = (void *) cp; cp += sizeof(*sal_ptc); + sal_apwake = (void *) cp; cp += sizeof(*sal_apwake); + acpi_systab = (void *) cp; cp += sizeof(*acpi_systab); + acpi_rsdt = (void *) cp; cp += sizeof(*acpi_rsdt); + acpi_sapic = (void *) cp; cp += sizeof(*acpi_sapic); + acpi_lsapic = (void *) cp; cp += num_cpus*sizeof(*acpi_lsapic); + vendor = (char *) cp; cp += 32; + efi_memmap = (void *) cp; cp += 8*32*sizeof(*efi_memmap); + sal_ptcdi = (void *) cp; cp += CPUS_PER_FSB*(1+num_nodes)*sizeof(*sal_ptcdi); + sal_ptclid = (void *) cp; cp += ((3+num_cpus)*sizeof(*sal_ptclid)+7)/8*8; + cmd_line = (void *) cp; + + if (args) { + if (arglen >= 1024) + arglen = 1023; + memcpy(cmd_line, args, arglen); + } else { + arglen = 0; + } + cmd_line[arglen] = '\0'; + strcpy(cmd_line, ""); + + memset(efi_systab, 0, sizeof(efi_systab)); + efi_systab->hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE; + efi_systab->hdr.revision = EFI_SYSTEM_TABLE_REVISION; + efi_systab->hdr.headersize = sizeof(efi_systab->hdr); + efi_systab->fw_vendor = __fwtab_pa(base_nasid, vendor); + efi_systab->fw_revision = 1; + efi_systab->runtime = __fwtab_pa(base_nasid, efi_runtime); + efi_systab->nr_tables = 2; + efi_systab->tables = __fwtab_pa(base_nasid, efi_tables); + memcpy(vendor, "S\0i\0l\0i\0c\0o\0n\0-\0G\0r\0a\0p\0h\0i\0c\0s\0\0", 32); + + efi_runtime->hdr.signature = EFI_RUNTIME_SERVICES_SIGNATURE; + efi_runtime->hdr.revision = EFI_RUNTIME_SERVICES_REVISION; + efi_runtime->hdr.headersize = sizeof(efi_runtime->hdr); + efi_runtime->get_time = __fwtab_pa(base_nasid, &efi_get_time); + efi_runtime->set_time = __fwtab_pa(base_nasid, &efi_unimplemented); + efi_runtime->get_wakeup_time = __fwtab_pa(base_nasid, &efi_unimplemented); + efi_runtime->set_wakeup_time = __fwtab_pa(base_nasid, &efi_unimplemented); + efi_runtime->set_virtual_address_map = __fwtab_pa(base_nasid, &efi_success); + efi_runtime->get_variable = __fwtab_pa(base_nasid, &efi_unimplemented); + efi_runtime->get_next_variable = __fwtab_pa(base_nasid, &efi_unimplemented); + efi_runtime->set_variable = __fwtab_pa(base_nasid, &efi_unimplemented); + efi_runtime->get_next_high_mono_count = __fwtab_pa(base_nasid, &efi_unimplemented); + efi_runtime->reset_system = __fwtab_pa(base_nasid, &efi_reset_system); + + efi_tables->guid = SAL_SYSTEM_TABLE_GUID; + efi_tables->table = __fwtab_pa(base_nasid, sal_systab); + efi_tables++; + efi_tables->guid = ACPI_TABLE_GUID; + efi_tables->table = __fwtab_pa(base_nasid, acpi_systab); + fix_function_pointer(&efi_unimplemented); + fix_function_pointer(&efi_get_time); + fix_function_pointer(&efi_success); + fix_function_pointer(&efi_reset_system); + + /* fill in the ACPI system table: */ + memcpy(acpi_systab->signature, "RSD PTR ", 8); + acpi_systab->rsdt = (acpi_rsdt_t*)__fwtab_pa(base_nasid, acpi_rsdt); + + memcpy(acpi_rsdt->header.signature, "RSDT",4); + acpi_rsdt->header.length = sizeof(acpi_rsdt_t); + acpi_rsdt->entry_ptrs[0] = __fwtab_pa(base_nasid, acpi_sapic); + + memcpy(acpi_sapic->header.signature, "SPIC ", 4); + acpi_sapic->header.length = sizeof(acpi_sapic_t)+num_cpus*sizeof(acpi_entry_lsapic_t); + for (cnode=0; cnodetype = ACPI_ENTRY_LOCAL_SAPIC; + acpi_lsapic->length = sizeof(acpi_entry_lsapic_t); + acpi_lsapic->acpi_processor_id = cnode*4+cpu; + acpi_lsapic->flags = LSAPIC_ENABLED|LSAPIC_PRESENT; + acpi_lsapic->eid = cpu; + acpi_lsapic->id = nasid; + acpi_lsapic++; + } + } + + + /* fill in the SAL system table: */ + memcpy(sal_systab->signature, "SST_", 4); + sal_systab->size = sizeof(*sal_systab); + sal_systab->sal_rev_minor = 1; + sal_systab->sal_rev_major = 0; + sal_systab->entry_count = 3; + sal_systab->ia32_bios_present = 0; + + strcpy(sal_systab->oem_id, "SGI"); + strcpy(sal_systab->product_id, "sn1"); + + /* fill in an entry point: */ + sal_ed->type = SAL_DESC_ENTRY_POINT; + sal_ed->pal_proc = __fwtab_pa(base_nasid, pal_desc[0]); + sal_ed->sal_proc = __fwtab_pa(base_nasid, sal_desc[0]); + sal_ed->gp = __fwtab_pa(base_nasid, sal_desc[1]); + + /* kludge the PTC domain info */ + sal_ptc->type = SAL_DESC_PTC; + sal_ptc->num_domains = 0; + sal_ptc->domain_info = __fwtab_pa(base_nasid, sal_ptcdi); + cpus_found = 0; + last_domain = -1; + sal_ptcdi--; + for (cnode=0; cnodenum_domains++; + sal_ptcdi++; + sal_ptcdi->proc_count = 0; + sal_ptcdi->proc_list = __fwtab_pa(base_nasid, sal_ptclid); + last_domain = domain; + } + sal_ptcdi->proc_count++; + sal_ptclid->id = nasid; + sal_ptclid->eid = cpu; + sal_ptclid++; + cpus_found++; + } + } + } + + if (cpus_found != num_cpus) + FPROM_BUG(); + + /* Make the AP WAKEUP entry */ + sal_apwake->type = SAL_DESC_AP_WAKEUP; + sal_apwake->mechanism = IA64_SAL_AP_EXTERNAL_INT; + sal_apwake->vector = 18; + + for (cp = (char *) sal_systab; cp < (char *) efi_memmap; ++cp) + checksum += *cp; + + sal_systab->checksum = -checksum; + + md = &efi_memmap[0]; + num_memmd = build_efi_memmap((void *)md, mdsize) ; + + bp = id(ZERO_PAGE_ADDR + (((long)base_nasid)<<33)); + bp->efi_systab = __fwtab_pa(base_nasid, &fw_mem); + bp->efi_memmap = __fwtab_pa(base_nasid, efi_memmap); + bp->efi_memmap_size = num_memmd*mdsize; + bp->efi_memdesc_size = mdsize; + bp->efi_memdesc_version = 1; + bp->command_line = __fwtab_pa(base_nasid, cmd_line); + bp->console_info.num_cols = 80; + bp->console_info.num_rows = 25; + bp->console_info.orig_x = 0; + bp->console_info.orig_y = 24; + bp->num_pci_vectors = 0; + bp->fpswa = 0; + + /* + * Now pick the BSP & store it LID value in + * a global variable. Note if BSP is greater than last cpu, + * pick the last cpu. + */ + for (cnode=0; cnode 0) + continue; + return; + } + } +} diff -urN linux-2.4.0-test10/arch/ia64/sn/fprom/main.c linux-2.4.0-test10-lia/arch/ia64/sn/fprom/main.c --- linux-2.4.0-test10/arch/ia64/sn/fprom/main.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/fprom/main.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,110 @@ +/* + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Jack Steiner (steiner@sgi.com) + */ + + + +#include +#include + +void bedrock_init(int); +void synergy_init(int, int); +void sys_fw_init (const char *args, int arglen, int bsp); + +volatile int bootmaster=0; /* Used to pick bootmaster */ +volatile int nasidmaster[128]={0}; /* Used to pick node/synergy masters */ +int init_done=0; +extern int bsp_lid; + +#define get_bit(b,p) (((*p)>>(b))&1) + +int +fmain(int lid, int bsp) { + int syn, nasid, cpu; + + /* + * First lets figure out who we are. This is done from the + * LID passed to us. + */ + nasid = (lid>>24); + syn = (lid>>17)&1; + cpu = (lid>>16)&1; + + /* + * Now pick a synergy master to initialize synergy registers. + */ + if (test_and_set_bit(syn, &nasidmaster[nasid]) == 0) { + synergy_init(nasid, syn); + test_and_set_bit(syn+2, &nasidmaster[nasid]); + } else + while (get_bit(syn+2, &nasidmaster[nasid]) == 0); + + /* + * Now pick a nasid master to initialize Bedrock registers. + */ + if (test_and_set_bit(8, &nasidmaster[nasid]) == 0) { + bedrock_init(nasid); + test_and_set_bit(9, &nasidmaster[nasid]); + } else + while (get_bit(9, &nasidmaster[nasid]) == 0); + + + /* + * Now pick a BSP & finish init. + */ + if (test_and_set_bit(0, &bootmaster) == 0) { + sys_fw_init(0, 0, bsp); + test_and_set_bit(1, &bootmaster); + } else + while (get_bit(1, &bootmaster) == 0); + + return (lid == bsp_lid); +} + + +void +bedrock_init(int nasid) +{ + nasid = nasid; /* to quiet gcc */ +} + + +void +synergy_init(int nasid, int syn) +{ + long *base; + long off; + + /* + * Enable all FSB flashed interrupts. + * ZZZ - I'd really like defines for this...... + */ + base = (long*)0x80000e0000000000LL; /* base of synergy regs */ + for (off = 0x2a0; off < 0x2e0; off+=8) /* offset for VEC_MASK_{0-3}_A/B */ + *(base+off/8) = -1LL; + + /* + * Set the NASID in the FSB_CONFIG register. + */ + base = (long*)0x80000e0000000450LL; + *base = (long)((nasid<<16)|(syn<<9)); +} + + +/* Why isnt there a bcopy/memcpy in lib64.a */ + +void* +memcpy(void * dest, const void *src, size_t count) +{ + char *s, *se, *d; + + for(d=dest, s=(char*)src, se=s+count; s" to create the initial control file). + +Script for running a LINUX kernel under medusa. +This script edits the control file and + - sets up the number of cpus & number of nodes + +(Note: the "st" command is useful for translating between +names and addresses). + +Usage: runsim -I [] # for initial setup + Path to directory in work tree for vmlinux + + runsim [-c ] [-u ] [-o ] [-B ] + [-N ] [-M] + + -H Help + -I Firsttime setup (create initial control file & link to kernel) + + -M Pipe output thru fmtmedusa + -B Boot processor number [Default: 0] + -c Path to control file. [Default: cf] + -u Specify the path to the linux file. [Default: vmlinux] + -o Output filename (copy of all commands/output) [Default: simout] + -N Specifies the cnode to load the kernel [Default: 0] + -X Specifies number of instructions to execute [Default: 0] + (Used only in auto test mode) + +END +exit 1 +} + + +IDEDISK=idedisk +SYM="vmlinux.sym" +SABLE=sable +CF="cf" +NODES=1 +CPUS=1 +LOADNODE=0 +BSP=0 +OUT="simout" +PROM=0 +INIT=0 +FMTMED=0 +STEPCNT=0 + +while getopts "B:HIMN:X:c:o:u:" c ; do + case ${c} in + H) help;; + B) BSP=${OPTARG};; + I) INIT=1;; + M) FMTMED=1;; + N) LOADNODE=${OPTARG};; + X) STEPCNT=${OPTARG};; + c) CF=${OPTARG};; + o) OUT=${OPTARG};; + u) LINUX=${OPTARG};; + \?) help;; + esac +done +shift `expr ${OPTIND} - 1` + +# Firsttime setup. Create a control_file & the link to vmlinux" +if [ $INIT -eq 1 ] ; then + if [ -f $CF ] ; then + echo "ERROR - wont overwrite an existing control file ($CF)" + exit 1 + fi + if [ $# -gt 0 ] ; then + rm -r -f vmlinux fprom + ln -s $1/vmlinux vmlinux + ln -s $1/vmlinux.sym vmlinux.sym + ln -s $1/arch/ia64/sn/fprom/fprom fprom + fi + cat <$CF + +# Template for a control file for running linux kernels +# under medusa. You probably want to make mods here but this is a +# good starting point. +# +# Note that uppercase names get translated to addresses +# in the run script. This allows you to set breakpoints easier. +# + + +setenv step_quantum 50 +setenv exceptionPrint off +setenv tsconsole on +setenv lastPCsize 10000 +#setenv consoleWindow on + +#setenv kernelPrintVaddr VSPRINTADDR +setenv interrupt_messages off +setenv symbol_table $SYM +setenv partialIntelChipSet on +setenv printIntelMessages off +setenv uart_echo on +setenv diskPresent 1 +setenv diskPath idedisk +setenv diskCylinders 611 +setenv diskHeads 16 +setenv diskSpt 63 +setenv bootDrive C +setenv low_power_mode on + +#setenv cpu_cache_type ia64_cac_128k_1w +#setenv uc_coherent yes +#setenv stop_on_uc_error yes +#setenv print_device_info on + +# This is the start address of the FPROM. It rarely changes. +setenv LOADPC 0x00100000 + +# Set kernel entry address. This rarely changes. +sr g 9 0xe000000000520000 + +# Memory map: +# setenv nodeN_memory_config 0xBSBSBSBS +# B=banksize (0=used, 1=64M, 2=128M,,5-1G, c=8M, d=16M, e=32M) +# S=bank enable (0=both disable, 3=both enable, 2=bank1 enable, 1=bank2 enable) +# rightmost digits are for bank 0, the lowest address +# +# You also need to set low nmemory so that the fake PROM understand the same memory map. +# Default to 16MB although this is not a valid hardware configuration (runs faster on medusa) + +setenv node0_memory_config 0xd1 # 16MB +setenv node0_nasid 0 # cnode 0 has NASID 0 +setenv node0_cpu_config 1 # enable only cpu 0 on the node +#setenv node1_memory_config 0xd1 # 16MB +#setenv node1_nasid 1 # cnode 1 has NASID 1 +#setenv node1_cpu_config 1 # enable only cpu 0 on the node + +setnode LOADNODE # Load FPROM & vmlinux on specified node +load fprom +LOAD LINUX + + +# Useful breakpoints to always have set. +# Add more if desired. +break 0xe000000000505e00 # dispatch_to_fault_handler +break panic # stop on panic +break die_if_kernel # may as well stop +END + echo "Basic control file created (in "cf"). You might want to edit" + echo "this file (at least, look at it)." + exit 0 +fi + +# Verify that the control file exists +if [ ! -f $CF ] ; then + echo "ERROR - no control file exists. Type" + echo " $0 -I # to create a prototype control file" + echo " OR" + echo " $0 -H # for more help" + exit 1 +fi + +# Determine if running multiple cpus +if [ $NODES -gt 1 -o $CPUS -gt 1 ] ; then + MP=1 +else + MP=0 +fi + +# Rebuild the idedisk +# !!!! Temporarily disabled +#gunzip -c /usr/idedisk_master.gz $IDEDISK +#chmod 777 $IDEDISK + +echo " .. locating magic address for vsprintf" +VSPRINTF="0X"`grep " vsprintf" $SYM | cut -f3 -d" "` +$TOOLS/$OBJDUMP --start-address=$VSPRINTF -d $LINUX | awk ' +/:/{ + while (substr($(NF-1),1,11) != "br.ret.sptk" || substr($NF,1,2) != "b0") + do { + getline; + } while(NF<2); + printf "0x%s0\n", substr($0,1,15); #last digit not valid, use a 0 + exit +}' > .vsprintaddr + + +# Build the .cf file from the user control file. The .cf file is +# identical except that the actual start & load addresses are inserted +# into the file. In addition, the FPROM commands for configuring memory +# and LIDs are generated. + +rm -f .cf +awk -v loadnode=$LOADNODE -v bsp=$BSP -v sym=$SYM -v vsprintaddr=`cat .vsprintaddr` -v idedisk=$IDEDISK -v unix=$LINUX ' +function strtonum(n) { + if (substr(n,1,2) != "0x") + return int(n) + n = substr(n,3) + r=0 + while (length(n) > 0) { + r = r*16+(index("0123456789abcdef", substr(n,1,1))-1) + n = substr(n,2) + } + return r + } +/^#/ {next} +/^$/ {next} +/VSPRINTADDR/ {print "setenv kernelPrintVaddr " vsprintaddr; next} +/IDEDISK/ {printf "setenv diskPath %s\n", idedisk; next} +/LOAD LINUX/ {printf "load %s\n", unix; next} +/LOADNODE/ {printf "setnode %d\n", loadnode; next} +/^setenv *LOADPC/ {loadpc = $3; next} +/^setenv *node._cpu_config/ {n=int(substr($2,5,1)); cpuconf[n] = strtonum($3); print; next} +/^setenv *node._memory_config/ {n=int(substr($2,5,1)); memconf[n] = strtonum($3); print; next} +/^setenv *node._nasid/ {n=int(substr($2,5,1)); nasid[n] = strtonum($3); print; next} + {print} +END { + # Generate the memmap info that starts at the beginning of + # the node the kernel was loaded on. + loadnasid = nasid[loadnode] + cnode = 0 + for (i=0; i<128; i++) { + if (memconf[i] != "") { + printf "sm 0x%x%08x 0x%x%04x%04x\n", + 2*loadnasid, 8*cnodes+8, memconf[i], cpuconf[i], nasid[i] + cnodes++ + cpus += substr("0112122312232334", cpuconf[i]+1,1) + } + } + printf "sm 0x%x00000000 0x%x%08x\n", 2*loadnasid, cnodes, cpus + printf "setenv number_of_nodes %d\n", cnodes + + # Now set the starting PC for each cpu. + cnode = 0 + lowcpu=-1 + for (i=0; i<128; i++) { + if (memconf[i] != "") { + printf "setnode %d\n", cnode + conf = cpuconf[i] + for (j=0; j<4; j++) { + if (conf != int(conf/2)*2) { + printf "setcpu %d\n", j + printf "sr g 8 %d\t\t# set BSP\n", bsp + printf "sr pc 0x%x%s\n", 2*loadnasid, substr(loadpc,3) + if (lowcpu == -1) { + lowcpu = j + } else { + printf "sr g 9 0\n" + } + } + conf = int(conf/2) + } + cnode++ + } + } + printf "setnode 0\n" + printf "setcpu %d\n", lowcpu + } +' <$CF >.cf + +# Check for errors & stop if any found +grep "ERROR:" .cf +[ $? -ne 0 ] || exit 1 + +# Now build the .cf1 & .cf2 control files. +egrep '^sm |^break ' .cf >.cf2 +egrep -v '^sm |^break |^run |^si |^quit ' .cf >.cf1 +if [ $STEPCNT -ne 0 ] ; then + echo "s $STEPCNT" >>.cf2 + echo "lastpc 1000" >>.cf2 + echo "q" >>.cf2 +fi +echo "script-on $OUT" >>.cf2 +echo "symbols on" >>.cf2 + +echo " .. running with $CPUS cpus and $NODES nodes." + +# Determine system type. Should go away after a while. +if [ $NODES -gt 1 -o $CPUS -gt 1 -o $STEPCNT -ne 0 ] ; then + SYSTYPE="mpsn1" +else + SYSTYPE="mpsn1" +fi + +# Now start medusa.... +if [ $FMTMED -ne 0 ] ; then + $MEDUSA -system $SYSTYPE -c .cf1 -i .cf2 | fmtmedusa +elif [ $STEPCNT -eq 0 ] ; then + $MEDUSA -system $SYSTYPE -c .cf1 -i .cf2 +else + $MEDUSA -system $SYSTYPE -c .cf1 -i .cf2 2>&1 +fi diff -urN linux-2.4.0-test10/arch/ia64/sn/io/Makefile linux-2.4.0-test10-lia/arch/ia64/sn/io/Makefile --- linux-2.4.0-test10/arch/ia64/sn/io/Makefile Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/Makefile Wed Nov 15 19:11:39 2000 @@ -0,0 +1,36 @@ +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 2000 Silicon Graphics, Inc. +# Copyright (C) Jack Steiner (steiner@sgi.com) +# +# +# Makefile for the linux kernel. +# +# 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 (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +CFLAGS := $(CFLAGS) -I. +CFLAGS := $(CFLAGS) -DLANGUAGE_C -D_LANGUAGE_C \ + -DBRINGUP -DDIRECT_L1_CONSOLE -DNUMA_BASE \ + -DSIMULATED_KLGRAPH \ + -DCONFIG_ARC64=1 -DNUMA_BASE -DNUMA_MIGR_CONTROL \ + -DLITTLE_ENDIAN -DSN -DREAL_HARDWARE -DNEW_INTERRUPTS +#-DMEDUSA_HACK +#-DXBRIDGE_REGS_SIM +O_TARGET := sgiio.o +O_OBJS := stubs.o sgi_if.o pciio.o pcibr.o xtalk.o xbow.o xswitch.o hubspc.o \ + klgraph_hack.o io.o hubdev.o \ + hcl.o labelcl.o invent.o klgraph.o klconflib.o sgi_io_sim.o \ + module.o sgi_io_init.o klgraph_hack.o ml_SN_init.o \ + ml_SN_intr.o ip37.o \ + ml_iograph.o hcl_util.o cdl.o \ + mem_refcnt.o devsupport.o alenlist.o pci_bus_cvlink.o \ + eeprom.o pci.o pci_dma.o + +include $(TOPDIR)/Rules.make diff -urN linux-2.4.0-test10/arch/ia64/sn/io/alenlist.c linux-2.4.0-test10-lia/arch/ia64/sn/io/alenlist.c --- linux-2.4.0-test10/arch/ia64/sn/io/alenlist.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/alenlist.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,901 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +/* Implementation of Address/Length Lists. */ + + +#include +#include +#include +#include +#include +#include + +/* + * Logically, an Address/Length List is a list of Pairs, where each pair + * holds an Address and a Length, all in some Address Space. In this + * context, "Address Space" is a particular Crosstalk Widget address + * space, a PCI device address space, a VME bus address space, a + * physical memory address space, etc. + * + * The main use for these Lists is to provide a single mechanism that + * describes where in an address space a DMA occurs. This allows the + * various I/O Bus support layers to provide a single interface for + * DMA mapping and DMA translation without regard to how the DMA target + * was specified by upper layers. The upper layers commonly specify a + * DMA target via a buf structure page list, a kernel virtual address, + * a user virtual address, a vector of addresses (a la uio and iov), + * or possibly a pfn list. + * + * Address/Length Lists also enable drivers to take advantage of their + * inate scatter/gather capabilities in systems where some address + * translation may be required between bus adapters. The driver forms + * a List that represents physical memory targets. This list is passed + * to the various adapters, which apply various translations. The final + * list that's returned to the driver is in terms of its local address + * address space -- addresses which can be passed off to a scatter/gather + * capable DMA controller. + * + * The current implementation is intended to be useful both in kernels + * that support interrupt threads (INTR_KTHREAD) and in systems that do + * not support interrupt threads. Of course, in the latter case, some + * interfaces can be called only within a suspendable context. + * + * Basic operations on Address/Length Lists include: + * alenlist_create Create a list + * alenlist_clear Clear a list + * alenlist_destroy Destroy a list + * alenlist_append Append a Pair to the end of a list + * alenlist_replace Replace a Pair in the middle of a list + * alenlist_get Get an Address/Length Pair from a list + * alenlist_size Return the number of Pairs in a list + * alenlist_concat Append one list to the end of another + * alenlist_clone Create a new copy of a list + * + * Operations that convert from upper-level specifications to Address/ + * Length Lists currently include: + * kvaddr_to_alenlist Convert from a kernel virtual address + * uvaddr_to_alenlist Convert from a user virtual address + * buf_to_alenlist Convert from a buf structure + * alenlist_done Tell system that we're done with an alenlist + * obtained from a conversion. + * Additional convenience operations: + * alenpair_init Create a list and initialize it with a Pair + * alenpair_get Peek at the first pair on a List + * + * A supporting type for Address/Length Lists is an alenlist_cursor_t. A + * cursor marks a position in a List, and determines which Pair is fetched + * by alenlist_get. + * alenlist_cursor_create Allocate and initialize a cursor + * alenlist_cursor_destroy Free space consumed by a cursor + * alenlist_cursor_init (Re-)Initialize a cursor to point + * to the start of a list + * alenlist_cursor_clone Clone a cursor (at the current offset) + * alenlist_cursor_offset Return the number of bytes into + * a list that this cursor marks + * Multiple cursors can point at various points into a List. Also, each + * list maintains one "internal cursor" which may be updated by alenlist_clear + * and alenlist_get. If calling code simply wishes to scan sequentially + * through a list starting at the beginning, and if it is the only user of + * a list, it can rely on this internal cursor rather than managing a + * separate explicit cursor. + * + * The current implementation allows callers to allocate both cursors and + * the lists as local stack (structure) variables. This allows for some + * extra efficiency at the expense of forward binary compatibility. It + * is recommended that customer drivers refrain from local allocation. + * In fact, we likely will choose to move the structures out of the public + * header file into a private place in order to discourage this usage. + * + * Currently, no locking is provided by the alenlist implementation. + * + * Implementation notes: + * For efficiency, Pairs are grouped into "chunks" of, say, 32 Pairs + * and a List consists of some number of these chunks. Chunks are completely + * invisible to calling code. Chunks should be large enough to hold most + * standard-sized DMA's, but not so large that they consume excessive space. + * + * It is generally expected that Lists will be constructed at one time and + * scanned at a later time. It is NOT expected that drivers will scan + * a List while the List is simultaneously extended, although this is + * theoretically possible with sufficient upper-level locking. + * + * In order to support demands of Real-Time drivers and in order to support + * swapping under low-memory conditions, we support the concept of a + * "pre-allocated fixed-sized List". After creating a List with + * alenlist_create, a driver may explicitly grow the list (via "alenlist_grow") + * to a specific number of Address/Length pairs. It is guaranteed that future + * operations involving this list will never automatically grow the list + * (i.e. if growth is ever required, the operation will fail). Additionally, + * operations that use alenlist's (e.g. DMA operations) accept a flag which + * causes processing to take place "in-situ"; that is, the input alenlist + * entries are replaced with output alenlist entries. The combination of + * pre-allocated Lists and in-situ processing allows us to avoid the + * potential deadlock scenario where we sleep (waiting for memory) in the + * swap out path. + * + * For debugging, we track the number of allocated Lists in alenlist_count + * the number of allocated chunks in alenlist_chunk_count, and the number + * of allocate cursors in alenlist_cursor_count. We also provide a debug + * routine, alenlist_show, which dumps the contents of an Address/Length List. + * + * Currently, Lists are formed by drivers on-demand. Eventually, we may + * associate an alenlist with a buf structure and keep it up to date as + * we go along. In that case, buf_to_alenlist simply returns a pointer + * to the existing List, and increments the Lists's reference count. + * alenlist_done would decrement the reference count and destroys the List + * if it was the last reference. + * + * Eventually alenlist's may allow better support for user-level scatter/ + * gather operations (e.g. via readv/writev): With proper support, we + * could potentially handle a vector of reads with a single scatter/gather + * DMA operation. This could be especially useful on NUMA systems where + * there's more of a reason for users to use vector I/O operations. + * + * Eventually, alenlist's may replace kaio lists, vhand page lists, + * buffer cache pfdat lists, DMA page lists, etc. + */ + +/* Opaque data types */ + +/* An Address/Length pair. */ +typedef struct alen_s { + alenaddr_t al_addr; + size_t al_length; +} alen_t; + +/* + * Number of elements in one chunk of an Address/Length List. + * + * This size should be sufficient to hold at least an "average" size + * DMA request. Must be at least 1, and should be a power of 2, + * for efficiency. + */ +#define ALEN_CHUNK_SZ ((512*1024)/NBPP) + +/* + * A fixed-size set of Address/Length Pairs. Chunks of Pairs are strung together + * to form a complete Address/Length List. Chunking is entirely hidden within the + * alenlist implementation, and it simply makes allocation and growth of lists more + * efficient. + */ +typedef struct alenlist_chunk_s { + alen_t alc_pair[ALEN_CHUNK_SZ];/* list of addr/len pairs */ + struct alenlist_chunk_s *alc_next; /* point to next chunk of pairs */ +} *alenlist_chunk_t; + +/* + * An Address/Length List. An Address/Length List is allocated with alenlist_create. + * Alternatively, a list can be allocated on the stack (local variable of type + * alenlist_t) and initialized with alenpair_init or with a combination of + * alenlist_clear and alenlist_append, etc. Code which statically allocates these + * structures loses forward binary compatibility! + * + * A statically allocated List is sufficiently large to hold ALEN_CHUNK_SZ pairs. + */ +struct alenlist_s { + unsigned short al_flags; + unsigned short al_logical_size; /* logical size of list, in pairs */ + unsigned short al_actual_size; /* actual size of list, in pairs */ + struct alenlist_chunk_s *al_last_chunk; /* pointer to last logical chunk */ + struct alenlist_cursor_s al_cursor; /* internal cursor */ + struct alenlist_chunk_s al_chunk; /* initial set of pairs */ + alenaddr_t al_compaction_address; /* used to compact pairs */ +}; + +/* al_flags field */ +#define AL_FIXED_SIZE 0x1 /* List is pre-allocated, and of fixed size */ + + +zone_t *alenlist_zone = NULL; +zone_t *alenlist_chunk_zone = NULL; +zone_t *alenlist_cursor_zone = NULL; + +#if DEBUG +int alenlist_count=0; /* Currently allocated Lists */ +int alenlist_chunk_count = 0; /* Currently allocated chunks */ +int alenlist_cursor_count = 0; /* Currently allocate cursors */ +#define INCR_COUNT(ptr) atomicAddInt((ptr), 1); +#define DECR_COUNT(ptr) atomicAddInt((ptr), -1); +#else +#define INCR_COUNT(ptr) +#define DECR_COUNT(ptr) +#endif /* DEBUG */ + +#if DEBUG +static void alenlist_show(alenlist_t); +#endif /* DEBUG */ + +/* + * Initialize Address/Length List management. One time initialization. + */ +void +alenlist_init(void) +{ + alenlist_zone = kmem_zone_init(sizeof(struct alenlist_s), "alenlist"); + alenlist_chunk_zone = kmem_zone_init(sizeof(struct alenlist_chunk_s), "alchunk"); + alenlist_cursor_zone = kmem_zone_init(sizeof(struct alenlist_cursor_s), "alcursor"); +#if DEBUG + idbg_addfunc("alenshow", alenlist_show); +#endif /* DEBUG */ +} + + +/* + * Initialize an Address/Length List cursor. + */ +static void +do_cursor_init(alenlist_t alenlist, alenlist_cursor_t cursorp) +{ + cursorp->al_alenlist = alenlist; + cursorp->al_offset = 0; + cursorp->al_chunk = &alenlist->al_chunk; + cursorp->al_index = 0; + cursorp->al_bcount = 0; +} + + +/* + * Create an Address/Length List, and clear it. + * Set the cursor to the beginning. + */ +alenlist_t +alenlist_create(unsigned flags) +{ + alenlist_t alenlist; + + alenlist = kmem_zone_alloc(alenlist_zone, flags & AL_NOSLEEP ? VM_NOSLEEP : 0); + if (alenlist) { + INCR_COUNT(&alenlist_count); + + alenlist->al_flags = 0; + alenlist->al_logical_size = 0; + alenlist->al_actual_size = ALEN_CHUNK_SZ; + alenlist->al_last_chunk = &alenlist->al_chunk; + alenlist->al_chunk.alc_next = NULL; + do_cursor_init(alenlist, &alenlist->al_cursor); + } + + return(alenlist); +} + + +/* + * Grow an Address/Length List so that all resources needed to contain + * the specified number of Pairs are pre-allocated. An Address/Length + * List that has been explicitly "grown" will never *automatically* + * grow, shrink, or be destroyed. + * + * Pre-allocation is useful for Real-Time drivers and for drivers that + * may be used along the swap-out path and therefore cannot afford to + * sleep until memory is freed. + * + * The cursor is set to the beginning of the list. + */ +int +alenlist_grow(alenlist_t alenlist, size_t npairs) +{ + /* + * This interface should be used relatively rarely, so + * the implementation is kept simple: We clear the List, + * then append npairs bogus entries. Finally, we mark + * the list as FIXED_SIZE and re-initialize the internal + * cursor. + */ + + /* + * Temporarily mark as non-fixed size, since we're about + * to shrink and expand it. + */ + alenlist->al_flags &= ~AL_FIXED_SIZE; + + /* Free whatever was in the alenlist. */ + alenlist_clear(alenlist); + + /* Allocate everything that we need via automatic expansion. */ + while (npairs--) + if (alenlist_append(alenlist, 0, 0, AL_NOCOMPACT) == ALENLIST_FAILURE) + return(ALENLIST_FAILURE); + + /* Now, mark as FIXED_SIZE */ + alenlist->al_flags |= AL_FIXED_SIZE; + + /* Clear out bogus entries */ + alenlist_clear(alenlist); + + /* Initialize internal cursor to the beginning */ + do_cursor_init(alenlist, &alenlist->al_cursor); + + return(ALENLIST_SUCCESS); +} + + +/* + * Clear an Address/Length List so that it holds no pairs. + */ +void +alenlist_clear(alenlist_t alenlist) +{ + alenlist_chunk_t chunk, freechunk; + + /* + * If this List is not FIXED_SIZE, free all the + * extra chunks. + */ + if (!(alenlist->al_flags & AL_FIXED_SIZE)) { + /* First, free any extension alenlist chunks */ + chunk = alenlist->al_chunk.alc_next; + while (chunk) { + freechunk = chunk; + chunk = chunk->alc_next; + kmem_zone_free(alenlist_chunk_zone, freechunk); + DECR_COUNT(&alenlist_chunk_count); + } + alenlist->al_actual_size = ALEN_CHUNK_SZ; + alenlist->al_chunk.alc_next = NULL; + } + + alenlist->al_logical_size = 0; + alenlist->al_last_chunk = &alenlist->al_chunk; + do_cursor_init(alenlist, &alenlist->al_cursor); +} + + +/* + * Create and initialize an Address/Length Pair. + * This is intended for degenerate lists, consisting of a single + * address/length pair. + */ +alenlist_t +alenpair_init( alenaddr_t address, + size_t length) +{ + alenlist_t alenlist; + + alenlist = alenlist_create(0); + + alenlist->al_logical_size = 1; + ASSERT(alenlist->al_last_chunk == &alenlist->al_chunk); + alenlist->al_chunk.alc_pair[0].al_length = length; + alenlist->al_chunk.alc_pair[0].al_addr = address; + + return(alenlist); +} + +/* + * Return address/length from a degenerate (1-pair) List, or + * first pair from a larger list. Does NOT update the internal cursor, + * so this is an easy way to peek at a start address. + */ +int +alenpair_get( alenlist_t alenlist, + alenaddr_t *address, + size_t *length) +{ + if (alenlist->al_logical_size == 0) + return(ALENLIST_FAILURE); + + *length = alenlist->al_chunk.alc_pair[0].al_length; + *address = alenlist->al_chunk.alc_pair[0].al_addr; + return(ALENLIST_SUCCESS); +} + + +/* + * Destroy an Address/Length List. + */ +void +alenlist_destroy(alenlist_t alenlist) +{ + if (alenlist == NULL) + return; + + /* + * Turn off FIXED_SIZE so this List can be + * automatically shrunk. + */ + alenlist->al_flags &= ~AL_FIXED_SIZE; + + /* Free extension chunks first */ + if (alenlist->al_chunk.alc_next) + alenlist_clear(alenlist); + + /* Now, free the alenlist itself */ + kmem_zone_free(alenlist_zone, alenlist); + DECR_COUNT(&alenlist_count); +} + +/* + * Release an Address/Length List. + * This is in preparation for a day when alenlist's may be longer-lived, and + * perhaps associated with a buf structure. We'd add a reference count, and + * this routine would decrement the count. For now, we create alenlist's on + * on demand and free them when done. If the driver is not explicitly managing + * a List for its own use, it should call alenlist_done rather than alenlist_destroy. + */ +void +alenlist_done(alenlist_t alenlist) +{ + alenlist_destroy(alenlist); +} + + +/* + * Append another address/length to the end of an Address/Length List, + * growing the list if permitted and necessary. + * + * Returns: SUCCESS/FAILURE + */ +int +alenlist_append( alenlist_t alenlist, /* append to this list */ + alenaddr_t address, /* address to append */ + size_t length, /* length to append */ + unsigned flags) +{ + alen_t *alenp; + int index, last_index; + + index = alenlist->al_logical_size % ALEN_CHUNK_SZ; + + if ((alenlist->al_logical_size > 0)) { + /* + * See if we can compact this new pair in with the previous entry. + * al_compaction_address holds that value that we'd need to see + * in order to compact. + */ + if (!(flags & AL_NOCOMPACT) && + (alenlist->al_compaction_address == address)) { + last_index = (alenlist->al_logical_size-1) % ALEN_CHUNK_SZ; + alenp = &(alenlist->al_last_chunk->alc_pair[last_index]); + alenp->al_length += length; + alenlist->al_compaction_address += length; + return(ALENLIST_SUCCESS); + } + + /* + * If we're out of room in this chunk, move to a new chunk. + */ + if (index == 0) { + if (alenlist->al_flags & AL_FIXED_SIZE) { + alenlist->al_last_chunk = alenlist->al_last_chunk->alc_next; + + /* If we're out of space in a FIXED_SIZE List, quit. */ + if (alenlist->al_last_chunk == NULL) { + ASSERT(alenlist->al_logical_size == alenlist->al_actual_size); + return(ALENLIST_FAILURE); + } + } else { + alenlist_chunk_t new_chunk; + + new_chunk = kmem_zone_alloc(alenlist_chunk_zone, + flags & AL_NOSLEEP ? VM_NOSLEEP : 0); + + if (new_chunk == NULL) + return(ALENLIST_FAILURE); + + alenlist->al_last_chunk->alc_next = new_chunk; + new_chunk->alc_next = NULL; + alenlist->al_last_chunk = new_chunk; + alenlist->al_actual_size += ALEN_CHUNK_SZ; + INCR_COUNT(&alenlist_chunk_count); + } + } + } + + alenp = &(alenlist->al_last_chunk->alc_pair[index]); + alenp->al_addr = address; + alenp->al_length = length; + + alenlist->al_logical_size++; + alenlist->al_compaction_address = address + length; + + return(ALENLIST_SUCCESS); +} + + +/* + * Replace an item in an Address/Length List. Cursor is updated so + * that alenlist_get will get the next item in the list. This interface + * is not very useful for drivers; but it is useful to bus providers + * that need to translate between address spaced in situ. The old Address + * and Length are returned. + */ +/* ARGSUSED */ +int +alenlist_replace( alenlist_t alenlist, /* in: replace in this list */ + alenlist_cursor_t cursorp, /* inout: which item to replace */ + alenaddr_t *addrp, /* inout: address */ + size_t *lengthp, /* inout: length */ + unsigned flags) +{ + alen_t *alenp; + alenlist_chunk_t chunk; + unsigned int index; + size_t length; + alenaddr_t addr; + + if ((addrp == NULL) || (lengthp == NULL)) + return(ALENLIST_FAILURE); + + if (alenlist->al_logical_size == 0) + return(ALENLIST_FAILURE); + + addr = *addrp; + length = *lengthp; + + /* + * If no cursor explicitly specified, use the Address/Length List's + * internal cursor. + */ + if (cursorp == NULL) + cursorp = &alenlist->al_cursor; + + chunk = cursorp->al_chunk; + index = cursorp->al_index; + + ASSERT(cursorp->al_alenlist == alenlist); + if (cursorp->al_alenlist != alenlist) + return(ALENLIST_FAILURE); + + alenp = &chunk->alc_pair[index]; + + /* Return old values */ + *addrp = alenp->al_length; + *lengthp = alenp->al_addr; + + /* Set up new values */ + alenp->al_length = length; + alenp->al_addr = addr; + + /* Update cursor to point to next item */ + cursorp->al_bcount = length; + + return(ALENLIST_SUCCESS); +} + + +/* + * Initialize a cursor in order to walk an alenlist. + * An alenlist_cursor always points to the last thing that was obtained + * from the list. If al_chunk is NULL, then nothing has yet been obtained. + * + * Note: There is an "internal cursor" associated with every Address/Length List. + * For users that scan sequentially through a List, it is more efficient to + * simply use the internal cursor. The caller must insure that no other users + * will simultaneously scan the List. The caller can reposition the internal + * cursor by calling alenlist_cursor_init with a NULL cursorp. + */ +int +alenlist_cursor_init(alenlist_t alenlist, size_t offset, alenlist_cursor_t cursorp) +{ + size_t byte_count; + + if (cursorp == NULL) + cursorp = &alenlist->al_cursor; + + /* Get internal cursor's byte count for use as a hint. + * + * If the internal cursor points passed the point that we're interested in, + * we need to seek forward from the beginning. Otherwise, we can seek forward + * from the internal cursor. + */ + if ((offset > 0) && + ((byte_count = alenlist_cursor_offset(alenlist, (alenlist_cursor_t)NULL)) <= offset)) { + offset -= byte_count; + alenlist_cursor_clone(alenlist, NULL, cursorp); + } else + do_cursor_init(alenlist, cursorp); + + /* We could easily speed this up, but it shouldn't be used very often. */ + while (offset != 0) { + alenaddr_t addr; + size_t length; + + if (alenlist_get(alenlist, cursorp, offset, &addr, &length, 0) != ALENLIST_SUCCESS) + return(ALENLIST_FAILURE); + offset -= length; + } + return(ALENLIST_SUCCESS); +} + + +/* + * Copy a cursor. The source cursor is either an internal alenlist cursor + * or an explicit cursor. + */ +int +alenlist_cursor_clone( alenlist_t alenlist, + alenlist_cursor_t cursorp_in, + alenlist_cursor_t cursorp_out) +{ + ASSERT(cursorp_out); + + if (alenlist && cursorp_in) + if (alenlist != cursorp_in->al_alenlist) + return(ALENLIST_FAILURE); + + if (alenlist) + *cursorp_out = alenlist->al_cursor; /* small structure copy */ + else if (cursorp_in) + *cursorp_out = *cursorp_in; /* small structure copy */ + else + return(ALENLIST_FAILURE); /* no source */ + + return(ALENLIST_SUCCESS); +} + +/* + * Return the number of bytes passed so far according to the specified cursor. + * If cursorp is NULL, use the alenlist's internal cursor. + */ +size_t +alenlist_cursor_offset(alenlist_t alenlist, alenlist_cursor_t cursorp) +{ + ASSERT(!alenlist || !cursorp || (alenlist == cursorp->al_alenlist)); + + if (cursorp == NULL) { + ASSERT(alenlist); + cursorp = &alenlist->al_cursor; + } + + return(cursorp->al_offset); +} + +/* + * Allocate and initialize an Address/Length List cursor. + */ +alenlist_cursor_t +alenlist_cursor_create(alenlist_t alenlist, unsigned flags) +{ + alenlist_cursor_t cursorp; + + ASSERT(alenlist != NULL); + cursorp = kmem_zone_alloc(alenlist_cursor_zone, flags & AL_NOSLEEP ? VM_NOSLEEP : 0); + if (cursorp) { + INCR_COUNT(&alenlist_cursor_count); + alenlist_cursor_init(alenlist, 0, cursorp); + } + return(cursorp); +} + +/* + * Free an Address/Length List cursor. + */ +void +alenlist_cursor_destroy(alenlist_cursor_t cursorp) +{ + DECR_COUNT(&alenlist_cursor_count); + kmem_zone_free(alenlist_cursor_zone, cursorp); +} + + +/* + * Fetch an address/length pair from an Address/Length List. Update + * the "cursor" so that next time this routine is called, we'll get + * the next address range. Never return a length that exceeds maxlength + * (if non-zero). If maxlength is a power of 2, never return a length + * that crosses a maxlength boundary. [This may seem strange at first, + * but it's what many drivers want.] + * + * Returns: SUCCESS/FAILURE + */ +int +alenlist_get( alenlist_t alenlist, /* in: get from this list */ + alenlist_cursor_t cursorp, /* inout: which item to get */ + size_t maxlength, /* in: at most this length */ + alenaddr_t *addrp, /* out: address */ + size_t *lengthp, /* out: length */ + unsigned flags) +{ + alen_t *alenp; + alenlist_chunk_t chunk; + unsigned int index; + size_t bcount; + size_t length; + + /* + * If no cursor explicitly specified, use the Address/Length List's + * internal cursor. + */ + if (cursorp == NULL) { + if (alenlist->al_logical_size == 0) + return(ALENLIST_FAILURE); + cursorp = &alenlist->al_cursor; + } + + chunk = cursorp->al_chunk; + index = cursorp->al_index; + bcount = cursorp->al_bcount; + + ASSERT(cursorp->al_alenlist == alenlist); + if (cursorp->al_alenlist != alenlist) + return(ALENLIST_FAILURE); + + alenp = &chunk->alc_pair[index]; + length = alenp->al_length - bcount; + + /* Bump up to next pair, if we're done with this pair. */ + if (length == 0) { + cursorp->al_bcount = bcount = 0; + cursorp->al_index = index = (index + 1) % ALEN_CHUNK_SZ; + + /* Bump up to next chunk, if we're done with this chunk. */ + if (index == 0) { + if (cursorp->al_chunk == alenlist->al_last_chunk) + return(ALENLIST_FAILURE); + chunk = chunk->alc_next; + ASSERT(chunk != NULL); + } else { + /* If in last chunk, don't go beyond end. */ + if (cursorp->al_chunk == alenlist->al_last_chunk) { + int last_size = alenlist->al_logical_size % ALEN_CHUNK_SZ; + if (last_size && (index >= last_size)) + return(ALENLIST_FAILURE); + } + } + + alenp = &chunk->alc_pair[index]; + length = alenp->al_length; + } + + /* Constrain what we return according to maxlength */ + if (maxlength) { + size_t maxlen1 = maxlength - 1; + + if ((maxlength & maxlen1) == 0) /* power of 2 */ + maxlength -= + ((alenp->al_addr + cursorp->al_bcount) & maxlen1); + + length = MIN(maxlength, length); + } + + /* Update the cursor, if desired. */ + if (!(flags & AL_LEAVE_CURSOR)) { + cursorp->al_bcount += length; + cursorp->al_chunk = chunk; + } + + *lengthp = length; + *addrp = alenp->al_addr + bcount; + + return(ALENLIST_SUCCESS); +} + + +/* + * Return the number of pairs in the specified Address/Length List. + * (For FIXED_SIZE Lists, this returns the logical size of the List, + * not the actual capacity of the List.) + */ +int +alenlist_size(alenlist_t alenlist) +{ + return(alenlist->al_logical_size); +} + + +/* + * Concatenate two Address/Length Lists. + */ +void +alenlist_concat(alenlist_t from, + alenlist_t to) +{ + struct alenlist_cursor_s cursor; + alenaddr_t addr; + size_t length; + + alenlist_cursor_init(from, 0, &cursor); + + while(alenlist_get(from, &cursor, (size_t)0, &addr, &length, 0) == ALENLIST_SUCCESS) + alenlist_append(to, addr, length, 0); +} + +/* + * Create a copy of a list. + * (Not all attributes of the old list are cloned. For instance, if + * a FIXED_SIZE list is cloned, the resulting list is NOT FIXED_SIZE.) + */ +alenlist_t +alenlist_clone(alenlist_t old_list, unsigned flags) +{ + alenlist_t new_list; + + new_list = alenlist_create(flags); + if (new_list != NULL) + alenlist_concat(old_list, new_list); + + return(new_list); +} + + +/* + * Convert a kernel virtual address to a Physical Address/Length List. + */ +alenlist_t +kvaddr_to_alenlist(alenlist_t alenlist, caddr_t kvaddr, size_t length, unsigned flags) +{ + alenaddr_t paddr; + long offset; + size_t piece_length; + int created_alenlist; + + if (length <=0) + return(NULL); + + /* If caller supplied a List, use it. Otherwise, allocate one. */ + if (alenlist == NULL) { + alenlist = alenlist_create(0); + created_alenlist = 1; + } else { + alenlist_clear(alenlist); + created_alenlist = 0; + } + + paddr = kvtophys(kvaddr); + offset = poff(kvaddr); + + /* Handle first page */ + piece_length = MIN(NBPP - offset, length); + if (alenlist_append(alenlist, paddr, piece_length, flags) == ALENLIST_FAILURE) + goto failure; + length -= piece_length; + kvaddr += piece_length; + + /* Handle middle pages */ + while (length >= NBPP) { + paddr = kvtophys(kvaddr); + if (alenlist_append(alenlist, paddr, NBPP, flags) == ALENLIST_FAILURE) + goto failure; + length -= NBPP; + kvaddr += NBPP; + } + + /* Handle last page */ + if (length) { + ASSERT(length < NBPP); + paddr = kvtophys(kvaddr); + if (alenlist_append(alenlist, paddr, length, flags) == ALENLIST_FAILURE) + goto failure; + } + + alenlist_cursor_init(alenlist, 0, NULL); + return(alenlist); + +failure: + if (created_alenlist) + alenlist_destroy(alenlist); + return(NULL); +} + + +#if DEBUG +static void +alenlist_show(alenlist_t alenlist) +{ + struct alenlist_cursor_s cursor; + alenaddr_t addr; + size_t length; + int i = 0; + + alenlist_cursor_init(alenlist, 0, &cursor); + + qprintf("Address/Length List@0x%x:\n", alenlist); + qprintf("logical size=0x%x actual size=0x%x last_chunk at 0x%x\n", + alenlist->al_logical_size, alenlist->al_actual_size, + alenlist->al_last_chunk); + qprintf("cursor: chunk=0x%x index=%d offset=0x%x\n", + alenlist->al_cursor.al_chunk, + alenlist->al_cursor.al_index, + alenlist->al_cursor.al_bcount); + while(alenlist_get(alenlist, &cursor, (size_t)0, &addr, &length, 0) == ALENLIST_SUCCESS) + qprintf("%d:\t0x%lx 0x%lx\n", ++i, addr, length); +} +#endif /* DEBUG */ diff -urN linux-2.4.0-test10/arch/ia64/sn/io/cdl.c linux-2.4.0-test10-lia/arch/ia64/sn/io/cdl.c --- linux-2.4.0-test10/arch/ia64/sn/io/cdl.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/cdl.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,233 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +#include +#include +#include +#include +#include +#include +#include +#include "asm/sn/ioerror_handling.h" +#include + +#ifdef BRINGUP +/* these get called directly in cdl_add_connpt in fops bypass hack */ +extern int pcibr_attach(devfs_handle_t); +extern int xbow_attach(devfs_handle_t); +#endif /* BRINGUP */ + +/* + * cdl: Connection and Driver List + * + * We are not porting this to Linux. Devices are registered via + * the normal Linux PCI layer. This is a very simplified version + * of cdl that will allow us to register and call our very own + * IO Infrastructure Drivers e.g. pcibr. + */ + +struct cdl { + int part_num; + int mfg_num; + int (*attach) (devfs_handle_t); +} dummy_reg; + +#if !defined(CONFIG_SGI_IP27) +typedef struct cdl *cdl_p; +#endif + +#define MAX_SGI_IO_INFRA_DRVR 4 +struct cdl sgi_infrastructure_drivers[MAX_SGI_IO_INFRA_DRVR] = +{ + { XBRIDGE_WIDGET_PART_NUM, XBRIDGE_WIDGET_MFGR_NUM, pcibr_attach /* &pcibr_fops */}, + { BRIDGE_WIDGET_PART_NUM, BRIDGE_WIDGET_MFGR_NUM, pcibr_attach /* &pcibr_fops */}, + { XXBOW_WIDGET_PART_NUM, XXBOW_WIDGET_MFGR_NUM, xbow_attach /* &xbow_fops */}, + { XBOW_WIDGET_PART_NUM, XBOW_WIDGET_MFGR_NUM, xbow_attach /* &xbow_fops */}, +}; + +/* + * cdl_new: Called by pciio and xtalk. + */ +cdl_p +cdl_new(char *name, char *k1str, char *k2str) +{ + /* + * Just return a dummy pointer. + */ + return((cdl_p)&dummy_reg); +} + +/* + * cdl_del: Do nothing. + */ +void +cdl_del(cdl_p reg) +{ + printk("SGI IO INFRASTRUCTURE - cdl_del not supported.\n"); +} + +/* + * cdl_add_driver: The driver part number and manufacturers number + * are statically initialized above. + * + Do nothing. + */ +int +cdl_add_driver(cdl_p reg, int key1, int key2, char *prefix, int flags) +{ + return 0; +} + +/* + * cdl_del_driver: Not supported. + */ +void +cdl_del_driver(cdl_p reg, + char *prefix) +{ + + printk("SGI IO INFRASTRUCTURE - cdl_del_driver not supported.\n"); +} + +/* + * cdl_add_connpt: We found a device and it's connect point. Call the + * attach routine of that driver. + * + * May need support for pciba registration here ... + * + * This routine use to create /hw/.id/pci/.../.. that links to + * /hw/module/006c06/Pbrick/xtalk/15/pci/ .. do we still need + * it? The specified driver attach routine does not reference these + * vertices. + */ +int +cdl_add_connpt(cdl_p reg, int part_num, int mfg_num, + devfs_handle_t connpt) +{ + int i; + + /* + * Find the driver entry point and call the attach routine. + */ + for (i = 0; i < MAX_SGI_IO_INFRA_DRVR; i++) { + + if ( (part_num == sgi_infrastructure_drivers[i].part_num) && + ( mfg_num == sgi_infrastructure_drivers[i].mfg_num) ) { + /* + * Call the device attach routines. + */ + if (sgi_infrastructure_drivers[i].attach) { + return(sgi_infrastructure_drivers[i].attach(connpt)); + } +#ifdef BRINGUP + /* + * XXX HACK ALERT bypassing fops for now.. + */ + else { + printk("cdl_add_connpt: NEED FOPS FOR OUR DRIVERS!!\n"); + printk("cdl_add_connpt: part_num= 0x%x mfg_num= 0x%x\n", + part_num, mfg_num); + return(-1); + } +#endif /* BRINGUP */ + } else { + continue; + } + + printk("**** cdl_add_connpt: driver not found for part_num %d mfg_num %d ****\n", part_num, mfg_num); + + return(-1); + } + if ( (i == MAX_SGI_IO_INFRA_DRVR) ) + printk("**** cdl_add_connpt: Driver not found for part_num 0x%x mfg_num 0x%x ****\n", part_num, mfg_num); + + return (0); +} + +/* + * cdl_del_connpt: Not implemented. + */ +void +cdl_del_connpt(cdl_p reg, int key1, int key2, devfs_handle_t connpt) +{ + + printk("SGI IO INFRASTRUCTURE - cdl_del_cdl_del_connpt not supported.\n"); +} + +/* + * cdl_iterate: Not Implemented. + */ +void +cdl_iterate(cdl_p reg, + char *prefix, + cdl_iter_f * func) +{ + + printk("SGI IO INFRASTRUCTURE - cdl_iterate not supported.\n"); +} + +async_attach_t +async_attach_new(void) +{ + + printk("SGI IO INFRASTRUCTURE - async_attach_new not supported.\n"); + return(0); +} + +void +async_attach_free(async_attach_t aa) +{ + printk("SGI IO INFRASTRUCTURE - async_attach_free not supported.\n"); +} + +async_attach_t +async_attach_get_info(devfs_handle_t vhdl) +{ + + printk("SGI IO INFRASTRUCTURE - async_attach_get_info not supported.\n"); + return(0); +} + +void +async_attach_add_info(devfs_handle_t vhdl, async_attach_t aa) +{ + printk("SGI IO INFRASTRUCTURE - async_attach_add_info not supported.\n"); + +} + +void +async_attach_del_info(devfs_handle_t vhdl) +{ + + printk("SGI IO INFRASTRUCTURE - async_attach_del_info not supported.\n"); + +} + +void async_attach_signal_start(async_attach_t aa) +{ + + printk("SGI IO INFRASTRUCTURE - async_attach_signal_start not supported.\n"); + +} + +void async_attach_signal_done(async_attach_t aa) +{ + + printk("SGI IO INFRASTRUCTURE - async_attach_signal_done not supported.\n"); + +} + +void async_attach_waitall(async_attach_t aa) +{ + + printk("SGI IO INFRASTRUCTURE - async_attach_waitall not supported.\n"); + +} + diff -urN linux-2.4.0-test10/arch/ia64/sn/io/devsupport.c linux-2.4.0-test10-lia/arch/ia64/sn/io/devsupport.c --- linux-2.4.0-test10/arch/ia64/sn/io/devsupport.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/devsupport.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,1292 @@ +#define ilvt_t int + +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Interfaces in this file are all platform-independent AND IObus-independent. + * Be aware that there may be macro equivalents to each of these hiding in + * header files which supercede these functions. + */ + +/* =====Generic iobus support===== */ + +/* String table to hold names of interrupts. */ +#ifdef notyet +static struct string_table device_desc_string_table; +#endif + +/* One time initialization for device descriptor support. */ +static void +device_desc_init(void) +{ +#ifdef notyet + string_table_init(&device_desc_string_table); +#endif + FIXME("device_desc_init"); +} + + +/* Drivers use these interfaces to manage device descriptors */ +static device_desc_t +device_desc_alloc(void) +{ +#ifdef notyet + device_desc_t device_desc; + + device_desc = (device_desc_t)kmem_zalloc(sizeof(struct device_desc_s), 0); + device_desc->intr_target = GRAPH_VERTEX_NONE; + + ASSERT(device_desc->intr_policy == 0); + device_desc->intr_swlevel = -1; + ASSERT(device_desc->intr_name == NULL); + ASSERT(device_desc->flags == 0); + + ASSERT(!(device_desc->flags & D_IS_ASSOC)); + return(device_desc); +#else + FIXME("device_desc_alloc"); + return((device_desc_t)0); +#endif +} + +void +device_desc_free(device_desc_t device_desc) +{ +#ifdef notyet + if (!(device_desc->flags & D_IS_ASSOC)) /* sanity */ + kfree(device_desc); +#endif + FIXME("device_desc_free"); +} + +device_desc_t +device_desc_dup(devfs_handle_t dev) +{ +#ifdef notyet + device_desc_t orig_device_desc, new_device_desc; + + + new_device_desc = device_desc_alloc(); + orig_device_desc = device_desc_default_get(dev); + if (orig_device_desc) + *new_device_desc = *orig_device_desc;/* small structure copy */ + else { + device_driver_t driver; + ilvl_t pri; + /* + * Use the driver's thread priority in + * case the device thread priority has not + * been given. + */ + if (driver = device_driver_getbydev(dev)) { + pri = device_driver_thread_pri_get(driver); + device_desc_intr_swlevel_set(new_device_desc,pri); + } + } + new_device_desc->flags &= ~D_IS_ASSOC; + return(new_device_desc); +#else + FIXME("device_desc_dup"); + return((device_desc_t)0); +#endif +} + +device_desc_t +device_desc_default_get(devfs_handle_t dev) +{ +#ifdef notyet + graph_error_t rc; + device_desc_t device_desc; + + rc = hwgraph_info_get_LBL(dev, INFO_LBL_DEVICE_DESC, (arbitrary_info_t *)&device_desc); + + if (rc == GRAPH_SUCCESS) + return(device_desc); + else + return(NULL); +#else + FIXME("device_desc_default_get"); + return((device_desc_t)0); +#endif +} + +void +device_desc_default_set(devfs_handle_t dev, device_desc_t new_device_desc) +{ +#ifdef notyet + graph_error_t rc; + device_desc_t old_device_desc = NULL; + + if (new_device_desc) { + new_device_desc->flags |= D_IS_ASSOC; + rc = hwgraph_info_add_LBL(dev, INFO_LBL_DEVICE_DESC, + (arbitrary_info_t)new_device_desc); + if (rc == GRAPH_DUP) { + rc = hwgraph_info_replace_LBL(dev, INFO_LBL_DEVICE_DESC, + (arbitrary_info_t)new_device_desc, + (arbitrary_info_t *)&old_device_desc); + + ASSERT(rc == GRAPH_SUCCESS); + } + hwgraph_info_export_LBL(dev, INFO_LBL_DEVICE_DESC, + sizeof(struct device_desc_s)); + } else { + rc = hwgraph_info_remove_LBL(dev, INFO_LBL_DEVICE_DESC, + (arbitrary_info_t *)&old_device_desc); + } + + if (old_device_desc) { + ASSERT(old_device_desc->flags & D_IS_ASSOC); + old_device_desc->flags &= ~D_IS_ASSOC; + device_desc_free(old_device_desc); + } +#endif + FIXME("device_desc_default_set"); +} + +devfs_handle_t +device_desc_intr_target_get(device_desc_t device_desc) +{ +#ifdef notyet + return(device_desc->intr_target); +#else + FIXME("device_desc_intr_target_get"); + return((devfs_handle_t)0); +#endif +} + +int +device_desc_intr_policy_get(device_desc_t device_desc) +{ +#ifdef notyet + return(device_desc->intr_policy); +#else + FIXME("device_desc_intr_policy_get"); + return(0); +#endif +} + +ilvl_t +device_desc_intr_swlevel_get(device_desc_t device_desc) +{ +#ifdef notyet + return(device_desc->intr_swlevel); +#else + FIXME("device_desc_intr_swlevel_get"); + return((ilvl_t)0); +#endif +} + +char * +device_desc_intr_name_get(device_desc_t device_desc) +{ +#ifdef notyet + return(device_desc->intr_name); +#else + FIXME("device_desc_intr_name_get"); + return(NULL); +#endif +} + +int +device_desc_flags_get(device_desc_t device_desc) +{ +#ifdef notyet + return(device_desc->flags); +#else + FIXME("device_desc_flags_get"); + return(0); +#endif +} + +void +device_desc_intr_target_set(device_desc_t device_desc, devfs_handle_t target) +{ + if ( device_desc != (device_desc_t)0 ) + device_desc->intr_target = target; +} + +void +device_desc_intr_policy_set(device_desc_t device_desc, int policy) +{ + if ( device_desc != (device_desc_t)0 ) + device_desc->intr_policy = policy; +} + +void +device_desc_intr_swlevel_set(device_desc_t device_desc, ilvl_t swlevel) +{ + if ( device_desc != (device_desc_t)0 ) + device_desc->intr_swlevel = swlevel; +} + +void +device_desc_intr_name_set(device_desc_t device_desc, char *name) +{ +#ifdef notyet + if ( device_desc != (device_desc_t)0 ) + device_desc->intr_name = string_table_insert(&device_desc_string_table, name); +#else + FIXME("device_desc_intr_name_set"); +#endif +} + +void +device_desc_flags_set(device_desc_t device_desc, int flags) +{ + if ( device_desc != (device_desc_t)0 ) + device_desc->flags = flags; +} + + + +/*============= device admin registry routines ===================== */ + +/* Linked list of pairs */ +typedef struct dev_admin_list_s { + struct dev_admin_list_s *admin_next; /* next entry in the + * list + */ + char *admin_name; /* info label */ + char *admin_val; /* actual info */ +} dev_admin_list_t; + +/* Device/Driver administration registry */ +typedef struct dev_admin_registry_s { + mrlock_t reg_lock; /* To allow + * exclusive + * access + */ + dev_admin_list_t *reg_first; /* first entry in + * the list + */ + dev_admin_list_t **reg_last; /* pointer to the + * next to last entry + * in the last which + * is also the place + * where the new + * entry gets + * inserted + */ +} dev_admin_registry_t; + +/* +** device_driver_s associates a device driver prefix with device switch entries. +*/ +struct device_driver_s { + struct device_driver_s *dd_next; /* next element on hash chain */ + struct device_driver_s *dd_prev; /* previous element on hash chain */ + char *dd_prefix; /* driver prefix string */ + struct bdevsw *dd_bdevsw; /* driver's bdevsw */ + struct cdevsw *dd_cdevsw; /* driver's cdevsw */ + + /* driver administration specific data structures need to + * maintain the list of pairs + */ + dev_admin_registry_t dd_dev_admin_registry; + ilvl_t dd_thread_pri; /* default thread priority for + * all this driver's + * threads. + */ + +}; + +#define NEW(_p) (_p = kmalloc(sizeof(*_p), GFP_KERNEL)) +#define FREE(_p) (kmem_free(_p)) + +/* + * helpful lock macros + */ + +#define DEV_ADMIN_REGISTRY_INITLOCK(lockp,name) mrinit(lockp,name) +#define DEV_ADMIN_REGISTRY_RDLOCK(lockp) mraccess(lockp) +#define DEV_ADMIN_REGISTRY_WRLOCK(lockp) mrupdate(lockp) +#define DEV_ADMIN_REGISTRY_UNLOCK(lockp) mrunlock(lockp) + +/* Initialize the registry + */ +static void +dev_admin_registry_init(dev_admin_registry_t *registry) +{ +#ifdef notyet + if ( registry != (dev_admin_registry_t *)0 ) + DEV_ADMIN_REGISTRY_INITLOCK(®istry->reg_lock, + "dev_admin_registry_lock"); + registry->reg_first = NULL; + registry->reg_last = ®istry->reg_first; + } +#else + FIXME("dev_admin_registry_init"); +#endif +} + +/* + * add an entry to the dev admin registry. + * if the name already exists in the registry then change the + * value iff the new value differs from the old value. + * if the name doesn't exist a new list entry is created and put + * at the end. + */ +static void +dev_admin_registry_add(dev_admin_registry_t *registry, + char *name, + char *val) +{ +#ifdef notyet + dev_admin_list_t *reg_entry; + dev_admin_list_t *scan = 0; + + DEV_ADMIN_REGISTRY_WRLOCK(®istry->reg_lock); + + /* check if the name already exists in the registry */ + scan = registry->reg_first; + + while (scan) { + if (strcmp(scan->admin_name,name) == 0) { + /* name is there in the registry */ + if (strcmp(scan->admin_val,val)) { + /* old value != new value + * reallocate memory and copy the new value + */ + FREE(scan->admin_val); + scan->admin_val = + (char *)kern_calloc(1,strlen(val)+1); + strcpy(scan->admin_val,val); + goto out; + } + goto out; /* old value == new value */ + } + scan = scan->admin_next; + } + + /* name is not there in the registry. + * allocate memory for the new registry entry + */ + NEW(reg_entry); + + reg_entry->admin_next = 0; + reg_entry->admin_name = (char *)kern_calloc(1,strlen(name)+1); + strcpy(reg_entry->admin_name,name); + reg_entry->admin_val = (char *)kern_calloc(1,strlen(val)+1); + strcpy(reg_entry->admin_val,val); + + /* add the entry at the end of the registry */ + + *(registry->reg_last) = reg_entry; + registry->reg_last = ®_entry->admin_next; + +out: DEV_ADMIN_REGISTRY_UNLOCK(®istry->reg_lock); +#endif + FIXME("dev_admin_registry_add"); +} +/* + * check if there is an info corr. to a particular + * name starting from the cursor position in the + * registry + */ +static char * +dev_admin_registry_find(dev_admin_registry_t *registry,char *name) +{ +#ifdef notyet + dev_admin_list_t *scan = 0; + + DEV_ADMIN_REGISTRY_RDLOCK(®istry->reg_lock); + scan = registry->reg_first; + + while (scan) { + if (strcmp(scan->admin_name,name) == 0) { + DEV_ADMIN_REGISTRY_UNLOCK(®istry->reg_lock); + return scan->admin_val; + } + scan = scan->admin_next; + } + DEV_ADMIN_REGISTRY_UNLOCK(®istry->reg_lock); + return 0; +#else + FIXME("dev_admin_registry_find"); + return(NULL); +#endif +} +/*============= MAIN DEVICE/ DRIVER ADMINISTRATION INTERFACE================ */ +/* + * return any labelled info associated with a device. + * called by any kernel code including device drivers. + */ +char * +device_admin_info_get(devfs_handle_t dev_vhdl, + char *info_lbl) +{ +#ifdef notyet + char *info = 0; + + /* return value need not be GRAPH_SUCCESS as the labelled + * info may not be present + */ + (void)hwgraph_info_get_LBL(dev_vhdl,info_lbl, + (arbitrary_info_t *)&info); + + + return info; +#else + FIXME("device_admin_info_get"); + return(NULL); +#endif +} + +/* + * set labelled info associated with a device. + * called by hwgraph infrastructure . may also be called + * by device drivers etc. + */ +int +device_admin_info_set(devfs_handle_t dev_vhdl, + char *dev_info_lbl, + char *dev_info_val) +{ +#ifdef notyet + graph_error_t rv; + arbitrary_info_t old_info; + + /* Handle the labelled info + * intr_target + * sw_level + * in a special way. These are part of device_desc_t + * Right now this is the only case where we have + * a set of related device_admin attributes which + * are grouped together. + * In case there is a need for another set we need to + * take a more generic approach to solving this. + * Basically a registry should be implemented. This + * registry is initialized with the callbacks for the + * attributes which need to handled in a special way + * For example: + * Consider + * device_desc + * intr_target + * intr_swlevel + * register "do_intr_target" for intr_target + * register "do_intr_swlevel" for intr_swlevel. + * When the device_admin interface layer gets an pair + * it looks in the registry to see if there is a function registered to + * handle "attr. If not follow the default path of setting the + * as labelled information hanging off the vertex. + * In the above example: + * "do_intr_target" does what is being done below for the ADMIN_LBL_INTR_TARGET + * case + */ + if (!strcmp(dev_info_lbl,ADMIN_LBL_INTR_TARGET) || + !strcmp(dev_info_lbl,ADMIN_LBL_INTR_SWLEVEL)) { + + device_desc_t device_desc; + + /* Check if there is a default device descriptor + * information for this vertex. If not dup one . + */ + if (!(device_desc = device_desc_default_get(dev_vhdl))) { + device_desc = device_desc_dup(dev_vhdl); + device_desc_default_set(dev_vhdl,device_desc); + + } + if (!strcmp(dev_info_lbl,ADMIN_LBL_INTR_TARGET)) { + /* Check if a target cpu has been specified + * for this device by a device administration + * directive + */ +#ifdef DEBUG + printf(ADMIN_LBL_INTR_TARGET + " dev = 0x%x " + "dev_admin_info = %s" + " target = 0x%x\n", + dev_vhdl, + dev_info_lbl, + hwgraph_path_to_vertex(dev_info_val)); +#endif + + device_desc->intr_target = + hwgraph_path_to_vertex(dev_info_val); + } else if (!strcmp(dev_info_lbl,ADMIN_LBL_INTR_SWLEVEL)) { + /* Check if the ithread priority level has been + * specified for this device by a device administration + * directive + */ +#ifdef DEBUG + printf(ADMIN_LBL_INTR_SWLEVEL + " dev = 0x%x " + "dev_admin_info = %s" + " sw level = 0x%x\n", + dev_vhdl, + dev_info_lbl, + atoi(dev_info_val)); +#endif + device_desc->intr_swlevel = atoi(dev_info_val); + } + + } + if (!dev_info_val) + rv = hwgraph_info_remove_LBL(dev_vhdl, + dev_info_lbl, + &old_info); + else { + + rv = hwgraph_info_add_LBL(dev_vhdl, + dev_info_lbl, + (arbitrary_info_t)dev_info_val); + + if (rv == GRAPH_DUP) { + rv = hwgraph_info_replace_LBL(dev_vhdl, + dev_info_lbl, + (arbitrary_info_t)dev_info_val, + &old_info); + } + } + ASSERT(rv == GRAPH_SUCCESS); +#endif + FIXME("device_admin_info_set"); + return 0; +} + +/* + * return labelled info associated with a device driver + * called by kernel code including device drivers + */ +char * +device_driver_admin_info_get(char *driver_prefix, + char *driver_info_lbl) +{ +#ifdef notyet + device_driver_t driver; + + driver = device_driver_get(driver_prefix); + return (dev_admin_registry_find(&driver->dd_dev_admin_registry, + driver_info_lbl)); +#else + FIXME("device_driver_admin_info_get"); + return(NULL); +#endif +} + +/* + * set labelled info associated with a device driver. + * called by hwgraph infrastructure . may also be called + * from drivers etc. + */ +int +device_driver_admin_info_set(char *driver_prefix, + char *driver_info_lbl, + char *driver_info_val) +{ +#ifdef notyet + device_driver_t driver; + + driver = device_driver_get(driver_prefix); + dev_admin_registry_add(&driver->dd_dev_admin_registry, + driver_info_lbl, + driver_info_val); +#endif + FIXME("device_driver_admin_info_set"); + return 0; +} +/*================== device / driver admin support routines================*/ + +/* static tables created by lboot */ +extern dev_admin_info_t dev_admin_table[]; +extern dev_admin_info_t drv_admin_table[]; +extern int dev_admin_table_size; +extern int drv_admin_table_size; + +/* Extend the device admin table to allow the kernel startup code to + * provide some device specific administrative hints + */ +#define ADMIN_TABLE_CHUNK 100 +static dev_admin_info_t extended_dev_admin_table[ADMIN_TABLE_CHUNK]; +static int extended_dev_admin_table_size = 0; +static mrlock_t extended_dev_admin_table_lock; + +/* Initialize the extended device admin table */ +void +device_admin_table_init(void) +{ +#ifdef notyet + extended_dev_admin_table_size = 0; + mrinit(&extended_dev_admin_table_lock, + "extended_dev_admin_table_lock"); +#endif + FIXME("device_admin_table_init"); +} +/* Add triple to + * the extended device administration info table. This is helpful + * for kernel startup code to put some hints before the hwgraph + * is setup + */ +void +device_admin_table_update(char *name,char *label,char *value) +{ +#ifdef notyet + dev_admin_info_t *p; + + mrupdate(&extended_dev_admin_table_lock); + + /* Safety check that we haven't exceeded array limits */ + ASSERT(extended_dev_admin_table_size < ADMIN_TABLE_CHUNK); + + if (extended_dev_admin_table_size == ADMIN_TABLE_CHUNK) + goto out; + + /* Get the pointer to the entry in the table where we are + * going to put the new information + */ + p = &extended_dev_admin_table[extended_dev_admin_table_size++]; + + /* Allocate memory for the strings and copy them in */ + p->dai_name = (char *)kern_calloc(1,strlen(name)+1); + strcpy(p->dai_name,name); + p->dai_param_name = (char *)kern_calloc(1,strlen(label)+1); + strcpy(p->dai_param_name,label); + p->dai_param_val = (char *)kern_calloc(1,strlen(value)+1); + strcpy(p->dai_param_val,value); + +out: mrunlock(&extended_dev_admin_table_lock); +#endif + FIXME("device_admin_table_update"); +} +/* Extend the device driver admin table to allow the kernel startup code to + * provide some device driver specific administrative hints + */ + +static dev_admin_info_t extended_drv_admin_table[ADMIN_TABLE_CHUNK]; +static int extended_drv_admin_table_size = 0; +mrlock_t extended_drv_admin_table_lock; + +/* Initialize the extended device driver admin table */ +void +device_driver_admin_table_init(void) +{ +#ifdef notyet + extended_drv_admin_table_size = 0; + mrinit(&extended_drv_admin_table_lock, + "extended_drv_admin_table_lock"); +#endif + FIXME("device_driver_admin_table_init"); +} +/* Add triple to + * the extended device administration info table. This is helpful + * for kernel startup code to put some hints before the hwgraph + * is setup + */ +void +device_driver_admin_table_update(char *name,char *label,char *value) +{ +#ifdef notyet + dev_admin_info_t *p; + + mrupdate(&extended_dev_admin_table_lock); + + /* Safety check that we haven't exceeded array limits */ + ASSERT(extended_drv_admin_table_size < ADMIN_TABLE_CHUNK); + + if (extended_drv_admin_table_size == ADMIN_TABLE_CHUNK) + goto out; + + /* Get the pointer to the entry in the table where we are + * going to put the new information + */ + p = &extended_drv_admin_table[extended_drv_admin_table_size++]; + + /* Allocate memory for the strings and copy them in */ + p->dai_name = (char *)kern_calloc(1,strlen(name)+1); + strcpy(p->dai_name,name); + p->dai_param_name = (char *)kern_calloc(1,strlen(label)+1); + strcpy(p->dai_param_name,label); + p->dai_param_val = (char *)kern_calloc(1,strlen(value)+1); + strcpy(p->dai_param_val,value); + +out: mrunlock(&extended_drv_admin_table_lock); +#endif + FIXME("device_driver_admin_table_update"); +} +/* + * keeps on adding the labelled info for each new (lbl,value) pair + * that it finds in the static dev admin table ( created by lboot) + * and the extended dev admin table ( created if at all by the kernel startup + * code) corresponding to a device in the hardware graph. + */ +void +device_admin_info_update(devfs_handle_t dev_vhdl) +{ +#ifdef notyet + int i = 0; + dev_admin_info_t *scan; + devfs_handle_t scan_vhdl; + + /* Check the static device administration info table */ + scan = dev_admin_table; + while (i < dev_admin_table_size) { + + scan_vhdl = hwgraph_path_to_dev(scan->dai_name); + if (scan_vhdl == dev_vhdl) { + device_admin_info_set(dev_vhdl, + scan->dai_param_name, + scan->dai_param_val); + } + if (scan_vhdl != NODEV) + hwgraph_vertex_unref(scan_vhdl); + scan++;i++; + + } + i = 0; + /* Check the extended device administration info table */ + scan = extended_dev_admin_table; + while (i < extended_dev_admin_table_size) { + scan_vhdl = hwgraph_path_to_dev(scan->dai_name); + if (scan_vhdl == dev_vhdl) { + device_admin_info_set(dev_vhdl, + scan->dai_param_name, + scan->dai_param_val); + } + if (scan_vhdl != NODEV) + hwgraph_vertex_unref(scan_vhdl); + scan++;i++; + + } + + +#endif + FIXME("device_admin_info_update"); +} + +/* looks up the static drv admin table ( created by the lboot) and the extended + * drv admin table (created if at all by the kernel startup code) + * for this driver specific administration info and adds it to the admin info + * associated with this device driver's object + */ +void +device_driver_admin_info_update(device_driver_t driver) +{ +#ifdef notyet + int i = 0; + dev_admin_info_t *scan; + + /* Check the static device driver administration info table */ + scan = drv_admin_table; + while (i < drv_admin_table_size) { + + if (strcmp(scan->dai_name,driver->dd_prefix) == 0) { + dev_admin_registry_add(&driver->dd_dev_admin_registry, + scan->dai_param_name, + scan->dai_param_val); + } + scan++;i++; + } + i = 0; + /* Check the extended device driver administration info table */ + scan = extended_drv_admin_table; + while (i < extended_drv_admin_table_size) { + + if (strcmp(scan->dai_name,driver->dd_prefix) == 0) { + dev_admin_registry_add(&driver->dd_dev_admin_registry, + scan->dai_param_name, + scan->dai_param_val); + } + scan++;i++; + } +#endif + FIXME("device_driver_admin_info_update"); +} + +/* =====Device Driver Support===== */ + + + +/* +** Generic device driver support routines for use by kernel modules that +** deal with device drivers (but NOT for use by the drivers themselves). +** EVERY registered driver currently in the system -- static or loadable -- +** has an entry in the device_driver_hash table. A pointer to such an entry +** serves as a generic device driver handle. +*/ + +#define DEVICE_DRIVER_HASH_SIZE 32 +#ifdef notyet +lock_t device_driver_lock[DEVICE_DRIVER_HASH_SIZE]; +device_driver_t device_driver_hash[DEVICE_DRIVER_HASH_SIZE]; +static struct string_table driver_prefix_string_table; +#endif + +/* +** Initialize device driver infrastructure. +*/ +void +device_driver_init(void) +{ +#ifdef notyet + int i; + extern void alenlist_init(void); + extern void hwgraph_init(void); + extern void device_desc_init(void); + + ASSERT(DEVICE_DRIVER_NONE == NULL); + alenlist_init(); + hwgraph_init(); + device_desc_init(); + + string_table_init(&driver_prefix_string_table); + + for (i=0; isdd_prefix); + if (!driver) + driver = device_driver_alloc(desc->sdd_prefix); + pri = device_driver_sysgen_thread_pri_get(desc->sdd_prefix); + device_driver_thread_pri_set(driver, pri); + device_driver_devsw_put(driver, desc->sdd_bdevsw, desc->sdd_cdevsw); + } +#endif + FIXME("device_driver_init"); +} + +/* +** Hash a prefix string into a hash table chain. +*/ +static int +driver_prefix_hash(char *prefix) +{ +#ifdef notyet + int accum = 0; + char nextchar; + + while (nextchar = *prefix++) + accum = accum ^ nextchar; + + return(accum % DEVICE_DRIVER_HASH_SIZE); +#else + FIXME("driver_prefix_hash"); + return(0); +#endif +} + + +/* +** Allocate a driver handle. +** Returns the driver handle, or NULL if the driver prefix +** already has a handle. +** +** Upper layers prevent races among device_driver_alloc, +** device_driver_free, and device_driver_get*. +*/ +device_driver_t +device_driver_alloc(char *prefix) +{ +#ifdef notyet + int which_hash; + device_driver_t new_driver; + int s; + + which_hash = driver_prefix_hash(prefix); + + new_driver = kern_calloc(1, sizeof(*new_driver)); + ASSERT(new_driver != NULL); + new_driver->dd_prev = NULL; + new_driver->dd_prefix = string_table_insert(&driver_prefix_string_table, prefix); + new_driver->dd_bdevsw = NULL; + new_driver->dd_cdevsw = NULL; + + dev_admin_registry_init(&new_driver->dd_dev_admin_registry); + device_driver_admin_info_update(new_driver); + + s = mutex_spinlock(&device_driver_lock[which_hash]); + +#if DEBUG + { + device_driver_t drvscan; + + /* Make sure we haven't already added a driver with this prefix */ + drvscan = device_driver_hash[which_hash]; + while (drvscan && + strcmp(drvscan->dd_prefix, prefix)) { + drvscan = drvscan->dd_next; + } + + ASSERT(!drvscan); + } +#endif /* DEBUG */ + + + /* Add new_driver to front of hash chain. */ + new_driver->dd_next = device_driver_hash[which_hash]; + if (new_driver->dd_next) + new_driver->dd_next->dd_prev = new_driver; + device_driver_hash[which_hash] = new_driver; + + mutex_spinunlock(&device_driver_lock[which_hash], s); + + return(new_driver); +#else + FIXME("device_driver_alloc"); + return((device_driver_t)0); +#endif +} + +/* +** Free a driver handle. +** +** Statically loaded drivers should never device_driver_free. +** Dynamically loaded drivers device_driver_free when either an +** unloaded driver is unregistered, or when an unregistered driver +** is unloaded. +*/ +void +device_driver_free(device_driver_t driver) +{ +#ifdef notyet + int which_hash; + int s; + + if (!driver) + return; + + which_hash = driver_prefix_hash(driver->dd_prefix); + + s = mutex_spinlock(&device_driver_lock[which_hash]); + +#if DEBUG + { + device_driver_t drvscan; + + /* Make sure we're dealing with the right list */ + drvscan = device_driver_hash[which_hash]; + while (drvscan && (drvscan != driver)) + drvscan = drvscan->dd_next; + + ASSERT(drvscan); + } +#endif /* DEBUG */ + + if (driver->dd_next) + driver->dd_next->dd_prev = driver->dd_prev; + + if (driver->dd_prev) + driver->dd_prev->dd_next = driver->dd_next; + else + device_driver_hash[which_hash] = driver->dd_next; + + mutex_spinunlock(&device_driver_lock[which_hash], s); + + driver->dd_next = NULL; /* sanity */ + driver->dd_prev = NULL; /* sanity */ + driver->dd_prefix = NULL; /* sanity */ + + if (driver->dd_bdevsw) { + driver->dd_bdevsw->d_driver = NULL; + driver->dd_bdevsw = NULL; + } + + if (driver->dd_cdevsw) { + if (driver->dd_cdevsw->d_str) { + str_free_mux_node(driver); + } + driver->dd_cdevsw->d_driver = NULL; + driver->dd_cdevsw = NULL; + } + + kern_free(driver); +#endif + FIXME("device_driver_free"); +} + + +/* +** Given a device driver prefix, return a handle to the caller. +*/ +device_driver_t +device_driver_get(char *prefix) +{ +#ifdef notyet + int which_hash; + device_driver_t drvscan; + int s; + + if (prefix == NULL) + return(NULL); + + which_hash = driver_prefix_hash(prefix); + + s = mutex_spinlock(&device_driver_lock[which_hash]); + + drvscan = device_driver_hash[which_hash]; + while (drvscan && strcmp(drvscan->dd_prefix, prefix)) + drvscan = drvscan->dd_next; + + mutex_spinunlock(&device_driver_lock[which_hash], s); + + return(drvscan); +#else + FIXME("device_driver_get"); + return((device_driver_t)0); +#endif +} + + +/* +** Given a block or char special file devfs_handle_t, find the +** device driver that controls it. +*/ +device_driver_t +device_driver_getbydev(devfs_handle_t device) +{ +#ifdef notyet + struct bdevsw *my_bdevsw; + struct cdevsw *my_cdevsw; + + my_cdevsw = get_cdevsw(device); + if (my_cdevsw != NULL) + return(my_cdevsw->d_driver); + + my_bdevsw = get_bdevsw(device); + if (my_bdevsw != NULL) + return(my_bdevsw->d_driver); + +#endif + FIXME("device_driver_getbydev"); + return((device_driver_t)0); +} + + +/* +** Associate a driver with bdevsw/cdevsw pointers. +** +** Statically loaded drivers are permanently and automatically associated +** with the proper bdevsw/cdevsw. Dynamically loaded drivers associate +** themselves when the driver is registered, and disassociate when the +** driver unregisters. +** +** Returns 0 on success, -1 on failure (devsw already associated with driver) +*/ +int +device_driver_devsw_put(device_driver_t driver, + struct bdevsw *my_bdevsw, + struct cdevsw *my_cdevsw) +{ +#ifdef notyet + int i; + + if (!driver) + return(-1); + + /* Trying to re-register data? */ + if (((my_bdevsw != NULL) && (driver->dd_bdevsw != NULL)) || + ((my_cdevsw != NULL) && (driver->dd_cdevsw != NULL))) + return(-1); + + if (my_bdevsw != NULL) { + driver->dd_bdevsw = my_bdevsw; + my_bdevsw->d_driver = driver; + for (i = 0; i < bdevmax; i++) { + if (driver->dd_bdevsw->d_flags == bdevsw[i].d_flags) { + bdevsw[i].d_driver = driver; + break; + } + } + } + + if (my_cdevsw != NULL) { + driver->dd_cdevsw = my_cdevsw; + my_cdevsw->d_driver = driver; + for (i = 0; i < cdevmax; i++) { + if (driver->dd_cdevsw->d_flags == cdevsw[i].d_flags) { + cdevsw[i].d_driver = driver; + break; + } + } + } +#endif + FIXME("device_driver_devsw_put"); + return(0); +} + + +/* +** Given a driver, return the corresponding bdevsw and cdevsw pointers. +*/ +void +device_driver_devsw_get( device_driver_t driver, + struct bdevsw **bdevswp, + struct cdevsw **cdevswp) +{ + if (!driver) { + *bdevswp = NULL; + *cdevswp = NULL; + } else { + *bdevswp = driver->dd_bdevsw; + *cdevswp = driver->dd_cdevsw; + } +} + +/* + * device_driver_thread_pri_set + * Given a driver try to set its thread priority. + * Returns 0 on success , -1 on failure. + */ +int +device_driver_thread_pri_set(device_driver_t driver,ilvl_t pri) +{ + if (!driver) + return(-1); + driver->dd_thread_pri = pri; + return(0); +} +/* + * device_driver_thread_pri_get + * Given a driver return the driver thread priority. + * If the driver is NULL return invalid driver thread + * priority. + */ +ilvl_t +device_driver_thread_pri_get(device_driver_t driver) +{ + if (driver) + return(driver->dd_thread_pri); + else + return(DRIVER_THREAD_PRI_INVALID); +} +/* +** Given a device driver, return it's handle (prefix). +*/ +void +device_driver_name_get(device_driver_t driver, char *buffer, int length) +{ + if (driver == NULL) + return; + + strncpy(buffer, driver->dd_prefix, length); +} + + +/* +** Associate a pointer-sized piece of information with a device. +*/ +void +device_info_set(devfs_handle_t device, void *info) +{ +#ifdef notyet + hwgraph_fastinfo_set(device, (arbitrary_info_t)info); +#endif + FIXME("device_info_set"); +} + + +/* +** Retrieve a pointer-sized piece of information associated with a device. +*/ +void * +device_info_get(devfs_handle_t device) +{ +#ifdef notyet + return((void *)hwgraph_fastinfo_get(device)); +#else + FIXME("device_info_get"); + return(NULL); +#endif +} + +/* + * Find the thread priority for a device, from the various + * sysgen files. + */ +int +device_driver_sysgen_thread_pri_get(char *dev_prefix) +{ +#ifdef notyet + int pri; + char *pri_s; + char *class; + + extern default_intr_pri; + extern disk_intr_pri; + extern serial_intr_pri; + extern parallel_intr_pri; + extern tape_intr_pri; + extern graphics_intr_pri; + extern network_intr_pri; + extern scsi_intr_pri; + extern audio_intr_pri; + extern video_intr_pri; + extern external_intr_pri; + extern tserialio_intr_pri; + + /* Check if there is a thread priority specified for + * this driver's thread thru admin hints. If so + * use that value. Otherwise set it to its default + * class value, otherwise set it to the default + * value. + */ + + if (pri_s = device_driver_admin_info_get(dev_prefix, + ADMIN_LBL_THREAD_PRI)) { + pri = atoi(pri_s); + } else if (class = device_driver_admin_info_get(dev_prefix, + ADMIN_LBL_THREAD_CLASS)) { + if (strcmp(class, "disk") == 0) + pri = disk_intr_pri; + else if (strcmp(class, "serial") == 0) + pri = serial_intr_pri; + else if (strcmp(class, "parallel") == 0) + pri = parallel_intr_pri; + else if (strcmp(class, "tape") == 0) + pri = tape_intr_pri; + else if (strcmp(class, "graphics") == 0) + pri = graphics_intr_pri; + else if (strcmp(class, "network") == 0) + pri = network_intr_pri; + else if (strcmp(class, "scsi") == 0) + pri = scsi_intr_pri; + else if (strcmp(class, "audio") == 0) + pri = audio_intr_pri; + else if (strcmp(class, "video") == 0) + pri = video_intr_pri; + else if (strcmp(class, "external") == 0) + pri = external_intr_pri; + else if (strcmp(class, "tserialio") == 0) + pri = tserialio_intr_pri; + else + pri = default_intr_pri; + } else + pri = default_intr_pri; + + if (pri > 255) + pri = 255; + else if (pri < 0) + pri = 0; + return pri; +#else + FIXME("device_driver_sysgen_thread_pri_get"); + return(-1); +#endif +} diff -urN linux-2.4.0-test10/arch/ia64/sn/io/eeprom.c linux-2.4.0-test10-lia/arch/ia64/sn/io/eeprom.c --- linux-2.4.0-test10/arch/ia64/sn/io/eeprom.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/eeprom.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,1478 @@ +/* + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Jack Steiner (steiner@sgi.com) + */ + + +/* + * WARNING: There is more than one copy of this file in different isms. + * All copies must be kept exactly in sync. + * Do not modify this file without also updating the following: + * + * irix/kern/io/eeprom.c + * stand/arcs/lib/libsk/ml/eeprom.c + * stand/arcs/lib/libkl/io/eeprom.c + * + * (from time to time they might not be in sync but that's due to bringup + * activity - this comment is to remind us that they eventually have to + * get back together) + * + * eeprom.c + * + * access to board-mounted EEPROMs via the L1 system controllers + * + */ + +/************************************************************************** + * * + * Copyright (C) 1999 Silicon Graphics, Inc. * + * * + * These coded instructions, statements, and computer programs contain * + * unpublished proprietary information of Silicon Graphics, Inc., and * + * are protected by Federal copyright law. They may not be disclosed * + * to third parties or copied or duplicated in any form, in whole or * + * in part, without the prior written consent of Silicon Graphics, Inc. * + * * + ************************************************************************** + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* #include */ +#include +#include +#include +#ifdef _STANDALONE +#include +#include +#else +#include +#endif +#include + +#if defined(EEPROM_DEBUG) +#define db_printf(x) printk x +#else +#define db_printf(x) +#endif + +#ifdef _STANDALONE +#define bcopy(a,b,len) memcpy(b,a,len) +#endif + +#define UNDERSCORE 0 /* don't convert underscores to hyphens */ +#define HYPHEN 1 /* convert underscores to hyphens */ + +void copy_ascii_field( char *to, char *from, int length, + int change_underscore ); +uint64_t generate_unique_id( char *sn, int sn_len ); +uchar_t char_to_base36( char c ); +int nicify( char *dst, eeprom_brd_record_t *src ); +static void int64_to_hex_string( char *out, uint64_t val ); + +#ifndef _STANDALONE +extern int router_lock( net_vec_t, int, int ); +extern int router_unlock( net_vec_t ); +#define ROUTER_LOCK(p) router_lock(p, 10000, 3000000) +#define ROUTER_UNLOCK(p) router_unlock(p) + +#else +/* router should already be locked when calling vector routines in the prom */ +#define ROUTER_LOCK(p) +#define ROUTER_UNLOCK(p) +#endif + + +/* the following function converts an EEPROM record to a close facsimile + * of the string returned by reading a Dallas Semiconductor NIC (see + * one of the many incarnations of nic.c for details on that driver) + */ +int nicify( char *dst, eeprom_brd_record_t *src ) +{ + int field_len; + uint64_t unique_id; + char *cur_dst = dst; + eeprom_board_ia_t *board; + + board = src->board_ia; + ASSERT( board ); /* there should always be a board info area */ + + /* copy part number */ + strcpy( cur_dst, "Part:" ); + cur_dst += strlen( cur_dst ); + ASSERT( (board->part_num_tl & FIELD_FORMAT_MASK) + == FIELD_FORMAT_ASCII ); + field_len = board->part_num_tl & FIELD_LENGTH_MASK; + copy_ascii_field( cur_dst, board->part_num, field_len, HYPHEN ); + cur_dst += field_len; + + /* copy product name */ + strcpy( cur_dst, ";Name:" ); + cur_dst += strlen( cur_dst ); + ASSERT( (board->product_tl & FIELD_FORMAT_MASK) == FIELD_FORMAT_ASCII ); + field_len = board->product_tl & FIELD_LENGTH_MASK; + copy_ascii_field( cur_dst, board->product, field_len, UNDERSCORE ); + cur_dst += field_len; + + /* copy serial number */ + strcpy( cur_dst, ";Serial:" ); + cur_dst += strlen( cur_dst ); + ASSERT( (board->serial_num_tl & FIELD_FORMAT_MASK) + == FIELD_FORMAT_ASCII ); + field_len = board->serial_num_tl & FIELD_LENGTH_MASK; + copy_ascii_field( cur_dst, board->serial_num, field_len, + HYPHEN); + + cur_dst += field_len; + + /* copy revision */ + strcpy( cur_dst, ";Revision:"); + cur_dst += strlen( cur_dst ); + ASSERT( (board->board_rev_tl & FIELD_FORMAT_MASK) + == FIELD_FORMAT_ASCII ); + field_len = board->board_rev_tl & FIELD_LENGTH_MASK; + copy_ascii_field( cur_dst, board->board_rev, field_len, HYPHEN ); + cur_dst += field_len; + + /* EEPROMs don't have equivalents for the Group, Capability and + * Variety fields, so we pad these with 0's + */ + strcpy( cur_dst, ";Group:ff;Capability:ffffffff;Variety:ff" ); + cur_dst += strlen( cur_dst ); + + /* use the board serial number to "fake" a laser id */ + strcpy( cur_dst, ";Laser:" ); + cur_dst += strlen( cur_dst ); + unique_id = generate_unique_id( board->serial_num, + board->serial_num_tl & FIELD_LENGTH_MASK ); + int64_to_hex_string( cur_dst, unique_id ); + strcat( dst, ";" ); + + return 1; +} + + +/* These functions borrow heavily from chars2* in nic.c + */ +void copy_ascii_field( char *to, char *from, int length, + int change_underscore ) +{ + int i; + for( i = 0; i < length; i++ ) { + + /* change underscores to hyphens if requested */ + if( from[i] == '_' && change_underscore == HYPHEN ) + to[i] = '-'; + + /* ; and ; are separators, so mustn't appear within + * a field */ + else if( from[i] == ':' || from[i] == ';' ) + to[i] = '?'; + + /* I'm not sure why or if ASCII character 0xff would + * show up in an EEPROM field, but the NIC parsing + * routines wouldn't like it if it did... so we + * get rid of it, just in case. */ + else if( (unsigned char)from[i] == (unsigned char)0xff ) + to[i] = ' '; + + /* unprintable characters are replaced with . */ + else if( from[i] < ' ' || from[i] >= 0x7f ) + to[i] = '.'; + + /* otherwise, just copy the character */ + else + to[i] = from[i]; + } + + if( i == 0 ) { + to[i] = ' '; /* return at least a space... */ + i++; + } + to[i] = 0; /* terminating null */ +} + +/* Note that int64_to_hex_string currently only has a big-endian + * implementation. + */ +#ifdef _MIPSEB +static void int64_to_hex_string( char *out, uint64_t val ) +{ + int i; + uchar_t table[] = "0123456789abcdef"; + uchar_t *byte_ptr = (uchar_t *)&val; + for( i = 0; i < sizeof(uint64_t); i++ ) { + out[i*2] = table[ ((*byte_ptr) >> 4) & 0x0f ]; + out[i*2+1] = table[ (*byte_ptr) & 0x0f ]; + byte_ptr++; + } + out[i*2] = '\0'; +} + +#else /* little endian */ + +static void int64_to_hex_string( char *out, uint64_t val ) +{ + + + printk("int64_to_hex_string needs a little-endian implementation.\n"); +} +#endif /* _MIPSEB */ + +/* Convert a standard ASCII serial number to a unique integer + * id number by treating the serial number string as though + * it were a base 36 number + */ +uint64_t generate_unique_id( char *sn, int sn_len ) +{ + int uid = 0; + int i; + + #define VALID_BASE36(c) ((c >= '0' && c <='9') \ + || (c >= 'A' && c <='Z') \ + || (c >= 'a' && c <='z')) + + for( i = 0; i < sn_len; i++ ) { + if( !VALID_BASE36(sn[i]) ) + continue; + uid *= 36; + uid += char_to_base36( sn[i] ); + } + + if( uid == 0 ) + return rtc_time(); + + return uid; +} + +uchar_t char_to_base36( char c ) +{ + uchar_t val; + + if( c >= '0' && c <= '9' ) + val = (c - '0'); + + else if( c >= 'A' && c <= 'Z' ) + val = (c - 'A' + 10); + + else if( c >= 'a' && c <= 'z' ) + val = (c - 'a' + 10); + + else val = 0; + + return val; +} + + +/* given a pointer to the three-byte little-endian EEPROM representation + * of date-of-manufacture, this function translates to a big-endian + * integer format + */ +int eeprom_xlate_board_mfr_date( uchar_t *src ) +{ + int rval = 0; + rval += *src; src++; + rval += ((int)(*src) << 8); src ++; + rval += ((int)(*src) << 16); + return rval; +} + + +int eeprom_str( char *nic_str, nasid_t nasid, int component ) +{ + eeprom_brd_record_t eep; + eeprom_board_ia_t board; + eeprom_chassis_ia_t chassis; + int r; + + if( (component & C_DIMM) == C_DIMM ) { + /* this function isn't applicable to DIMMs */ + return EEP_PARAM; + } + else { + eep.board_ia = &board; + eep.spd = NULL; + if( !(component & SUBORD_MASK) ) + eep.chassis_ia = &chassis; /* only main boards have a chassis + * info area */ + else + eep.chassis_ia = NULL; + } + + switch( component & BRICK_MASK ) { + case C_BRICK: + r = cbrick_eeprom_read( &eep, nasid, component ); + break; + case IO_BRICK: + r = iobrick_eeprom_read( &eep, nasid, component ); + break; + default: + return EEP_PARAM; /* must be an invalid component */ + } + if( r ) + return r; + if( !nicify( nic_str, &eep ) ) + return EEP_NICIFY; + + return EEP_OK; +} + +int vector_eeprom_str( char *nic_str, nasid_t nasid, + int component, net_vec_t path ) +{ + eeprom_brd_record_t eep; + eeprom_board_ia_t board; + eeprom_chassis_ia_t chassis; + int r; + + eep.board_ia = &board; + if( !(component & SUBORD_MASK) ) + eep.chassis_ia = &chassis; /* only main boards have a chassis + * info area */ + else + eep.chassis_ia = NULL; + + if( !(component & VECTOR) ) + return EEP_PARAM; + + if( (r = vector_eeprom_read( &eep, nasid, path, component )) ) + return r; + + if( !nicify( nic_str, &eep ) ) + return EEP_NICIFY; + + return EEP_OK; +} + + +int is_iobrick( int nasid, int widget_num ) +{ + uint32_t wid_reg; + int part_num, mfg_num; + + /* Read the widget's WIDGET_ID register to get + * its part number and mfg number + */ + wid_reg = *(volatile int32_t *) + (NODE_SWIN_BASE( nasid, widget_num ) + WIDGET_ID); + + part_num = (wid_reg & WIDGET_PART_NUM) >> WIDGET_PART_NUM_SHFT; + mfg_num = (wid_reg & WIDGET_MFG_NUM) >> WIDGET_MFG_NUM_SHFT; + + /* Is this the "xbow part" of an XBridge? If so, this + * widget is definitely part of an I/O brick. + */ + if( part_num == XXBOW_WIDGET_PART_NUM && + mfg_num == XXBOW_WIDGET_MFGR_NUM ) + + return 1; + + /* Is this a "bridge part" of an XBridge? If so, once + * again, we know this widget is part of an I/O brick. + */ + if( part_num == XBRIDGE_WIDGET_PART_NUM && + mfg_num == XBRIDGE_WIDGET_MFGR_NUM ) + + return 1; + + return 0; +} + + +int cbrick_uid_get( nasid_t nasid, uint64_t *uid ) +{ +#if !defined(DIRECT_L1_CONSOLE) + char uid_str[32]; + char msg[BRL1_QSIZE]; + int subch, len; + l1sc_t sc; + l1sc_t *scp; + int local = (nasid == get_nasid()); + + /* If the promlog variable pointed to by IP27LOG_OVNIC is set, + * use that value for the cbrick UID rather than the EEPROM + * serial number. + */ + if( ip27log_getenv( nasid, IP27LOG_OVNIC, uid_str, NULL, 0 ) >= 0 ) + { + /* We successfully read IP27LOG_OVNIC, so return it as the UID. */ + db_printf(( "cbrick_uid_get:" + "Overriding UID with environment variable %s\n", + IP27LOG_OVNIC )); + *uid = strtoull( uid_str, NULL, 0 ); + return EEP_OK; + } + + /* If this brick is retrieving its own uid, use the local l1sc_t to + * arbitrate access to the l1; otherwise, set up a new one. + */ + if( local ) { + scp = get_l1sc(); + } + else { + scp = ≻ + sc_init( &sc, nasid, BRL1_LOCALUART ); + } + + /* fill in msg with the opcode & params */ + BZERO( msg, BRL1_QSIZE ); + if( (subch = sc_open( scp, L1_ADDR_LOCAL )) < 0 ) + return EEP_L1; + + if( (len = sc_construct_msg( scp, subch, msg, BRL1_QSIZE, + L1_ADDR_TASK_GENERAL, + L1_REQ_SER_NUM, 0 )) < 0 ) + { + sc_close( scp, subch ); + return( EEP_L1 ); + } + + /* send the request to the L1 */ + if( sc_command( scp, subch, msg, msg, &len ) ) { + sc_close( scp, subch ); + return( EEP_L1 ); + } + + /* free up subchannel */ + sc_close(scp, subch); + + /* check response */ + if( sc_interpret_resp( msg, 2, L1_ARG_ASCII, uid_str ) < 0 ) + { + return( EEP_L1 ); + } + + *uid = generate_unique_id( uid_str, strlen( uid_str ) ); + + return EEP_OK; + +#else /* the following applies if DIRECT_L1_CONSOLE is enabled */ + return EEP_L1; +#endif /* DIRECT_L1_CONSOLE */ +} + + +int rbrick_uid_get( nasid_t nasid, net_vec_t path, uint64_t *uid ) +{ +#if !defined(DIRECT_L1_CONSOLE) + char uid_str[32]; + char msg[BRL1_QSIZE]; + int subch, len; + l1sc_t sc; + +#ifdef BRINGUP +#define FAIL \ + { \ + *uid = rtc_time(); \ + printk( "rbrick_uid_get failed; using current time as uid\n" ); \ + return EEP_OK; \ + } +#endif /* BRINGUP */ + + ROUTER_LOCK(path); + sc_init( &sc, nasid, path ); + + /* fill in msg with the opcode & params */ + BZERO( msg, BRL1_QSIZE ); + if( (subch = sc_open( &sc, L1_ADDR_LOCAL )) < 0 ) { + ROUTER_UNLOCK(path); + FAIL; + } + + if( (len = sc_construct_msg( &sc, subch, msg, BRL1_QSIZE, + L1_ADDR_TASK_GENERAL, + L1_REQ_SER_NUM, 0 )) < 0 ) + { + ROUTER_UNLOCK(path); + sc_close( &sc, subch ); + FAIL; + } + + /* send the request to the L1 */ + if( sc_command( &sc, subch, msg, msg, &len ) ) { + ROUTER_UNLOCK(path); + sc_close( &sc, subch ); + FAIL; + } + + /* free up subchannel */ + ROUTER_UNLOCK(path); + sc_close(&sc, subch); + + /* check response */ + if( sc_interpret_resp( msg, 2, L1_ARG_ASCII, uid_str ) < 0 ) + { + FAIL; + } + + *uid = generate_unique_id( uid_str, strlen( uid_str ) ); + + return EEP_OK; + +#else /* the following applies if DIRECT_L1_CONSOLE is enabled */ + return EEP_L1; +#endif /* DIRECT_L1_CONSOLE */ + +} + +int iobrick_uid_get( nasid_t nasid, uint64_t *uid ) +{ + eeprom_brd_record_t eep; + eeprom_board_ia_t board; + eeprom_chassis_ia_t chassis; + int r; + + eep.board_ia = &board; + eep.chassis_ia = &chassis; + eep.spd = NULL; + + r = iobrick_eeprom_read( &eep, nasid, IO_BRICK ); + if( r != EEP_OK ) { + *uid = rtc_time(); + return r; + } + + *uid = generate_unique_id( board.serial_num, + board.serial_num_tl & FIELD_LENGTH_MASK ); + + return EEP_OK; +} + + +int ibrick_mac_addr_get( nasid_t nasid, char *eaddr ) +{ + eeprom_brd_record_t eep; + eeprom_board_ia_t board; + eeprom_chassis_ia_t chassis; + int r; + char *tmp; + + eep.board_ia = &board; + eep.chassis_ia = &chassis; + eep.spd = NULL; + + r = iobrick_eeprom_read( &eep, nasid, IO_BRICK ); + if( (r != EEP_OK) || (board.mac_addr[0] == '\0') ) { + db_printf(( "ibrick_mac_addr_get: " + "Couldn't read MAC address from EEPROM\n" )); + return EEP_L1; + } + else { + /* successfully read info area */ + int ix; + tmp = board.mac_addr; + for( ix = 0; ix < (board.mac_addr_tl & FIELD_LENGTH_MASK); ix++ ) + { + *eaddr++ = *tmp++; + } + *eaddr = '\0'; + } + + return EEP_OK; +} + + +#ifndef _STANDALONE + +/* + * eeprom_vertex_info_set + * + * Given a vertex handle, a component designation, a starting nasid + * and (in the case of a router) a vector path to the component, this + * function will read the EEPROM and attach the resulting information + * to the vertex in the same string format as that provided by the + * Dallas Semiconductor NIC drivers. If the vertex already has the + * string, this function just returns the string. + */ + +extern char *nic_vertex_info_get( devfs_handle_t ); +extern void nic_vmc_check( devfs_handle_t, char * ); +#ifdef BRINGUP +/* the following were lifted from nic.c - change later? */ +#define MAX_INFO 2048 +#define NEWSZ(ptr,sz) ((ptr) = kern_malloc((sz))) +#define DEL(ptr) (kern_free((ptr))) +#endif /* BRINGUP */ + +char *eeprom_vertex_info_set( int component, int nasid, devfs_handle_t v, + net_vec_t path ) +{ + char *info_tmp; + int info_len; + char *info; + + /* see if this vertex is already marked */ + info_tmp = nic_vertex_info_get(v); + if (info_tmp) return info_tmp; + + /* get a temporary place for the data */ + NEWSZ(info_tmp, MAX_INFO); + if (!info_tmp) return NULL; + + /* read the EEPROM */ + if( component & R_BRICK ) { + if( RBRICK_EEPROM_STR( info_tmp, nasid, path ) != EEP_OK ) + return NULL; + } + else { + if( eeprom_str( info_tmp, nasid, component ) != EEP_OK ) + return NULL; + } + + /* allocate a smaller final place */ + info_len = strlen(info_tmp)+1; + NEWSZ(info, info_len); + if (info) { + strcpy(info, info_tmp); + DEL(info_tmp); + } else { + info = info_tmp; + } + + /* add info to the vertex */ + hwgraph_info_add_LBL(v, INFO_LBL_NIC, + (arbitrary_info_t) info); + + /* see if someone else got there first */ + info_tmp = nic_vertex_info_get(v); + if (info != info_tmp) { + DEL(info); + return info_tmp; + } + + /* export the data */ + hwgraph_info_export_LBL(v, INFO_LBL_NIC, info_len); + + /* trigger all matching callbacks */ + nic_vmc_check(v, info); + + return info; +} + +#endif /* !_STANDALONE */ + +/********************************************************************* + * + * stubs for use until the Bedrock/L1 link is available + * + */ + +#include + +/* #define EEPROM_TEST */ + +/* fake eeprom reading functions (replace when the BR/L1 communication + * channel is in working order) + */ + + +/* generate a charater in [0-9A-Z]; if an "extra" character is + * specified (such as '_'), include it as one of the possibilities. + */ +char random_eeprom_ch( char extra ) +{ + char ch; + int modval = 36; + if( extra ) + modval++; + + ch = rtc_time() % modval; + + if( ch < 10 ) + ch += '0'; + else if( ch >= 10 && ch < 36 ) + ch += ('A' - 10); + else + ch = extra; + + return ch; +} + +/* create a part number of the form xxx-xxxx-xxx. + * It may be important later to generate different + * part numbers depending on the component we're + * supposed to be "reading" from, so the component + * paramter is provided. + */ +void fake_a_part_number( char *buf, int component ) +{ + int i; + switch( component ) { + + /* insert component-specific routines here */ + + case C_BRICK: + strcpy( buf, "030-1266-001" ); + break; + default: + for( i = 0; i < 12; i++ ) { + if( i == 3 || i == 8 ) + buf[i] = '-'; + else + buf[i] = random_eeprom_ch(0); + } + } +} + + +/* create a six-character serial number */ +void fake_a_serial_number( char *buf, uint64_t ser ) +{ + int i; + static const char hexchars[] = "0123456789ABCDEF"; + + if (ser) { + for( i = 5; i >=0; i-- ) { + buf[i] = hexchars[ser & 0xf]; + ser >>= 4; + } + } + else { + for( i = 0; i < 6; i++ ) + buf[i] = random_eeprom_ch(0); + } +} + + +void fake_a_product_name( uchar_t *format, char* buf, int component ) +{ + switch( component & BRICK_MASK ) { + + case C_BRICK: + if( component & SUBORD_MASK ) { + strcpy( buf, "C_BRICK_SUB" ); + *format = 0xCB; + } + else { + strcpy( buf, "IP35" ); + *format = 0xC4; + } + break; + + case R_BRICK: + if( component & SUBORD_MASK ) { + strcpy( buf, "R_BRICK_SUB" ); + *format = 0xCB; + } + else { + strcpy( buf, "R_BRICK" ); + *format = 0xC7; + } + break; + + case IO_BRICK: + if( component & SUBORD_MASK ) { + strcpy( buf, "IO_BRICK_SUB" ); + *format = 0xCC; + } + else { + strcpy( buf, "IO_BRICK" ); + *format = 0xC8; + } + break; + + default: + strcpy( buf, "UNK_DEVICE" ); + *format = 0xCA; + } +} + + + +int fake_an_eeprom_record( eeprom_brd_record_t *buf, int component, + uint64_t ser ) +{ + eeprom_board_ia_t *board; + eeprom_chassis_ia_t *chassis; + int i, cs; + + board = buf->board_ia; + chassis = buf->chassis_ia; + + if( !(component & SUBORD_MASK) ) { + if( !chassis ) + return EEP_PARAM; + chassis->format = 0; + chassis->length = 5; + chassis->type = 0x17; + + chassis->part_num_tl = 0xCC; + fake_a_part_number( chassis->part_num, component ); + chassis->serial_num_tl = 0xC6; + fake_a_serial_number( chassis->serial_num, ser ); + + cs = chassis->format + chassis->length + chassis->type + + chassis->part_num_tl + chassis->serial_num_tl; + for( i = 0; i < (chassis->part_num_tl & FIELD_LENGTH_MASK); i++ ) + cs += chassis->part_num[i]; + for( i = 0; i < (chassis->serial_num_tl & FIELD_LENGTH_MASK); i++ ) + cs += chassis->serial_num[i]; + chassis->checksum = 256 - (cs % 256); + } + + if( !board ) + return EEP_PARAM; + board->format = 0; + board->length = 10; + board->language = 0; + board->mfg_date = 1789200; /* noon, 5/26/99 */ + board->manuf_tl = 0xC3; + strcpy( board->manuf, "SGI" ); + + fake_a_product_name( &(board->product_tl), board->product, component ); + + board->serial_num_tl = 0xC6; + fake_a_serial_number( board->serial_num, ser ); + + board->part_num_tl = 0xCC; + fake_a_part_number( board->part_num, component ); + + board->board_rev_tl = 0xC2; + board->board_rev[0] = '0'; + board->board_rev[1] = '1'; + + board->eeprom_size_tl = 0x01; + board->eeprom_size = 1; + + board->temp_waiver_tl = 0xC2; + board->temp_waiver[0] = '0'; + board->temp_waiver[1] = '1'; + + cs = board->format + board->length + board->language + + (board->mfg_date & 0xFF) + + (board->mfg_date & 0xFF00) + + (board->mfg_date & 0xFF0000) + + board->manuf_tl + board->product_tl + board->serial_num_tl + + board->part_num_tl + board->board_rev_tl + + board->board_rev[0] + board->board_rev[1] + + board->eeprom_size_tl + board->eeprom_size + board->temp_waiver_tl + + board->temp_waiver[0] + board->temp_waiver[1]; + for( i = 0; i < (board->manuf_tl & FIELD_LENGTH_MASK); i++ ) + cs += board->manuf[i]; + for( i = 0; i < (board->product_tl & FIELD_LENGTH_MASK); i++ ) + cs += board->product[i]; + for( i = 0; i < (board->serial_num_tl & FIELD_LENGTH_MASK); i++ ) + cs += board->serial_num[i]; + for( i = 0; i < (board->part_num_tl & FIELD_LENGTH_MASK); i++ ) + cs += board->part_num[i]; + + board->checksum = 256 - (cs % 256); + + return EEP_OK; +} + +#define EEPROM_CHUNKSIZE 64 + +#if defined(EEPROM_DEBUG) +#define RETURN_ERROR \ +{ \ + printk( "read_ia error return, component 0x%x, line %d" \ + ", address 0x%x, ia code 0x%x\n", \ + l1_compt, __LINE__, sc->subch[subch].target, ia_code ); \ + return EEP_L1; \ +} + +#else +#define RETURN_ERROR return(EEP_L1) +#endif + +int read_ia( l1sc_t *sc, int subch, int l1_compt, + int ia_code, char *eep_record ) +{ +#if !defined(DIRECT_L1_CONSOLE) + char msg[BRL1_QSIZE]; /* message buffer */ + int len; /* number of bytes used in message buffer */ + int ia_len = EEPROM_CHUNKSIZE; /* remaining bytes in info area */ + int offset = 0; /* current offset into info area */ + + BZERO( msg, BRL1_QSIZE ); + + /* retrieve EEPROM data in 64-byte chunks + */ + + while( ia_len ) + { + /* fill in msg with opcode & params */ + if( (len = sc_construct_msg( sc, subch, msg, BRL1_QSIZE, + L1_ADDR_TASK_GENERAL, + L1_REQ_EEPROM, 8, + L1_ARG_INT, l1_compt, + L1_ARG_INT, ia_code, + L1_ARG_INT, offset, + L1_ARG_INT, ia_len )) < 0 ) + { + RETURN_ERROR; + } + + /* send the request to the L1 */ + if( sc_command( sc, subch, msg, msg, &len ) ) { + RETURN_ERROR; + } + + /* check response */ + if( sc_interpret_resp( msg, 5, + L1_ARG_INT, &ia_len, + L1_ARG_UNKNOWN, &len, eep_record ) < 0 ) + { + RETURN_ERROR; + } + + if( ia_len > EEPROM_CHUNKSIZE ) + ia_len = EEPROM_CHUNKSIZE; + + eep_record += EEPROM_CHUNKSIZE; + offset += EEPROM_CHUNKSIZE; + } + + return EEP_OK; + +#else /* can't send requests to the L1 if DIRECT_L1_CONSOLE is defined */ + return EEP_L1; + +#endif /* DIRECT_L1_CONSOLE */ +} + + +int read_spd( l1sc_t *sc, int subch, int l1_compt, + eeprom_spd_u *spd ) +{ +#if !defined(DIRECT_L1_CONSOLE) + char msg[BRL1_QSIZE]; /* message buffer */ + int len; /* number of bytes used in message buffer */ + int spd_len = EEPROM_CHUNKSIZE; /* remaining bytes in spd record */ + int offset = 0; /* current offset into spd record */ + char *spd_p = spd->bytes; /* "thumb" for writing to spd */ + + BZERO( msg, BRL1_QSIZE ); + + /* retrieve EEPROM data in 64-byte chunks + */ + + while( spd_len ) + { + /* fill in msg with opcode & params */ + if( (len = sc_construct_msg( sc, subch, msg, BRL1_QSIZE, + L1_ADDR_TASK_GENERAL, + L1_REQ_EEPROM, 8, + L1_ARG_INT, l1_compt, + L1_ARG_INT, L1_EEP_SPD, + L1_ARG_INT, offset, + L1_ARG_INT, spd_len )) < 0 ) + { + return( EEP_L1 ); + } + + /* send the request to the L1 */ + if( sc_command( sc, subch, msg, msg, &len ) ) { + return( EEP_L1 ); + } + + /* check response */ + if( sc_interpret_resp( msg, 5, + L1_ARG_INT, &spd_len, + L1_ARG_UNKNOWN, &len, spd_p ) < 0 ) + { + return( EEP_L1 ); + } + + if( spd_len > EEPROM_CHUNKSIZE ) + spd_len = EEPROM_CHUNKSIZE; + + spd_p += EEPROM_CHUNKSIZE; + offset += EEPROM_CHUNKSIZE; + } + + return EEP_OK; + +#else /* can't send requests to the L1 if DIRECT_L1_CONSOLE is defined */ + return EEP_L1; + +#endif /* DIRECT_L1_CONSOLE */ +} + + +int read_chassis_ia( l1sc_t *sc, int subch, int l1_compt, + eeprom_chassis_ia_t *ia ) +{ + char eep_record[512]; /* scratch area for building up info area */ + char *eep_rec_p = eep_record; /* thumb for moving through eep_record */ + int checksum = 0; /* use to verify eeprom record checksum */ + int i; + + /* Read in info area record from the L1. + */ + if( read_ia( sc, subch, l1_compt, L1_EEP_CHASSIS, eep_record ) + != EEP_OK ) + { + return EEP_L1; + } + + /* Now we've got the whole info area. Transfer it to the data structure. + */ + + eep_rec_p = eep_record; + ia->format = *eep_rec_p++; + ia->length = *eep_rec_p++; + if( ia->length == 0 ) { + /* since we're using 8*ia->length-1 as an array index later, make + * sure it's sane. + */ + db_printf(( "read_chassis_ia: eeprom length byte of ZERO\n" )); + return EEP_L1; + } + ia->type = *eep_rec_p++; + + ia->part_num_tl = *eep_rec_p++; + + (void)bcopy( eep_rec_p, ia->part_num, (ia->part_num_tl & FIELD_LENGTH_MASK) ); + eep_rec_p += (ia->part_num_tl & FIELD_LENGTH_MASK); + + ia->serial_num_tl = *eep_rec_p++; + + bcopy( eep_rec_p, ia->serial_num, + (ia->serial_num_tl & FIELD_LENGTH_MASK) ); + eep_rec_p += (ia->serial_num_tl & FIELD_LENGTH_MASK); + + ia->checksum = eep_record[(8 * ia->length) - 1]; + + /* verify checksum */ + eep_rec_p = eep_record; + checksum = 0; + for( i = 0; i < (8 * ia->length); i++ ) { + checksum += *eep_rec_p++; + } + + if( (checksum & 0xff) != 0 ) + { + db_printf(( "read_chassis_ia: bad checksum\n" )); + db_printf(( "read_chassis_ia: target 0x%x uart 0x%x\n", + sc->subch[subch].target, sc->uart )); + return EEP_BAD_CHECKSUM; + } + + return EEP_OK; +} + + +int read_board_ia( l1sc_t *sc, int subch, int l1_compt, + eeprom_board_ia_t *ia ) +{ + char eep_record[512]; /* scratch area for building up info area */ + char *eep_rec_p = eep_record; /* thumb for moving through eep_record */ + int checksum = 0; /* running checksum total */ + int i; + + BZERO( ia, sizeof( eeprom_board_ia_t ) ); + + /* Read in info area record from the L1. + */ + if( read_ia( sc, subch, l1_compt, L1_EEP_BOARD, eep_record ) + != EEP_OK ) + { + db_printf(( "read_board_ia: error reading info area from L1\n" )); + return EEP_L1; + } + + /* Now we've got the whole info area. Transfer it to the data structure. + */ + + eep_rec_p = eep_record; + ia->format = *eep_rec_p++; + ia->length = *eep_rec_p++; + if( ia->length == 0 ) { + /* since we're using 8*ia->length-1 as an array index later, make + * sure it's sane. + */ + db_printf(( "read_board_ia: eeprom length byte of ZERO\n" )); + return EEP_L1; + } + ia->language = *eep_rec_p++; + + ia->mfg_date = eeprom_xlate_board_mfr_date( (uchar_t *)eep_rec_p ); + eep_rec_p += 3; + + ia->manuf_tl = *eep_rec_p++; + + bcopy( eep_rec_p, ia->manuf, (ia->manuf_tl & FIELD_LENGTH_MASK) ); + eep_rec_p += (ia->manuf_tl & FIELD_LENGTH_MASK); + + ia->product_tl = *eep_rec_p++; + + bcopy( eep_rec_p, ia->product, (ia->product_tl & FIELD_LENGTH_MASK) ); + eep_rec_p += (ia->product_tl & FIELD_LENGTH_MASK); + + ia->serial_num_tl = *eep_rec_p++; + + bcopy(eep_rec_p, ia->serial_num, (ia->serial_num_tl & FIELD_LENGTH_MASK)); + eep_rec_p += (ia->serial_num_tl & FIELD_LENGTH_MASK); + + ia->part_num_tl = *eep_rec_p++; + + bcopy( eep_rec_p, ia->part_num, (ia->part_num_tl & FIELD_LENGTH_MASK) ); + eep_rec_p += (ia->part_num_tl & FIELD_LENGTH_MASK); + + eep_rec_p++; /* we do not use the FRU file id */ + + ia->board_rev_tl = *eep_rec_p++; + + bcopy( eep_rec_p, ia->board_rev, (ia->board_rev_tl & FIELD_LENGTH_MASK) ); + eep_rec_p += (ia->board_rev_tl & FIELD_LENGTH_MASK); + + ia->eeprom_size_tl = *eep_rec_p++; + ia->eeprom_size = *eep_rec_p++; + + ia->temp_waiver_tl = *eep_rec_p++; + + bcopy( eep_rec_p, ia->temp_waiver, + (ia->temp_waiver_tl & FIELD_LENGTH_MASK) ); + eep_rec_p += (ia->temp_waiver_tl & FIELD_LENGTH_MASK); + + /* if there's more, we must be reading a main board; get + * additional fields + */ + if( ((unsigned char)*eep_rec_p != (unsigned char)EEPROM_EOF) ) { + + ia->ekey_G_tl = *eep_rec_p++; + bcopy( eep_rec_p, (char *)&ia->ekey_G, + ia->ekey_G_tl & FIELD_LENGTH_MASK ); + eep_rec_p += (ia->ekey_G_tl & FIELD_LENGTH_MASK); + + ia->ekey_P_tl = *eep_rec_p++; + bcopy( eep_rec_p, (char *)&ia->ekey_P, + ia->ekey_P_tl & FIELD_LENGTH_MASK ); + eep_rec_p += (ia->ekey_P_tl & FIELD_LENGTH_MASK); + + ia->ekey_Y_tl = *eep_rec_p++; + bcopy( eep_rec_p, (char *)&ia->ekey_Y, + ia->ekey_Y_tl & FIELD_LENGTH_MASK ); + eep_rec_p += (ia->ekey_Y_tl & FIELD_LENGTH_MASK); + + /* + * need to get a couple more fields if this is an I brick + */ + if( ((unsigned char)*eep_rec_p != (unsigned char)EEPROM_EOF) ) { + + ia->mac_addr_tl = *eep_rec_p++; + bcopy( eep_rec_p, ia->mac_addr, + ia->mac_addr_tl & FIELD_LENGTH_MASK ); + eep_rec_p += (ia->mac_addr_tl & FIELD_LENGTH_MASK); + + ia->ieee1394_cfg_tl = *eep_rec_p++; + bcopy( eep_rec_p, ia->ieee1394_cfg, + ia->ieee1394_cfg_tl & FIELD_LENGTH_MASK ); + + } + } + + ia->checksum = eep_record[(ia->length * 8) - 1]; + + /* verify checksum */ + eep_rec_p = eep_record; + checksum = 0; + for( i = 0; i < (8 * ia->length); i++ ) { + checksum += *eep_rec_p++; + } + + if( (checksum & 0xff) != 0 ) + { + db_printf(( "read_board_ia: bad checksum\n" )); + db_printf(( "read_board_ia: target 0x%x uart 0x%x\n", + sc->subch[subch].target, sc->uart )); + return EEP_BAD_CHECKSUM; + } + + return EEP_OK; +} + + +int _cbrick_eeprom_read( eeprom_brd_record_t *buf, l1sc_t *scp, + int component ) +{ +#if !defined(DIRECT_L1_CONSOLE) + + int r; + uint64_t uid = 0; + char uid_str[32]; + int l1_compt, subch; + + /* make sure we're targeting a cbrick */ + if( !(component & C_BRICK) ) + return EEP_PARAM; + + /* If the promlog variable pointed to by IP27LOG_OVNIC is set, + * use that value for the cbrick UID rather than the EEPROM + * serial number. + */ + if( ip27log_getenv( scp->nasid, IP27LOG_OVNIC, uid_str, "0", 0 ) >= 0 ) + { + db_printf(( "_cbrick_eeprom_read: " + "Overriding UID with environment variable %s\n", + IP27LOG_OVNIC )); + uid = strtoull( uid_str, NULL, 0 ); + } + + if( (subch = sc_open( scp, L1_ADDR_LOCAL )) < 0 ) + return EEP_L1; + + switch( component ) + { + case C_BRICK: + /* c-brick motherboard */ + l1_compt = L1_EEP_NODE; + r = read_chassis_ia( scp, subch, l1_compt, buf->chassis_ia ); + if( r != EEP_OK ) { + sc_close( scp, subch ); + db_printf(( "_cbrick_eeprom_read: using a fake eeprom record\n" )); + return fake_an_eeprom_record( buf, component, uid ); + } + if( uid ) { + /* If IP27LOG_OVNIC is set, we want to put that value + * in as our UID. */ + fake_a_serial_number( buf->chassis_ia->serial_num, uid ); + buf->chassis_ia->serial_num_tl = 6; + } + break; + + case C_PIMM: + /* one of the PIMM boards */ + l1_compt = L1_EEP_PIMM( component & COMPT_MASK ); + break; + + case C_DIMM: + /* one of the DIMMs */ + l1_compt = L1_EEP_DIMM( component & COMPT_MASK ); + r = read_spd( scp, subch, l1_compt, buf->spd ); + sc_close( scp, subch ); + return r; + + default: + /* unsupported board type */ + sc_close( scp, subch ); + return EEP_PARAM; + } + + r = read_board_ia( scp, subch, l1_compt, buf->board_ia ); + sc_close( scp, subch ); + if( r != EEP_OK ) + { + db_printf(( "_cbrick_eeprom_read: using a fake eeprom record\n" )); + return fake_an_eeprom_record( buf, component, uid ); + } + return EEP_OK; + +#else /* can't send requests to the L1 if DIRECT_L1_CONSOLE is enabled */ + return EEP_L1; + +#endif /* DIRECT_L1_CONSOLE */ +} + + +int cbrick_eeprom_read( eeprom_brd_record_t *buf, nasid_t nasid, + int component ) +{ +#if !defined(DIRECT_L1_CONSOLE) + +#ifdef _STANDALONE + l1sc_t sc; +#endif + l1sc_t *scp; + int local = (nasid == get_nasid()); + + /* If this brick is retrieving its own uid, use the local l1sc_t to + * arbitrate access to the l1; otherwise, set up a new one (prom) or + * use an existing remote l1sc_t (kernel) + */ + if( local ) { + scp = get_l1sc(); + } + else { +#ifdef _STANDALONE + scp = ≻ + sc_init( &sc, nasid, BRL1_LOCALUART ); +#else + scp = &NODEPDA( NASID_TO_COMPACT_NODEID(nasid) )->module->elsc; +#endif + } + + return _cbrick_eeprom_read( buf, scp, component ); + +#else /* can't send requests to the L1 if DIRECT_L1_CONSOLE is defined */ + return EEP_L1; + +#endif /* DIRECT_L1_CONSOLE */ +} + + +int iobrick_eeprom_read( eeprom_brd_record_t *buf, nasid_t nasid, + int component ) +{ +#if !defined(DIRECT_L1_CONSOLE) + + int r; + int l1_compt, subch; +#ifdef _STANDALONE + l1sc_t sc; +#endif + l1sc_t *scp; + int local = (nasid == get_nasid()); + + /* make sure we're talking to an applicable brick */ + if( !(component & IO_BRICK) ) { + return EEP_PARAM; + } + + /* If we're talking to this c-brick's attached io brick, use + * the local l1sc_t; otherwise, set up a new one (prom) or + * use an existing remote l1sc_t (kernel) + */ + if( local ) { + scp = get_l1sc(); + } + else { +#ifdef _STANDALONE + scp = ≻ + sc_init( &sc, nasid, BRL1_LOCALUART ); +#else + scp = &NODEPDA( NASID_TO_COMPACT_NODEID(nasid) )->module->elsc; +#endif + } + + if( (subch = sc_open( scp, L1_ADDR_LOCALIO )) < 0 ) + return EEP_L1; + + switch( component ) + { + case IO_BRICK: + /* IO brick motherboard */ + l1_compt = L1_EEP_LOGIC; + r = read_chassis_ia( scp, subch, l1_compt, buf->chassis_ia ); + + if( r != EEP_OK ) { + sc_close( scp, subch ); +#ifdef BRINGUP /* Once EEPROMs are universally available, remove this */ + r = fake_an_eeprom_record( buf, component, rtc_time() ); +#endif /* BRINGUP */ + return r; + } + break; + + case IO_POWER: + /* IO brick power board */ + l1_compt = L1_EEP_POWER; + break; + + default: + /* unsupported board type */ + sc_close( scp, subch ); + return EEP_PARAM; + } + + r = read_board_ia( scp, subch, l1_compt, buf->board_ia ); + sc_close( scp, subch ); + if( r != EEP_OK ) { + return r; + } + return EEP_OK; + +#else /* can't send requests to the L1 if DIRECT_L1_CONSOLE is defined */ + return EEP_L1; + +#endif /* DIRECT_L1_CONSOLE */ +} + + +int vector_eeprom_read( eeprom_brd_record_t *buf, nasid_t nasid, + net_vec_t path, int component ) +{ +#if !defined(DIRECT_L1_CONSOLE) + + int r; + uint64_t uid = 0; + int l1_compt, subch; + l1sc_t sc; + + /* make sure we're targeting an applicable brick */ + if( !(component & VECTOR) ) + return EEP_PARAM; + + switch( component & BRICK_MASK ) + { + case R_BRICK: + ROUTER_LOCK( path ); + sc_init( &sc, nasid, path ); + + if( (subch = sc_open( &sc, L1_ADDR_LOCAL )) < 0 ) + { + db_printf(( "vector_eeprom_read: couldn't open subch\n" )); + ROUTER_UNLOCK(path); + return EEP_L1; + } + switch( component ) + { + case R_BRICK: + /* r-brick motherboard */ + l1_compt = L1_EEP_LOGIC; + r = read_chassis_ia( &sc, subch, l1_compt, buf->chassis_ia ); + if( r != EEP_OK ) { + sc_close( &sc, subch ); + ROUTER_UNLOCK( path ); + printk( "vector_eeprom_read: couldn't get rbrick eeprom info;" + " using current time as uid\n" ); + uid = rtc_time(); + db_printf(("vector_eeprom_read: using a fake eeprom record\n")); + return fake_an_eeprom_record( buf, component, uid ); + } + break; + + case R_POWER: + /* r-brick power board */ + l1_compt = L1_EEP_POWER; + break; + + default: + /* unsupported board type */ + sc_close( &sc, subch ); + ROUTER_UNLOCK( path ); + return EEP_PARAM; + } + r = read_board_ia( &sc, subch, l1_compt, buf->board_ia ); + sc_close( &sc, subch ); + ROUTER_UNLOCK( path ); + if( r != EEP_OK ) { + db_printf(( "vector_eeprom_read: using a fake eeprom record\n" )); + return fake_an_eeprom_record( buf, component, uid ); + } + return EEP_OK; + + case C_BRICK: + sc_init( &sc, nasid, path ); + return _cbrick_eeprom_read( buf, &sc, component ); + + default: + /* unsupported brick type */ + return EEP_PARAM; + } + +#else /* can't send requests to the L1 if DIRECT_L1_CONSOLE is defined */ + + return EEP_L1; + +#endif /* DIRECT_L1_CONSOLE */ +} + diff -urN linux-2.4.0-test10/arch/ia64/sn/io/hcl.c linux-2.4.0-test10-lia/arch/ia64/sn/io/hcl.c --- linux-2.4.0-test10/arch/ia64/sn/io/hcl.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/hcl.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,1506 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * hcl - SGI's Hardware Graph compatibility layer. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HCL_NAME "SGI-HWGRAPH COMPATIBILITY DRIVER" +#define HCL_TEMP_NAME "HCL_TEMP_NAME_USED_FOR_HWGRAPH_VERTEX_CREATE" +#define HCL_TEMP_NAME_LEN 44 +#define HCL_VERSION "1.0" +devfs_handle_t hwgraph_root = NULL; + +/* + * Debug flag definition. + */ +#define OPTION_NONE 0x00 +#define HCL_DEBUG_NONE 0x00000 +#define HCL_DEBUG_ALL 0x0ffff +#if defined(CONFIG_HCL_DEBUG) +static unsigned int hcl_debug_init __initdata = HCL_DEBUG_NONE; +#endif +static unsigned int hcl_debug = HCL_DEBUG_NONE; +static unsigned int boot_options = OPTION_NONE; + +/* + * Some Global definitions. + */ +spinlock_t hcl_spinlock; +devfs_handle_t hcl_handle = NULL; + +/* + * HCL device driver. + * The purpose of this device driver is to provide a facility + * for User Level Apps e.g. hinv, ioconfig etc. an ioctl path + * to manipulate label entries without having to implement + * system call interfaces. This methodology will enable us to + * make this feature module loadable. + */ +static int hcl_open(struct inode * inode, struct file * filp) +{ + if (hcl_debug) { + printk("HCL: hcl_open called.\n"); + } + + return(0); + +} + +static int hcl_close(struct inode * inode, struct file * filp) +{ + + if (hcl_debug) { + printk("HCL: hcl_close called.\n"); + } + + return(0); + +} + +static int hcl_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, unsigned long arg) +{ + + if (hcl_debug) { + printk("HCL: hcl_ioctl called.\n"); + } + + switch (cmd) { + default: + if (hcl_debug) { + printk("HCL: hcl_ioctl cmd = 0x%x\n", cmd); + } + } + + return(0); + +} + +struct file_operations hcl_fops = { + NULL, /* lseek - default */ + NULL, /* read - general block-dev read */ + NULL, /* write - general block-dev write */ + NULL, /* readdir - bad */ + NULL, /* poll */ + hcl_ioctl, /* ioctl */ + NULL, /* mmap */ + hcl_open, /* open */ + NULL, /* flush */ + hcl_close, /* release */ + NULL, /* fsync */ + NULL, /* fasync */ + NULL, /* check_media_change */ + NULL, /* revalidate */ + NULL /* lock */ +}; + + +/* + * init_hcl() - Boot time initialization. Ensure that it is called + * after devfs has been initialized. + * + * For now this routine is being called out of devfs/base.c. Actually + * Not a bad place to be .. + * + */ +#ifdef MODULE +int init_module (void) +#else +int __init init_hcl(void) +#endif +{ + extern void string_table_init(struct string_table *); + extern struct string_table label_string_table; + int rv = 0; + + printk ("\n%s: v%s Colin Ngam (cngam@sgi.com)\n", + HCL_NAME, HCL_VERSION); +#if defined(CONFIG_HCL_DEBUG) && !defined(MODULE) + hcl_debug = hcl_debug_init; + printk ("%s: hcl_debug: 0x%0x\n", HCL_NAME, hcl_debug); +#endif + printk ("\n%s: boot_options: 0x%0x\n", HCL_NAME, boot_options); + spin_lock_init(&hcl_spinlock); + + /* + * Create the hwgraph_root on devfs. + */ + rv = hwgraph_path_add(NULL, "hw", &hwgraph_root); + if (rv) + printk ("init_hcl: Failed to create hwgraph_root. Error = %d.\n", rv); + + /* + * Create the hcl driver to support inventory entry manipulations. + * By default, it is expected that devfs is mounted on /dev. + * + */ + hcl_handle = hwgraph_register(hwgraph_root, ".hcl", + 0, DEVFS_FL_AUTO_DEVNUM, + 0, 0, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0, + &hcl_fops, NULL); + + if (hcl_handle == NULL) { + panic("HCL: Unable to create HCL Driver in init_hcl().\n"); + return(0); + } + + /* + * Initialize the HCL string table. + */ + string_table_init(&label_string_table); + + return(0); + +} + + +/* + * hcl_setup() - Process boot time parameters if given. + * "hcl=" + * This routine gets called only if "hcl=" is given in the + * boot line and before init_hcl(). + * + * We currently do not have any boot options .. when we do, + * functionalities can be added here. + * + */ +static int __init hcl_setup(char *str) +{ + while ( (*str != '\0') && !isspace (*str) ) + { + printk("HCL: Boot time parameter %s\n", str); +#ifdef CONFIG_HCL_DEBUG + if (strncmp (str, "all", 3) == 0) { + hcl_debug_init |= HCL_DEBUG_ALL; + str += 3; + } else + return 0; +#endif + if (*str != ',') return 0; + ++str; + } + + return 1; + +} + +__setup("hcl=", hcl_setup); + + +/* + * Set device specific "fast information". + * + */ +void +hwgraph_fastinfo_set(devfs_handle_t de, arbitrary_info_t fastinfo) +{ + + if (hcl_debug) { + printk("HCL: hwgraph_fastinfo_set handle 0x%p fastinfo %ld\n", + de, fastinfo); + } + + labelcl_info_replace_IDX(de, HWGRAPH_FASTINFO, fastinfo, NULL); + +} + + +/* + * Get device specific "fast information". + * + */ +arbitrary_info_t +hwgraph_fastinfo_get(devfs_handle_t de) +{ + arbitrary_info_t fastinfo; + int rv; + + if (!de) { + printk(KERN_WARNING "HCL: hwgraph_fastinfo_get handle given is NULL.\n"); + return(-1); + } + + rv = labelcl_info_get_IDX(de, HWGRAPH_FASTINFO, &fastinfo); + if (rv == 0) + return(fastinfo); + + return(0); +} + + +/* + * hwgraph_connectpt_set - Sets the connect point handle in de to the + * given connect_de handle. By default, the connect point of the + * devfs node is the parent. This effectively changes this assumption. + */ +int +hwgraph_connectpt_set(devfs_handle_t de, devfs_handle_t connect_de) +{ + int rv; + + if (!de) + return(-1); + + rv = labelcl_info_connectpt_set(de, connect_de); + + return(rv); +} + + +/* + * hwgraph_connectpt_get: Returns the entry's connect point in the devfs + * tree. + */ +devfs_handle_t +hwgraph_connectpt_get(devfs_handle_t de) +{ + int rv; + arbitrary_info_t info; + devfs_handle_t connect; + + rv = labelcl_info_get_IDX(de, HWGRAPH_CONNECTPT, &info); + if (rv != 0) { + return(NULL); + } + + connect = (devfs_handle_t)info; + return(connect); + +} + + +/* + * hwgraph_mk_dir - Creates a directory entry with devfs. + * Note that a directory entry in devfs can have children + * but it cannot be a char|block special file. + */ +devfs_handle_t +hwgraph_mk_dir(devfs_handle_t de, const char *name, + unsigned int namelen, void *info) +{ + + int rv; + labelcl_info_t *labelcl_info = NULL; + devfs_handle_t new_devfs_handle = NULL; + devfs_handle_t parent = NULL; + + /* + * Create the device info structure for hwgraph compatiblity support. + */ + labelcl_info = labelcl_info_create(); + if (!labelcl_info) + return(NULL); + + /* + * Create a devfs entry. + */ + new_devfs_handle = devfs_mk_dir(de, name, (void *)labelcl_info); + if (!new_devfs_handle) { + labelcl_info_destroy(labelcl_info); + return(NULL); + } + + /* + * Get the parent handle. + */ + parent = devfs_get_parent (new_devfs_handle); + + /* + * To provide the same semantics as the hwgraph, set the connect point. + */ + rv = hwgraph_connectpt_set(new_devfs_handle, parent); + if (!rv) { + /* + * We need to clean up! + */ + } + + /* + * If the caller provides a private data pointer, save it in the + * labelcl info structure(fastinfo). This can be retrieved via + * hwgraph_fastinfo_get() + */ + if (info) + hwgraph_fastinfo_set(new_devfs_handle, (arbitrary_info_t)info); + + return(new_devfs_handle); + +} + +/* + * hwgraph_vertex_create - Create a vertex by giving it a temp name. + */ + +/* + * hwgraph_path_add - Create a directory node with the given path starting + * from the given devfs_handle_t. + */ +extern char * dev_to_name(devfs_handle_t, char *, uint); +int +hwgraph_path_add(devfs_handle_t fromv, + char *path, + devfs_handle_t *new_de) +{ + + unsigned int namelen = strlen(path); + int rv; + + /* + * We need to handle the case when fromv is NULL .. + * in this case we need to create the path from the + * hwgraph root! + */ + if (fromv == NULL) + fromv = hwgraph_root; + + /* + * check the entry doesn't already exist, if it does + * then we simply want new_de to point to it (otherwise + * we'll overwrite the existing labelcl_info struct) + */ + rv = hwgraph_edge_get(fromv, path, new_de); + if (rv) { /* couldn't find entry so we create it */ + *new_de = hwgraph_mk_dir(fromv, path, namelen, NULL); + if (new_de == NULL) + return(-1); + else + return(0); + } + else + return(0); + +} + +/* + * hwgraph_register - Creates a file entry with devfs. + * Note that a file entry cannot have children .. it is like a + * char|block special vertex in hwgraph. + */ +devfs_handle_t +hwgraph_register(devfs_handle_t de, const char *name, + unsigned int namelen, unsigned int flags, + unsigned int major, unsigned int minor, + umode_t mode, uid_t uid, gid_t gid, + struct file_operations *fops, + void *info) +{ + + int rv; + void *labelcl_info = NULL; + devfs_handle_t new_devfs_handle = NULL; + devfs_handle_t parent = NULL; + + /* + * Create the labelcl info structure for hwgraph compatiblity support. + */ + labelcl_info = labelcl_info_create(); + if (!labelcl_info) + return(NULL); + + /* + * Create a devfs entry. + */ + new_devfs_handle = devfs_register(de, name, flags, major, + minor, mode, fops, labelcl_info); + if (!new_devfs_handle) { + labelcl_info_destroy((labelcl_info_t *)labelcl_info); + return(NULL); + } + + /* + * Get the parent handle. + */ + if (de == NULL) + parent = devfs_get_parent (new_devfs_handle); + else + parent = de; + + /* + * To provide the same semantics as the hwgraph, set the connect point. + */ + rv = hwgraph_connectpt_set(new_devfs_handle, parent); + if (rv) { + /* + * We need to clean up! + */ + printk("HCL: Unable to set the connect point to it's parent 0x%p\n", + new_devfs_handle); + } + + /* + * If the caller provides a private data pointer, save it in the + * labelcl info structure(fastinfo). This can be retrieved via + * hwgraph_fastinfo_get() + */ + if (info) + hwgraph_fastinfo_set(new_devfs_handle, (arbitrary_info_t)info); + + return(new_devfs_handle); + +} + + +/* + * hwgraph_mk_symlink - Create a symbolic link. + */ +int +hwgraph_mk_symlink(devfs_handle_t de, const char *name, unsigned int namelen, + unsigned int flags, const char *link, unsigned int linklen, + devfs_handle_t *handle, void *info) +{ + + void *labelcl_info = NULL; + int status = 0; + devfs_handle_t new_devfs_handle = NULL; + + /* + * Create the labelcl info structure for hwgraph compatiblity support. + */ + labelcl_info = labelcl_info_create(); + if (!labelcl_info) + return(-1); + + /* + * Create a symbolic link devfs entry. + */ + status = devfs_mk_symlink(de, name, flags, link, + &new_devfs_handle, labelcl_info); + if ( (!new_devfs_handle) || (!status) ){ + labelcl_info_destroy((labelcl_info_t *)labelcl_info); + return(-1); + } + + /* + * If the caller provides a private data pointer, save it in the + * labelcl info structure(fastinfo). This can be retrieved via + * hwgraph_fastinfo_get() + */ + if (info) + hwgraph_fastinfo_set(new_devfs_handle, (arbitrary_info_t)info); + + *handle = new_devfs_handle; + return(0); + +} + +/* + * hwgraph_vertex_get_next - this routine returns the next sibbling for the + * device entry given in de. If there are no more sibbling, NULL + * is returned in next_sibbling. + * + * Currently we do not have any protection against de being deleted + * while it's handle is being held. + */ +int +hwgraph_vertex_get_next(devfs_handle_t *next_sibbling, devfs_handle_t *de) +{ + *next_sibbling = devfs_get_next_sibling (*de); + + if (*next_sibbling != NULL) + *de = *next_sibbling; + return (0); +} + + +/* + * hwgraph_vertex_destroy - Destroy the devfs entry + */ +int +hwgraph_vertex_destroy(devfs_handle_t de) +{ + + void *labelcl_info = NULL; + + labelcl_info = devfs_get_info(de); + devfs_unregister(de); + + if (labelcl_info) + labelcl_info_destroy((labelcl_info_t *)labelcl_info); + + return(0); +} + +/* +** See if a vertex has an outgoing edge with a specified name. +** Vertices in the hwgraph *implicitly* contain these edges: +** "." refers to "current vertex" +** ".." refers to "connect point vertex" +** "char" refers to current vertex (character device access) +** "block" refers to current vertex (block device access) +*/ + +/* + * hwgraph_edge_add - This routines has changed from the original conext. + * All it does now is to create a symbolic link from "from" to "to". + */ +/* ARGSUSED */ +int +hwgraph_edge_add(devfs_handle_t from, devfs_handle_t to, char *name) +{ + + char *path; + int name_start; + devfs_handle_t handle = NULL; + int rv; + + path = kmalloc(1024, GFP_KERNEL); + name_start = devfs_generate_path (to, path, 1024); + + /* + * Otherwise, just create a symlink to the vertex. + * In this case the vertex was previous created with a REAL pathname. + */ + rv = devfs_mk_symlink (from, (const char *)name, + DEVFS_FL_DEFAULT, (const char *)&path[name_start], + &handle, NULL); + + name_start = devfs_generate_path (handle, path, 1024); + return(rv); + + +} +/* ARGSUSED */ +int +hwgraph_edge_get(devfs_handle_t from, char *name, devfs_handle_t *toptr) +{ + + int namelen = 0; + devfs_handle_t target_handle = NULL; + + if (name == NULL) + return(-1); + + if (toptr == NULL) + return(-1); + + /* + * If the name is "." just return the current devfs entry handle. + */ + if (!strcmp(name, HWGRAPH_EDGELBL_DOT)) { + if (toptr) { + *toptr = from; + } + } else if (!strcmp(name, HWGRAPH_EDGELBL_DOTDOT)) { + /* + * Hmmm .. should we return the connect point or parent .. + * see in hwgraph, the concept of parent is the connectpt! + * + * Maybe we should see whether the connectpt is set .. if + * not just return the parent! + */ + target_handle = hwgraph_connectpt_get(from); + if (target_handle) { + /* + * Just return the connect point. + */ + *toptr = target_handle; + return(0); + } + target_handle = devfs_get_parent(from); + *toptr = target_handle; + + } else { + /* + * Call devfs to get the devfs entry. + */ + namelen = (int) strlen(name); + target_handle = devfs_find_handle (from, name, 0, 0, + 0, 1); /* Yes traverse symbolic links */ + if (target_handle == NULL) + return(-1); + else + *toptr = target_handle; + } + + return(0); +} + + +/* + * hwgraph_edge_get_next - Retrieves the next sibbling given the current + * entry number "placeptr". + * + * Allow the caller to retrieve walk through the sibblings of "source" + * devfs_handle_t. The implicit edges "." and ".." is returned first + * followed by each of the real children. + * + * We may end up returning garbage if another thread perform any deletion + * in this directory before "placeptr". + * + */ +/* ARGSUSED */ +int +hwgraph_edge_get_next(devfs_handle_t source, char *name, devfs_handle_t *target, + uint *placeptr) + +{ + + uint which_place; + unsigned int namelen = 0; + const char *tempname = NULL; + + if (placeptr == NULL) + return(-1); + + which_place = *placeptr; + +again: + if (which_place <= HWGRAPH_RESERVED_PLACES) { + if (which_place == EDGE_PLACE_WANT_CURRENT) { + /* + * Looking for "." + * Return the current devfs handle. + */ + if (name != NULL) + strcpy(name, HWGRAPH_EDGELBL_DOT); + + if (target != NULL) { + *target = source; + /* XXX should incr "source" ref count here if we + * ever implement ref counts */ + } + + } else if (which_place == EDGE_PLACE_WANT_CONNECTPT) { + /* + * Looking for the connect point or parent. + * If the connect point is set .. it returns the connect point. + * Otherwise, it returns the parent .. will we support + * connect point? + */ + devfs_handle_t connect_point = hwgraph_connectpt_get(source); + + if (connect_point == NULL) { + /* + * No connectpoint set .. either the User + * explicitly NULL it or this node was not + * created via hcl. + */ + which_place++; + goto again; + } + + if (name != NULL) + strcpy(name, HWGRAPH_EDGELBL_DOTDOT); + + if (target != NULL) + *target = connect_point; + + } else if (which_place == EDGE_PLACE_WANT_REAL_EDGES) { + /* + * return first "real" entry in directory, and increment + * placeptr. Next time around we should have + * which_place > HWGRAPH_RESERVED_EDGES so we'll fall through + * this nested if block. + */ + *target = devfs_get_first_child(source); + if (*target && name) { + tempname = devfs_get_name(*target, &namelen); + if (tempname && namelen) + strcpy(name, tempname); + } + + *placeptr = which_place + 1; + return (0); + } + + *placeptr = which_place+1; + return(0); + } + + /* + * walk linked list, (which_place - HWGRAPH_RESERVED_PLACES) times + */ + { + devfs_handle_t curr; + int i = 0; + + for (curr=devfs_get_first_child(source), i= i+HWGRAPH_RESERVED_PLACES; + curr!=NULL && iinv_next) { + if ((int)class != -1 && old_pinv->inv_class != class) + continue; + if ((int)type != -1 && old_pinv->inv_type != type) + continue; + if ((int)state != -1 && old_pinv->inv_state != state) + continue; + if ((int)controller != -1 + && old_pinv->inv_controller != controller) + continue; + if ((int)unit != -1 && old_pinv->inv_unit != unit) + continue; + + /* exact duplicate of previously-added inventory item */ + rv = LABELCL_DUP; + goto failure; + } + + /* Not a duplicate, so we know that we need to add something. */ + if (pinv == NULL) { + /* Release lock while we wait for memory. */ + /* GRAPH_LOCK_DONE_UPDATE(&invent_lock); */ + pinv = (inventory_t *)kmalloc(sizeof(inventory_t), GFP_KERNEL); + replace_in_inventory(pinv, class, type, controller, unit, state); + goto again; + } + + pinv->inv_next = NULL; + if (last_pinv) { + last_pinv->inv_next = pinv; + } else { + rv = labelcl_info_add_LBL(de, INFO_LBL_INVENT, + sizeof(inventory_t), (arbitrary_info_t)pinv); + + if (!rv) + goto failure; + } + + /* GRAPH_LOCK_DONE_UPDATE(&invent_lock); */ + return(0); + +failure: + /* GRAPH_LOCK_DONE_UPDATE(&invent_lock); */ + if (pinv) + kfree(pinv); + return(rv); +} + + +/* + * hwgraph_inventory_remove - Removes an inventory entry. + * + * Remove an inventory item associated with a vertex. It is the caller's + * responsibility to make sure that there are no races between removing + * inventory from a vertex and simultaneously removing that vertex. +*/ +int +hwgraph_inventory_remove( devfs_handle_t de, + int class, + int type, + major_t controller, + minor_t unit, + int state) +{ + inventory_t *pinv = NULL, *last_pinv = NULL, *next_pinv = NULL; + labelcl_error_t rv; + + /* + * We never remove stuff from ".invent" .. + */ + if (!de) + return (-1); + + /* + * Remove our inventory data to the list of inventory data + * associated with this vertex. + */ + /* GRAPH_LOCK_UPDATE(&invent_lock); */ + rv = labelcl_info_get_LBL(de, + INFO_LBL_INVENT, + NULL, (arbitrary_info_t *)&pinv); + if (rv != LABELCL_SUCCESS) + goto failure; + + /* + * Search through inventory items associated with this + * vertex, looking for a match. + */ + for (;pinv; pinv = next_pinv) { + next_pinv = pinv->inv_next; + + if(((int)class == -1 || pinv->inv_class == class) && + ((int)type == -1 || pinv->inv_type == type) && + ((int)state == -1 || pinv->inv_state == state) && + ((int)controller == -1 || pinv->inv_controller == controller) && + ((int)unit == -1 || pinv->inv_unit == unit)) { + + /* Found a matching inventory item. Remove it. */ + if (last_pinv) { + last_pinv->inv_next = pinv->inv_next; + } else { + rv = hwgraph_info_replace_LBL(de, INFO_LBL_INVENT, (arbitrary_info_t)pinv->inv_next, NULL); + if (rv != LABELCL_SUCCESS) + goto failure; + } + + pinv->inv_next = NULL; /* sanity */ + kfree(pinv); + } else + last_pinv = pinv; + } + + if (last_pinv == NULL) { + rv = hwgraph_info_remove_LBL(de, INFO_LBL_INVENT, NULL); + if (rv != LABELCL_SUCCESS) + goto failure; + } + + rv = LABELCL_SUCCESS; + +failure: + /* GRAPH_LOCK_DONE_UPDATE(&invent_lock); */ + return(rv); +} + +/* + * hwgraph_inventory_get_next - Get next inventory item associated with the + * specified vertex. + * + * No locking is really needed. We don't yet have the ability + * to remove inventory items, and new items are always added to + * the end of a vertex' inventory list. + * + * However, a devfs entry can be removed! +*/ +int +hwgraph_inventory_get_next(devfs_handle_t de, invplace_t *place, inventory_t **ppinv) +{ + inventory_t *pinv; + labelcl_error_t rv; + + if (de == NULL) + return(LABELCL_BAD_PARAM); + + if (place->invplace_vhdl == NULL) { + place->invplace_vhdl = de; + place->invplace_inv = NULL; + } + + if (de != place->invplace_vhdl) + return(LABELCL_BAD_PARAM); + + if (place->invplace_inv == NULL) { + /* Just starting on this vertex */ + rv = labelcl_info_get_LBL(de, INFO_LBL_INVENT, + NULL, (arbitrary_info_t *)&pinv); + if (rv != LABELCL_SUCCESS) + return(LABELCL_NOT_FOUND); + + } else { + /* Advance to next item on this vertex */ + pinv = place->invplace_inv->inv_next; + } + place->invplace_inv = pinv; + *ppinv = pinv; + + return(LABELCL_SUCCESS); +} + +/* + * hwgraph_controller_num_get - Returns the controller number in the inventory + * entry. + */ +int +hwgraph_controller_num_get(devfs_handle_t device) +{ + inventory_t *pinv; + invplace_t invplace = { NULL, NULL, NULL }; + int val = -1; + if ((pinv = device_inventory_get_next(device, &invplace)) != NULL) { + val = (pinv->inv_class == INV_NETWORK)? pinv->inv_unit: pinv->inv_controller; + } +#ifdef DEBUG + /* + * It does not make any sense to call this on vertexes with multiple + * inventory structs chained together + */ + if ( device_inventory_get_next(device, &invplace) != NULL ) { + printk("Should panic here ... !\n"); +#endif + return (val); +} + +/* + * hwgraph_controller_num_set - Sets the controller number in the inventory + * entry. + */ +void +hwgraph_controller_num_set(devfs_handle_t device, int contr_num) +{ + inventory_t *pinv; + invplace_t invplace = { NULL, NULL, NULL }; + if ((pinv = device_inventory_get_next(device, &invplace)) != NULL) { + if (pinv->inv_class == INV_NETWORK) + pinv->inv_unit = contr_num; + else { + if (pinv->inv_class == INV_FCNODE) + pinv = device_inventory_get_next(device, &invplace); + if (pinv != NULL) + pinv->inv_controller = contr_num; + } + } +#ifdef DEBUG + /* + * It does not make any sense to call this on vertexes with multiple + * inventory structs chained together + */ + if(pinv != NULL) + ASSERT(device_inventory_get_next(device, &invplace) == NULL); +#endif +} + +/* + * Find the canonical name for a given vertex by walking back through + * connectpt's until we hit the hwgraph root vertex (or until we run + * out of buffer space or until something goes wrong). + * + * COMPATIBILITY FUNCTIONALITY + * Walks back through 'parents', not necessarily the same as connectpts. + * + * Need to resolve the fact that devfs does not return the path from + * "/" but rather it just stops right before /dev .. + */ +int +hwgraph_vertex_name_get(devfs_handle_t vhdl, char *buf, uint buflen) +{ + char *locbuf; + int pos; + + if (buflen < 1) + return(-1); /* XXX should be GRAPH_BAD_PARAM ? */ + + locbuf = kmalloc(buflen, GFP_KERNEL); + + pos = devfs_generate_path(vhdl, locbuf, buflen); + if (pos < 0) { + kfree(locbuf); + return pos; + } + + strcpy(buf, &locbuf[pos]); + kfree(locbuf); + return 0; +} + +/* +** vertex_to_name converts a vertex into a canonical name by walking +** back through connect points until we hit the hwgraph root (or until +** we run out of buffer space). +** +** Usually returns a pointer to the original buffer, filled in as +** appropriate. If the buffer is too small to hold the entire name, +** or if anything goes wrong while determining the name, vertex_to_name +** returns "UnknownDevice". +*/ + +#define DEVNAME_UNKNOWN "UnknownDevice" + +char * +vertex_to_name(devfs_handle_t vhdl, char *buf, uint buflen) +{ + if (hwgraph_vertex_name_get(vhdl, buf, buflen) == GRAPH_SUCCESS) + return(buf); + else + return(DEVNAME_UNKNOWN); +} + +#ifdef IRIX +/* +** Return the compact node id of the node that ultimately "owns" the specified +** vertex. In order to do this, we walk back through masters and connect points +** until we reach a vertex that represents a node. +*/ +cnodeid_t +master_node_get(devfs_handle_t vhdl) +{ + cnodeid_t cnodeid; + devfs_handle_t master; + + for (;;) { + cnodeid = nodevertex_to_cnodeid(vhdl); + if (cnodeid != CNODEID_NONE) + return(cnodeid); + + master = device_master_get(vhdl); + + /* Check for exceptional cases */ + if (master == vhdl) { + /* Since we got a reference to the "master" thru + * device_master_get() we should decrement + * its reference count by 1 + */ + hwgraph_vertex_unref(master); + return(CNODEID_NONE); + } + + if (master == GRAPH_VERTEX_NONE) { + master = hwgraph_connectpt_get(vhdl); + if ((master == GRAPH_VERTEX_NONE) || + (master == vhdl)) { + if (master == vhdl) + /* Since we got a reference to the + * "master" thru + * hwgraph_connectpt_get() we should + * decrement its reference count by 1 + */ + hwgraph_vertex_unref(master); + return(CNODEID_NONE); + } + } + + vhdl = master; + /* Decrement the reference to "master" which was got + * either thru device_master_get() or hwgraph_connectpt_get() + * above. + */ + hwgraph_vertex_unref(master); + } +} + +/* + * Using the canonical path name to get hold of the desired vertex handle will + * not work on multi-hub sn0 nodes. Hence, we use the following (slightly + * convoluted) algorithm. + * + * - Start at the vertex corresponding to the driver (provided as input parameter) + * - Loop till you reach a vertex which has EDGE_LBL_MEMORY + * - If EDGE_LBL_CONN exists, follow that up. + * else if EDGE_LBL_MASTER exists, follow that up. + * else follow EDGE_LBL_DOTDOT up. + * + * * We should be at desired hub/heart vertex now * + * - Follow EDGE_LBL_CONN to the widget vertex. + * + * - return vertex handle of this widget. + */ +devfs_handle_t +mem_vhdl_get(devfs_handle_t drv_vhdl) +{ +devfs_handle_t cur_vhdl, cur_upper_vhdl; +devfs_handle_t tmp_mem_vhdl, mem_vhdl; +graph_error_t loop_rv; + + /* Initializations */ + cur_vhdl = drv_vhdl; + loop_rv = ~GRAPH_SUCCESS; + + /* Loop till current vertex has EDGE_LBL_MEMORY */ + while (loop_rv != GRAPH_SUCCESS) { + + if ((hwgraph_edge_get(cur_vhdl, EDGE_LBL_CONN, &cur_upper_vhdl)) == GRAPH_SUCCESS) { + + } else if ((hwgraph_edge_get(cur_vhdl, EDGE_LBL_MASTER, &cur_upper_vhdl)) == GRAPH_SUCCESS) { + } else { /* Follow HWGRAPH_EDGELBL_DOTDOT up */ + (void) hwgraph_edge_get(cur_vhdl, HWGRAPH_EDGELBL_DOTDOT, &cur_upper_vhdl); + } + + cur_vhdl = cur_upper_vhdl; + +#if DEBUG && HWG_DEBUG + printf("Current vhdl %d \n", cur_vhdl); +#endif /* DEBUG */ + + loop_rv = hwgraph_edge_get(cur_vhdl, EDGE_LBL_MEMORY, &tmp_mem_vhdl); + } + + /* We should be at desired hub/heart vertex now */ + if ((hwgraph_edge_get(cur_vhdl, EDGE_LBL_CONN, &mem_vhdl)) != GRAPH_SUCCESS) + return (GRAPH_VERTEX_NONE); + + return (mem_vhdl); +} +#endif /* IRIX */ + + +/* +** Add a char device -- if the driver supports it -- at a specified vertex. +*/ +graph_error_t +hwgraph_char_device_add( devfs_handle_t from, + char *path, + char *prefix, + devfs_handle_t *devhdl) +{ + devfs_handle_t xx = NULL; + + printk("FIXME: hwgraph_char_device_add() called. Use hwgraph_register.\n"); + *devhdl = xx; // Must set devhdl + return(GRAPH_SUCCESS); +} + +graph_error_t +hwgraph_edge_remove(devfs_handle_t from, char *name, devfs_handle_t *toptr) +{ + printk("FIXME: hwgraph_edge_remove\n"); + return(GRAPH_ILLEGAL_REQUEST); +} + +graph_error_t +hwgraph_vertex_unref(devfs_handle_t vhdl) +{ + printk("FIXME: hwgraph_vertex_unref\n"); + return(GRAPH_ILLEGAL_REQUEST); +} + + +EXPORT_SYMBOL(hwgraph_mk_dir); +EXPORT_SYMBOL(hwgraph_path_add); +EXPORT_SYMBOL(hwgraph_char_device_add); +EXPORT_SYMBOL(hwgraph_register); +EXPORT_SYMBOL(hwgraph_vertex_destroy); + +EXPORT_SYMBOL(hwgraph_fastinfo_get); +EXPORT_SYMBOL(hwgraph_edge_get); + +EXPORT_SYMBOL(hwgraph_fastinfo_set); +EXPORT_SYMBOL(hwgraph_connectpt_set); +EXPORT_SYMBOL(hwgraph_connectpt_get); +EXPORT_SYMBOL(hwgraph_edge_get_next); +EXPORT_SYMBOL(hwgraph_info_add_LBL); +EXPORT_SYMBOL(hwgraph_info_remove_LBL); +EXPORT_SYMBOL(hwgraph_info_replace_LBL); +EXPORT_SYMBOL(hwgraph_info_get_LBL); +EXPORT_SYMBOL(hwgraph_info_get_exported_LBL); +EXPORT_SYMBOL(hwgraph_info_get_next_LBL); +EXPORT_SYMBOL(hwgraph_info_export_LBL); +EXPORT_SYMBOL(hwgraph_info_unexport_LBL); +EXPORT_SYMBOL(hwgraph_path_lookup); +EXPORT_SYMBOL(hwgraph_traverse); +EXPORT_SYMBOL(hwgraph_path_to_vertex); +EXPORT_SYMBOL(hwgraph_path_to_dev); +EXPORT_SYMBOL(hwgraph_block_device_get); +EXPORT_SYMBOL(hwgraph_char_device_get); +EXPORT_SYMBOL(hwgraph_cdevsw_get); +EXPORT_SYMBOL(hwgraph_bdevsw_get); +EXPORT_SYMBOL(hwgraph_vertex_name_get); diff -urN linux-2.4.0-test10/arch/ia64/sn/io/hcl_util.c linux-2.4.0-test10-lia/arch/ia64/sn/io/hcl_util.c --- linux-2.4.0-test10/arch/ia64/sn/io/hcl_util.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/hcl_util.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,160 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static devfs_handle_t hwgraph_all_cnodes = GRAPH_VERTEX_NONE; +extern devfs_handle_t hwgraph_root; + + +/* +** Return the "master" for a given vertex. A master vertex is a +** controller or adapter or other piece of hardware that the given +** vertex passes through on the way to the rest of the system. +*/ +devfs_handle_t +device_master_get(devfs_handle_t vhdl) +{ + graph_error_t rc; + devfs_handle_t master; + + rc = hwgraph_edge_get(vhdl, EDGE_LBL_MASTER, &master); + if (rc == GRAPH_SUCCESS) + return(master); + else + return(GRAPH_VERTEX_NONE); +} + +/* +** Set the master for a given vertex. +** Returns 0 on success, non-0 indicates failure +*/ +int +device_master_set(devfs_handle_t vhdl, devfs_handle_t master) +{ + graph_error_t rc; + + rc = hwgraph_edge_add(vhdl, master, EDGE_LBL_MASTER); + return(rc != GRAPH_SUCCESS); +} + + +/* +** Return the compact node id of the node that ultimately "owns" the specified +** vertex. In order to do this, we walk back through masters and connect points +** until we reach a vertex that represents a node. +*/ +cnodeid_t +master_node_get(devfs_handle_t vhdl) +{ + cnodeid_t cnodeid; + devfs_handle_t master; + + for (;;) { + cnodeid = nodevertex_to_cnodeid(vhdl); + if (cnodeid != CNODEID_NONE) + return(cnodeid); + + master = device_master_get(vhdl); + + /* Check for exceptional cases */ + if (master == vhdl) { + /* Since we got a reference to the "master" thru + * device_master_get() we should decrement + * its reference count by 1 + */ + return(CNODEID_NONE); + } + + if (master == GRAPH_VERTEX_NONE) { + master = hwgraph_connectpt_get(vhdl); + if ((master == GRAPH_VERTEX_NONE) || + (master == vhdl)) { + return(CNODEID_NONE); + } + } + + vhdl = master; + } +} + +/* +** If the specified device represents a node, return its +** compact node ID; otherwise, return CNODEID_NONE. +*/ +cnodeid_t +nodevertex_to_cnodeid(devfs_handle_t vhdl) +{ + int rv = 0; + arbitrary_info_t cnodeid = CNODEID_NONE; + + rv = labelcl_info_get_LBL(vhdl, INFO_LBL_CNODEID, NULL, &cnodeid); + + return((cnodeid_t)cnodeid); +} + +void +mark_nodevertex_as_node(devfs_handle_t vhdl, cnodeid_t cnodeid) +{ + if (cnodeid == CNODEID_NONE) + return; + + cnodeid_to_vertex(cnodeid) = vhdl; + labelcl_info_add_LBL(vhdl, INFO_LBL_CNODEID, INFO_DESC_EXPORT, + (arbitrary_info_t)cnodeid); + + { + char cnodeid_buffer[10]; + + if (hwgraph_all_cnodes == GRAPH_VERTEX_NONE) { + (void)hwgraph_path_add( hwgraph_root, + EDGE_LBL_NODENUM, + &hwgraph_all_cnodes); + } + + sprintf(cnodeid_buffer, "%d", cnodeid); + (void)hwgraph_edge_add( hwgraph_all_cnodes, + vhdl, + cnodeid_buffer); + } +} + + +/* +** dev_to_name converts a devfs_handle_t into a canonical name. If the devfs_handle_t +** represents a vertex in the hardware graph, it is converted in the +** normal way for vertices. If the devfs_handle_t is an old devfs_handle_t (one which +** does not represent a hwgraph vertex), we synthesize a name based +** on major/minor number. +** +** Usually returns a pointer to the original buffer, filled in as +** appropriate. If the buffer is too small to hold the entire name, +** or if anything goes wrong while determining the name, dev_to_name +** returns "UnknownDevice". +*/ +char * +dev_to_name(devfs_handle_t dev, char *buf, uint buflen) +{ + return(vertex_to_name(dev, buf, buflen)); +} + + diff -urN linux-2.4.0-test10/arch/ia64/sn/io/hubdev.c linux-2.4.0-test10-lia/arch/ia64/sn/io/hubdev.c --- linux-2.4.0-test10/arch/ia64/sn/io/hubdev.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/hubdev.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,127 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct hubdev_callout { + int (*attach_method)(devfs_handle_t); + struct hubdev_callout *fp; +}; + +typedef struct hubdev_callout hubdev_callout_t; + +mutex_t hubdev_callout_mutex; +hubdev_callout_t *hubdev_callout_list = NULL; + +void +hubdev_init(void) +{ + mutex_init(&hubdev_callout_mutex, MUTEX_DEFAULT, "hubdev"); + hubdev_callout_list = NULL; +} + +void +hubdev_register(int (*attach_method)(devfs_handle_t)) +{ + hubdev_callout_t *callout; + + ASSERT(attach_method); + + callout = (hubdev_callout_t *)kmem_zalloc(sizeof(hubdev_callout_t), KM_SLEEP); + ASSERT(callout); + + mutex_lock(&hubdev_callout_mutex, PZERO); + /* + * Insert at the front of the list + */ + callout->fp = hubdev_callout_list; + hubdev_callout_list = callout; + callout->attach_method = attach_method; + mutex_unlock(&hubdev_callout_mutex); +} + +int +hubdev_unregister(int (*attach_method)(devfs_handle_t)) +{ + hubdev_callout_t **p; + + ASSERT(attach_method); + + mutex_lock(&hubdev_callout_mutex, PZERO); + /* + * Remove registry element containing attach_method + */ + for (p = &hubdev_callout_list; *p != NULL; p = &(*p)->fp) { + if ((*p)->attach_method == attach_method) { + hubdev_callout_t* victim = *p; + *p = (*p)->fp; + kfree(victim); + mutex_unlock(&hubdev_callout_mutex); + return (0); + } + } + mutex_unlock(&hubdev_callout_mutex); + return (ENOENT); +} + + +int +hubdev_docallouts(devfs_handle_t hub) +{ + hubdev_callout_t *p; + int errcode; + + mutex_lock(&hubdev_callout_mutex, PZERO); + + for (p = hubdev_callout_list; p != NULL; p = p->fp) { + ASSERT(p->attach_method); + errcode = (*p->attach_method)(hub); + if (errcode != 0) { + mutex_unlock(&hubdev_callout_mutex); + return (errcode); + } + } + mutex_unlock(&hubdev_callout_mutex); + return (0); +} + +/* + * Given a hub vertex, return the base address of the Hspec space + * for that hub. + */ +caddr_t +hubdev_prombase_get(devfs_handle_t hub) +{ + hubinfo_t hinfo = NULL; + + hubinfo_get(hub, &hinfo); + ASSERT(hinfo); + + return ((caddr_t)NODE_RBOOT_BASE(hinfo->h_nasid)); +} + +cnodeid_t +hubdev_cnodeid_get(devfs_handle_t hub) +{ + hubinfo_t hinfo = NULL; + hubinfo_get(hub, &hinfo); + ASSERT(hinfo); + + return hinfo->h_cnodeid; +} diff -urN linux-2.4.0-test10/arch/ia64/sn/io/hubspc.c linux-2.4.0-test10-lia/arch/ia64/sn/io/hubspc.c --- linux-2.4.0-test10/arch/ia64/sn/io/hubspc.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/hubspc.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,462 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +/* + * hubspc.c - Hub Memory Space Management Driver + * This driver implements the managers for the following + * memory resources: + * 1) reference counters + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#if defined(CONFIG_SGI_IP27) +#include +#include /* Hub Device Registration */ +#elif defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) +#include +#include +#endif + +#include + + +/* Uncomment the following line for tracing */ +/* #define HUBSPC_DEBUG 1 */ + +int hubspc_devflag = D_MP; + +extern void *device_info_get(devfs_handle_t device); +extern void device_info_set(devfs_handle_t device, void *info); + + + +/***********************************************************************/ +/* CPU Prom Space */ +/***********************************************************************/ + +typedef struct cpuprom_info { + devfs_handle_t prom_dev; + devfs_handle_t nodevrtx; + struct cpuprom_info *next; +}cpuprom_info_t; + +static cpuprom_info_t *cpuprom_head; +lock_t cpuprom_spinlock; +#define PROM_LOCK() mutex_spinlock(&cpuprom_spinlock) +#define PROM_UNLOCK(s) mutex_spinunlock(&cpuprom_spinlock, (s)) + +/* + * Add prominfo to the linked list maintained. + */ +void +prominfo_add(devfs_handle_t hub, devfs_handle_t prom) +{ + cpuprom_info_t *info; + int s; + + info = kmalloc(sizeof(cpuprom_info_t), GFP_KERNEL); + ASSERT(info); + info->prom_dev = prom; + info->nodevrtx = hub; + + + s = PROM_LOCK(); + info->next = cpuprom_head; + cpuprom_head = info; + PROM_UNLOCK(s); +} + +void +prominfo_del(devfs_handle_t prom) +{ + int s; + cpuprom_info_t *info; + cpuprom_info_t **prev; + + s = PROM_LOCK(); + prev = &cpuprom_head; + while ( (info = *prev) ) { + if (info->prom_dev == prom) { + *prev = info->next; + PROM_UNLOCK(s); + return; + } + + prev = &info->next; + } + PROM_UNLOCK(s); + ASSERT(0); +} + +devfs_handle_t +prominfo_nodeget(devfs_handle_t prom) +{ + int s; + cpuprom_info_t *info; + + s = PROM_LOCK(); + info = cpuprom_head; + while (info) { + if(info->prom_dev == prom) { + PROM_UNLOCK(s); + return info->nodevrtx; + } + info = info->next; + } + PROM_UNLOCK(s); + return 0; +} + +#if defined(CONFIG_SGI_IP27) +#define SN_PROMVERSION INV_IP27PROM +#elif defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) +#define SN_PROMVERSION INV_IP35PROM +#endif + +/* Add "detailed" labelled inventory information to the + * prom vertex + */ +void +cpuprom_detailed_inventory_info_add(devfs_handle_t prom_dev,devfs_handle_t node) +{ + invent_miscinfo_t *cpuprom_inventory_info; + extern invent_generic_t *klhwg_invent_alloc(cnodeid_t cnode, + int class, int size); + cnodeid_t cnode = hubdev_cnodeid_get(node); + + /* Allocate memory for the extra inventory information + * for the prom + */ + cpuprom_inventory_info = (invent_miscinfo_t *) + klhwg_invent_alloc(cnode, INV_PROM, sizeof(invent_miscinfo_t)); + + ASSERT(cpuprom_inventory_info); + + /* Set the enabled flag so that the hinv interprets this + * information + */ + cpuprom_inventory_info->im_gen.ig_flag = INVENT_ENABLED; + cpuprom_inventory_info->im_type = SN_PROMVERSION; + /* Store prom revision into inventory information */ + cpuprom_inventory_info->im_rev = IP27CONFIG.pvers_rev; + cpuprom_inventory_info->im_version = IP27CONFIG.pvers_vers; + + + /* Store this info as labelled information hanging off the + * prom device vertex + */ + hwgraph_info_add_LBL(prom_dev, INFO_LBL_DETAIL_INVENT, + (arbitrary_info_t) cpuprom_inventory_info); + /* Export this information so that user programs can get to + * this by using attr_get() + */ + hwgraph_info_export_LBL(prom_dev, INFO_LBL_DETAIL_INVENT, + sizeof(invent_miscinfo_t)); +} + +int +cpuprom_attach(devfs_handle_t node) +{ + devfs_handle_t prom_dev; + + hwgraph_char_device_add(node, EDGE_LBL_PROM, "hubspc_", &prom_dev); +#ifdef HUBSPC_DEBUG + printf("hubspc: prom_attach hub: 0x%x prom: 0x%x\n", node, prom_dev); +#endif /* HUBSPC_DEBUG */ + device_inventory_add(prom_dev, INV_PROM, SN_PROMVERSION, + (major_t)0, (minor_t)0, 0); + + /* Add additional inventory info about the cpu prom like + * revision & version numbers etc. + */ + cpuprom_detailed_inventory_info_add(prom_dev,node); + device_info_set(prom_dev, (void*)(ulong)HUBSPC_PROM); + prominfo_add(node, prom_dev); + + return (0); +} + +#if defined(CONFIG_SGI_IP27) +#define FPROM_CONFIG_ADDR MD_MEMORY_CONFIG +#define FPROM_ENABLE_MASK MMC_FPROM_WR_MASK +#define FPROM_ENABLE_SHFT MMC_FPROM_WR_SHFT +#define CONFIG_FPROM_ENABLE CONFIG_SN0_FPROM_WR +#define FPROM_SETUP_MASK MMC_FPROM_CYC_MASK +#define FPROM_SETUP_SHFT MMC_FPROM_CYC_SHFT +#define CONFIG_FPROM_SETUP CONFIG_SN0_FPROM_CYC +#elif defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) +#define FPROM_CONFIG_ADDR MD_JUNK_BUS_TIMING +#define FPROM_ENABLE_MASK MJT_FPROM_ENABLE_MASK +#define FPROM_ENABLE_SHFT MJT_FPROM_ENABLE_SHFT +#define FPROM_SETUP_MASK MJT_FPROM_SETUP_MASK +#define FPROM_SETUP_SHFT MJT_FPROM_SETUP_SHFT +#endif + +/*ARGSUSED*/ +int +cpuprom_map(devfs_handle_t dev, vhandl_t *vt, off_t addr, size_t len) +{ + int errcode; + caddr_t kvaddr; + devfs_handle_t node; + cnodeid_t cnode; + + node = prominfo_nodeget(dev); + + if (!node) + return EIO; + + + kvaddr = hubdev_prombase_get(node); + cnode = hubdev_cnodeid_get(node); +#ifdef HUBSPC_DEBUG + printf("cpuprom_map: hubnode %d kvaddr 0x%x\n", node, kvaddr); +#endif + + if (len > RBOOT_SIZE) + len = RBOOT_SIZE; + /* + * Map in the prom space + */ + errcode = v_mapphys(vt, kvaddr, len); + + if (errcode == 0 ){ + /* + * Set the MD configuration registers suitably. + */ + nasid_t nasid; + uint64_t value; + volatile hubreg_t *regaddr; + + nasid = COMPACT_TO_NASID_NODEID(cnode); + regaddr = REMOTE_HUB_ADDR(nasid, FPROM_CONFIG_ADDR); + value = HUB_L(regaddr); + value &= ~(FPROM_SETUP_MASK | FPROM_ENABLE_MASK); + +#ifdef IRIX +#ifdef CONFIG_SGI_IP27 + if (private.p_sn00) { + value |= (((long)CONFIG_SN00_FPROM_CYC << FPROM_SETUP_SHFT) | + ((long)CONFIG_SN00_FPROM_WR << FPROM_ENABLE_SHFT)); + } else +#endif /* CONFIG_SGI_IP27 */ +#endif + { + value |= (((long)CONFIG_FPROM_SETUP << FPROM_SETUP_SHFT) | + ((long)CONFIG_FPROM_ENABLE << FPROM_ENABLE_SHFT)); + } + HUB_S(regaddr, value); + + } + return (errcode); +} + +/*ARGSUSED*/ +int +cpuprom_unmap(devfs_handle_t dev, vhandl_t *vt) +{ + return 0; +} + +/***********************************************************************/ +/* Base Hub Space Driver */ +/***********************************************************************/ + +extern int l1_attach( devfs_handle_t ); + +/* + * hubspc_init + * Registration of the hubspc devices with the hub manager + */ +void +hubspc_init(void) +{ + /* + * Register with the hub manager + */ + + /* The reference counters */ + hubdev_register(mem_refcnt_attach); + + /* Prom space */ + hubdev_register(cpuprom_attach); + +#if !defined(CONFIG_SGI_IP27) && !defined(DIRECT_L1_CONSOLE) + /* L1 system controller link */ + hubdev_register(l1_attach); +#endif + +#ifdef HUBSPC_DEBUG + printf("hubspc_init: Completed\n"); +#endif /* HUBSPC_DEBUG */ + /* Initialize spinlocks */ + spinlock_init(&cpuprom_spinlock, "promlist"); +} + +/* ARGSUSED */ +int +hubspc_open(devfs_handle_t *devp, mode_t oflag, int otyp, cred_t *crp) +{ + int errcode = 0; + + switch ((hubspc_subdevice_t)(ulong)device_info_get(*devp)) { + case HUBSPC_REFCOUNTERS: + errcode = mem_refcnt_open(devp, oflag, otyp, crp); + break; + + case HUBSPC_PROM: + /* Check if the user has proper access rights to + * read/write the prom space. + */ + if (!cap_able(CAP_DEVICE_MGT)) { + errcode = EPERM; + } + break; + + default: + errcode = ENODEV; + } + +#ifdef HUBSPC_DEBUG + printf("hubspc_open: Completed open for type %d\n", + (hubspc_subdevice_t)(ulong)device_info_get(*devp)); +#endif /* HUBSPC_DEBUG */ + + return (errcode); +} + + +/* ARGSUSED */ +int +hubspc_close(devfs_handle_t dev, int oflag, int otyp, cred_t *crp) +{ + int errcode = 0; + + switch ((hubspc_subdevice_t)(ulong)device_info_get(dev)) { + case HUBSPC_REFCOUNTERS: + errcode = mem_refcnt_close(dev, oflag, otyp, crp); + break; + + case HUBSPC_PROM: + break; + default: + errcode = ENODEV; + } + +#ifdef HUBSPC_DEBUG + printf("hubspc_close: Completed close for type %d\n", + (hubspc_subdevice_t)(ulong)device_info_get(dev)); +#endif /* HUBSPC_DEBUG */ + + return (errcode); +} + +/* ARGSUSED */ +int +hubspc_map(devfs_handle_t dev, vhandl_t *vt, off_t off, size_t len, uint prot) +{ + /*REFERENCED*/ + hubspc_subdevice_t subdevice; + int errcode = 0; + + /* check validity of request */ + if( len == 0 ) { + return ENXIO; + } + + subdevice = (hubspc_subdevice_t)(ulong)device_info_get(dev); + +#ifdef HUBSPC_DEBUG + printf("hubspc_map: subdevice: %d vaddr: 0x%x phyaddr: 0x%x len: 0x%x\n", + subdevice, v_getaddr(vt), off, len); +#endif /* HUBSPC_DEBUG */ + + switch ((hubspc_subdevice_t)(ulong)device_info_get(dev)) { + case HUBSPC_REFCOUNTERS: + errcode = mem_refcnt_mmap(dev, vt, off, len, prot); + break; + + case HUBSPC_PROM: + errcode = cpuprom_map(dev, vt, off, len); + break; + default: + errcode = ENODEV; + } + +#ifdef HUBSPC_DEBUG + printf("hubspc_map finished: spctype: %d vaddr: 0x%x len: 0x%x\n", + (hubspc_subdevice_t)(ulong)device_info_get(dev), v_getaddr(vt), len); +#endif /* HUBSPC_DEBUG */ + + return errcode; +} + +/* ARGSUSED */ +int +hubspc_unmap(devfs_handle_t dev, vhandl_t *vt) +{ + int errcode = 0; + + switch ((hubspc_subdevice_t)(ulong)device_info_get(dev)) { + case HUBSPC_REFCOUNTERS: + errcode = mem_refcnt_unmap(dev, vt); + break; + + case HUBSPC_PROM: + errcode = cpuprom_unmap(dev, vt); + break; + + default: + errcode = ENODEV; + } + return errcode; + +} + +/* ARGSUSED */ +int +hubspc_ioctl(devfs_handle_t dev, + int cmd, + void *arg, + int mode, + cred_t *cred_p, + int *rvalp) +{ + int errcode = 0; + + switch ((hubspc_subdevice_t)(ulong)device_info_get(dev)) { + case HUBSPC_REFCOUNTERS: + errcode = mem_refcnt_ioctl(dev, cmd, arg, mode, cred_p, rvalp); + break; + + case HUBSPC_PROM: + break; + + default: + errcode = ENODEV; + } + return errcode; + +} diff -urN linux-2.4.0-test10/arch/ia64/sn/io/invent.c linux-2.4.0-test10-lia/arch/ia64/sn/io/invent.c --- linux-2.4.0-test10/arch/ia64/sn/io/invent.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/invent.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,198 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +/* + * Hardware Inventory + * + * See sys/sn/invent.h for an explanation of the hardware inventory contents. + * + */ +#include +#include +#include +#include +#include +#include + +void +inventinit(void) +{ +} + +/* + * For initializing/updating an inventory entry. + */ +void +replace_in_inventory( + inventory_t *pinv, int class, int type, + int controller, int unit, int state) +{ + pinv->inv_class = class; + pinv->inv_type = type; + pinv->inv_controller = controller; + pinv->inv_unit = unit; + pinv->inv_state = state; +} + +/* + * Inventory addition + * + * XXX NOTE: Currently must be called after dynamic memory allocator is + * initialized. + * + */ +void +add_to_inventory(int class, int type, int controller, int unit, int state) +{ + (void)device_inventory_add((devfs_handle_t)GRAPH_VERTEX_NONE, class, type, + controller, unit, state); +} + + +/* + * Inventory retrieval + * + * These two routines are intended to prevent the caller from having to know + * the internal structure of the inventory table. + * + */ +inventory_t * +get_next_inventory(invplace_t *place) +{ + inventory_t *pinv; + devfs_handle_t device = place->invplace_vhdl; + int rv; + + while ((pinv = device_inventory_get_next(device, place)) == NULL) { + /* + * We've exhausted inventory items on the last device. + * Advance to next device. + */ + rv = hwgraph_vertex_get_next(&device, &place->invplace_vplace); + if (rv != LABELCL_SUCCESS) + return(NULL); + place->invplace_vhdl = device; + place->invplace_inv = NULL; /* Start from beginning invent on this device */ + } + + return(pinv); +} + +/* ARGSUSED */ +int +get_sizeof_inventory(int abi) +{ + return sizeof(inventory_t); +} + +/* + * Hardware inventory scanner. + * + * Calls fun() for every entry in inventory list unless fun() returns something + * other than 0. + */ +int +scaninvent(int (*fun)(inventory_t *, void *), void *arg) +{ + inventory_t *ie; + invplace_t iplace = { NULL,NULL, NULL }; + int rc; + + ie = 0; + rc = 0; + while ( (ie = (inventory_t *)get_next_inventory(&iplace)) ) { + rc = (*fun)(ie, arg); + if (rc) + break; + } + return rc; +} + +/* + * Find a particular inventory object + * + * pinv can be a pointer to an inventory entry and the search will begin from + * there, or it can be 0 in which case the search starts at the beginning. + * A -1 for any of the other arguments is a wildcard (i.e. it always matches). + */ +inventory_t * +find_inventory(inventory_t *pinv, int class, int type, int controller, + int unit, int state) +{ + invplace_t iplace = { NULL,NULL, NULL }; + + while ((pinv = (inventory_t *)get_next_inventory(&iplace)) != NULL) { + if (class != -1 && pinv->inv_class != class) + continue; + if (type != -1 && pinv->inv_type != type) + continue; + + /* XXXX - perhaps the "state" entry should be ignored so an + * an existing entry can be updated. See vino_init() and + * ml/IP22.c:add_ioboard() for an example. + */ + if (state != -1 && pinv->inv_state != state) + continue; + if (controller != -1 + && pinv->inv_controller != controller) + continue; + if (unit != -1 && pinv->inv_unit != unit) + continue; + break; + } + + return(pinv); +} + + +/* +** Retrieve inventory data associated with a device. +*/ +inventory_t * +device_inventory_get_next( devfs_handle_t device, + invplace_t *invplace) +{ + inventory_t *pinv; + int rv; + + rv = hwgraph_inventory_get_next(device, invplace, &pinv); + if (rv == LABELCL_SUCCESS) + return(pinv); + else + return(NULL); +} + + +/* +** Associate canonical inventory information with a device (and +** add it to the general inventory). +*/ +void +device_inventory_add( devfs_handle_t device, + int class, + int type, + major_t controller, + minor_t unit, + int state) +{ + hwgraph_inventory_add(device, class, type, controller, unit, state); +} + +int +device_controller_num_get(devfs_handle_t device) +{ + return (hwgraph_controller_num_get(device)); +} + +void +device_controller_num_set(devfs_handle_t device, int contr_num) +{ + hwgraph_controller_num_set(device, contr_num); +} diff -urN linux-2.4.0-test10/arch/ia64/sn/io/io.c linux-2.4.0-test10-lia/arch/ia64/sn/io/io.c --- linux-2.4.0-test10/arch/ia64/sn/io/io.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/io.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,1319 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern xtalk_provider_t hub_provider; + +#ifndef CONFIG_IA64_SGI_IO +/* Global variables */ +extern pdaindr_t pdaindr[MAXCPUS]; +#endif + +/* + * Perform any initializations needed to support hub-based I/O. + * Called once during startup. + */ +void +hubio_init(void) +{ +#if (defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)) && !defined(DIRECT_L1_CONSOLE) + extern void early_brl1_port_init( void ); + early_brl1_port_init(); +#endif +} + +/* + * Implementation of hub iobus operations. + * + * Hub provides a crosstalk "iobus" on IP27 systems. These routines + * provide a platform-specific implementation of xtalk used by all xtalk + * cards on IP27 systems. + * + * Called from corresponding xtalk_* routines. + */ + + +/* PIO MANAGEMENT */ +/* For mapping system virtual address space to xtalk space on a specified widget */ + +/* + * Setup pio structures needed for a particular hub. + */ +static void +hub_pio_init(devfs_handle_t hubv) +{ + xwidgetnum_t widget; + hubinfo_t hubinfo; + nasid_t nasid; + int bigwin; + hub_piomap_t hub_piomap; + + hubinfo_get(hubv, &hubinfo); + nasid = hubinfo->h_nasid; + + /* Initialize small window piomaps for this hub */ + for (widget=0; widget <= HUB_WIDGET_ID_MAX; widget++) { + hub_piomap = hubinfo_swin_piomap_get(hubinfo, (int)widget); + hub_piomap->hpio_xtalk_info.xp_target = widget; + hub_piomap->hpio_xtalk_info.xp_xtalk_addr = 0; + hub_piomap->hpio_xtalk_info.xp_mapsz = SWIN_SIZE; + hub_piomap->hpio_xtalk_info.xp_kvaddr = (caddr_t)NODE_SWIN_BASE(nasid, widget); + hub_piomap->hpio_hub = hubv; + hub_piomap->hpio_flags = HUB_PIOMAP_IS_VALID; + } + + /* Initialize big window piomaps for this hub */ + for (bigwin=0; bigwin < HUB_NUM_BIG_WINDOW; bigwin++) { + hub_piomap = hubinfo_bwin_piomap_get(hubinfo, bigwin); + hub_piomap->hpio_xtalk_info.xp_mapsz = BWIN_SIZE; + hub_piomap->hpio_hub = hubv; + hub_piomap->hpio_holdcnt = 0; + hub_piomap->hpio_flags = HUB_PIOMAP_IS_BIGWINDOW; + IIO_ITTE_DISABLE(nasid, bigwin); + } +#ifdef BRINGUP + hub_set_piomode(nasid, HUB_PIO_CONVEYOR); +#else + /* Set all the xwidgets in fire-and-forget mode + * by default + */ + hub_set_piomode(nasid, HUB_PIO_FIRE_N_FORGET); +#endif /* BRINGUP */ + + sv_init(&hubinfo->h_bwwait, SV_FIFO, "bigwin"); + spinlock_init(&hubinfo->h_bwlock, "bigwin"); +} + +/* + * Create a caddr_t-to-xtalk_addr mapping. + * + * Use a small window if possible (that's the usual case), but + * manage big windows if needed. Big window mappings can be + * either FIXED or UNFIXED -- we keep at least 1 big window available + * for UNFIXED mappings. + * + * Returns an opaque pointer-sized type which can be passed to + * other hub_pio_* routines on success, or NULL if the request + * cannot be satisfied. + */ +/* ARGSUSED */ +hub_piomap_t +hub_piomap_alloc(devfs_handle_t dev, /* set up mapping for this device */ + device_desc_t dev_desc, /* device descriptor */ + iopaddr_t xtalk_addr, /* map for this xtalk_addr range */ + size_t byte_count, + size_t byte_count_max, /* maximum size of a mapping */ + unsigned flags) /* defined in sys/pio.h */ +{ + xwidget_info_t widget_info = xwidget_info_get(dev); + xwidgetnum_t widget = xwidget_info_id_get(widget_info); + devfs_handle_t hubv = xwidget_info_master_get(widget_info); + hubinfo_t hubinfo; + hub_piomap_t bw_piomap; + int bigwin, free_bw_index; + nasid_t nasid; + volatile hubreg_t junk; + int s; + + /* sanity check */ + if (byte_count_max > byte_count) + return(NULL); + + hubinfo_get(hubv, &hubinfo); + + /* If xtalk_addr range is mapped by a small window, we don't have + * to do much + */ + if (xtalk_addr + byte_count <= SWIN_SIZE) + return(hubinfo_swin_piomap_get(hubinfo, (int)widget)); + + /* We need to use a big window mapping. */ + + /* + * TBD: Allow requests that would consume multiple big windows -- + * split the request up and use multiple mapping entries. + * For now, reject requests that span big windows. + */ + if ((xtalk_addr % BWIN_SIZE) + byte_count > BWIN_SIZE) + return(NULL); + + + /* Round xtalk address down for big window alignement */ + xtalk_addr = xtalk_addr & ~(BWIN_SIZE-1); + + /* + * Check to see if an existing big window mapping will suffice. + */ +tryagain: + free_bw_index = -1; + s = mutex_spinlock(&hubinfo->h_bwlock); + for (bigwin=0; bigwin < HUB_NUM_BIG_WINDOW; bigwin++) { + bw_piomap = hubinfo_bwin_piomap_get(hubinfo, bigwin); + + /* If mapping is not valid, skip it */ + if (!(bw_piomap->hpio_flags & HUB_PIOMAP_IS_VALID)) { + free_bw_index = bigwin; + continue; + } + + /* + * If mapping is UNFIXED, skip it. We don't allow sharing + * of UNFIXED mappings, because this would allow starvation. + */ + if (!(bw_piomap->hpio_flags & HUB_PIOMAP_IS_FIXED)) + continue; + + if ( xtalk_addr == bw_piomap->hpio_xtalk_info.xp_xtalk_addr && + widget == bw_piomap->hpio_xtalk_info.xp_target) { + bw_piomap->hpio_holdcnt++; + mutex_spinunlock(&hubinfo->h_bwlock, s); + return(bw_piomap); + } + } + + /* + * None of the existing big window mappings will work for us -- + * we need to establish a new mapping. + */ + + /* Insure that we don't consume all big windows with FIXED mappings */ + if (flags & PIOMAP_FIXED) { + if (hubinfo->h_num_big_window_fixed < HUB_NUM_BIG_WINDOW-1) { + ASSERT(free_bw_index >= 0); + hubinfo->h_num_big_window_fixed++; + } else { + bw_piomap = NULL; + goto done; + } + } else /* PIOMAP_UNFIXED */ { + if (free_bw_index < 0) { + if (flags & PIOMAP_NOSLEEP) { + bw_piomap = NULL; + goto done; + } + + sv_wait(&hubinfo->h_bwwait, PZERO, &hubinfo->h_bwlock, s); + goto tryagain; + } + } + + + /* OK! Allocate big window free_bw_index for this mapping. */ + /* + * The code below does a PIO write to setup an ITTE entry. + * We need to prevent other CPUs from seeing our updated memory + * shadow of the ITTE (in the piomap) until the ITTE entry is + * actually set up; otherwise, another CPU might attempt a PIO + * prematurely. + * + * Also, the only way we can know that an entry has been received + * by the hub and can be used by future PIO reads/writes is by + * reading back the ITTE entry after writing it. + * + * For these two reasons, we PIO read back the ITTE entry after + * we write it. + */ + + nasid = hubinfo->h_nasid; + IIO_ITTE_PUT(nasid, free_bw_index, HUB_PIO_MAP_TO_MEM, widget, xtalk_addr); + junk = HUB_L(IIO_ITTE_GET(nasid, free_bw_index)); + + bw_piomap = hubinfo_bwin_piomap_get(hubinfo, free_bw_index); + bw_piomap->hpio_xtalk_info.xp_dev = dev; + bw_piomap->hpio_xtalk_info.xp_target = widget; + bw_piomap->hpio_xtalk_info.xp_xtalk_addr = xtalk_addr; + bw_piomap->hpio_xtalk_info.xp_kvaddr = (caddr_t)NODE_BWIN_BASE(nasid, free_bw_index); + bw_piomap->hpio_holdcnt++; + bw_piomap->hpio_bigwin_num = free_bw_index; + + if (flags & PIOMAP_FIXED) + bw_piomap->hpio_flags |= HUB_PIOMAP_IS_VALID | HUB_PIOMAP_IS_FIXED; + else + bw_piomap->hpio_flags |= HUB_PIOMAP_IS_VALID; + +done: + mutex_spinunlock(&hubinfo->h_bwlock, s); + return(bw_piomap); +} + +/* + * hub_piomap_free destroys a caddr_t-to-xtalk pio mapping and frees + * any associated mapping resources. + * + * If this * piomap was handled with a small window, or if it was handled + * in a big window that's still in use by someone else, then there's + * nothing to do. On the other hand, if this mapping was handled + * with a big window, AND if we were the final user of that mapping, + * then destroy the mapping. + */ +void +hub_piomap_free(hub_piomap_t hub_piomap) +{ + devfs_handle_t hubv; + hubinfo_t hubinfo; + nasid_t nasid; + int s; + + /* + * Small windows are permanently mapped to corresponding widgets, + * so there're no resources to free. + */ + if (!(hub_piomap->hpio_flags & HUB_PIOMAP_IS_BIGWINDOW)) + return; + + ASSERT(hub_piomap->hpio_flags & HUB_PIOMAP_IS_VALID); + ASSERT(hub_piomap->hpio_holdcnt > 0); + + hubv = hub_piomap->hpio_hub; + hubinfo_get(hubv, &hubinfo); + nasid = hubinfo->h_nasid; + + s = mutex_spinlock(&hubinfo->h_bwlock); + + /* + * If this is the last hold on this mapping, free it. + */ + if (--hub_piomap->hpio_holdcnt == 0) { + IIO_ITTE_DISABLE(nasid, hub_piomap->hpio_bigwin_num ); + + if (hub_piomap->hpio_flags & HUB_PIOMAP_IS_FIXED) { + hub_piomap->hpio_flags &= ~(HUB_PIOMAP_IS_VALID | HUB_PIOMAP_IS_FIXED); + hubinfo->h_num_big_window_fixed--; + ASSERT(hubinfo->h_num_big_window_fixed >= 0); + } else + hub_piomap->hpio_flags &= ~HUB_PIOMAP_IS_VALID; + + (void)sv_signal(&hubinfo->h_bwwait); + } + + mutex_spinunlock(&hubinfo->h_bwlock, s); +} + +/* + * Establish a mapping to a given xtalk address range using the resources + * allocated earlier. + */ +caddr_t +hub_piomap_addr(hub_piomap_t hub_piomap, /* mapping resources */ + iopaddr_t xtalk_addr, /* map for this xtalk address */ + size_t byte_count) /* map this many bytes */ +{ + /* Verify that range can be mapped using the specified piomap */ + if (xtalk_addr < hub_piomap->hpio_xtalk_info.xp_xtalk_addr) + return(0); + + if (xtalk_addr + byte_count > + ( hub_piomap->hpio_xtalk_info.xp_xtalk_addr + + hub_piomap->hpio_xtalk_info.xp_mapsz)) + return(0); + + if (hub_piomap->hpio_flags & HUB_PIOMAP_IS_VALID) + return(hub_piomap->hpio_xtalk_info.xp_kvaddr + + (xtalk_addr % hub_piomap->hpio_xtalk_info.xp_mapsz)); + else + return(0); +} + + +/* + * Driver indicates that it's done with PIO's from an earlier piomap_addr. + */ +/* ARGSUSED */ +void +hub_piomap_done(hub_piomap_t hub_piomap) /* done with these mapping resources */ +{ + /* Nothing to do */ +} + + +/* + * For translations that require no mapping resources, supply a kernel virtual + * address that maps to the specified xtalk address range. + */ +/* ARGSUSED */ +caddr_t +hub_piotrans_addr( devfs_handle_t dev, /* translate to this device */ + device_desc_t dev_desc, /* device descriptor */ + iopaddr_t xtalk_addr, /* Crosstalk address */ + size_t byte_count, /* map this many bytes */ + unsigned flags) /* (currently unused) */ +{ + xwidget_info_t widget_info = xwidget_info_get(dev); + xwidgetnum_t widget = xwidget_info_id_get(widget_info); + devfs_handle_t hubv = xwidget_info_master_get(widget_info); + hub_piomap_t hub_piomap; + hubinfo_t hubinfo; + + hubinfo_get(hubv, &hubinfo); + + if (xtalk_addr + byte_count <= SWIN_SIZE) { + hub_piomap = hubinfo_swin_piomap_get(hubinfo, (int)widget); + return(hub_piomap_addr(hub_piomap, xtalk_addr, byte_count)); + } else + return(0); +} + + +/* DMA MANAGEMENT */ +/* Mapping from crosstalk space to system physical space */ + +/* + * There's not really very much to do here, since crosstalk maps + * directly to system physical space. It's quite possible that this + * DMA layer will be bypassed in performance kernels. + */ + + +/* ARGSUSED */ +static void +hub_dma_init(devfs_handle_t hubv) +{ +} + + +/* + * Allocate resources needed to set up DMA mappings up to a specified size + * on a specified adapter. + * + * We don't actually use the adapter ID for anything. It's just the adapter + * that the lower level driver plans to use for DMA. + */ +/* ARGSUSED */ +hub_dmamap_t +hub_dmamap_alloc( devfs_handle_t dev, /* set up mappings for this device */ + device_desc_t dev_desc, /* device descriptor */ + size_t byte_count_max, /* max size of a mapping */ + unsigned flags) /* defined in dma.h */ +{ + hub_dmamap_t dmamap; + xwidget_info_t widget_info = xwidget_info_get(dev); + xwidgetnum_t widget = xwidget_info_id_get(widget_info); + devfs_handle_t hubv = xwidget_info_master_get(widget_info); + + dmamap = kern_malloc(sizeof(struct hub_dmamap_s)); + dmamap->hdma_xtalk_info.xd_dev = dev; + dmamap->hdma_xtalk_info.xd_target = widget; + dmamap->hdma_hub = hubv; + dmamap->hdma_flags = HUB_DMAMAP_IS_VALID; + if (flags & XTALK_FIXED) + dmamap->hdma_flags |= HUB_DMAMAP_IS_FIXED; + + return(dmamap); +} + +/* + * Destroy a DMA mapping from crosstalk space to system address space. + * There is no actual mapping hardware to destroy, but we at least mark + * the dmamap INVALID and free the space that it took. + */ +void +hub_dmamap_free(hub_dmamap_t hub_dmamap) +{ + hub_dmamap->hdma_flags &= ~HUB_DMAMAP_IS_VALID; + kern_free(hub_dmamap); +} + +/* + * Establish a DMA mapping using the resources allocated in a previous dmamap_alloc. + * Return an appropriate crosstalk address range that maps to the specified physical + * address range. + */ +/* ARGSUSED */ +extern iopaddr_t +hub_dmamap_addr( hub_dmamap_t dmamap, /* use these mapping resources */ + paddr_t paddr, /* map for this address */ + size_t byte_count) /* map this many bytes */ +{ + devfs_handle_t vhdl; + + ASSERT(dmamap->hdma_flags & HUB_DMAMAP_IS_VALID); + + if (dmamap->hdma_flags & HUB_DMAMAP_USED) { + /* If the map is FIXED, re-use is OK. */ + if (!(dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) { + vhdl = dmamap->hdma_xtalk_info.xd_dev; +#if defined(SUPPORT_PRINTING_V_FORMAT) + cmn_err(CE_WARN, "%v: hub_dmamap_addr re-uses dmamap.\n",vhdl); +#else + cmn_err(CE_WARN, "0x%p: hub_dmamap_addr re-uses dmamap.\n", &vhdl); +#endif + } + } else { + dmamap->hdma_flags |= HUB_DMAMAP_USED; + } + + /* There isn't actually any DMA mapping hardware on the hub. */ + return(paddr); +} + +/* + * Establish a DMA mapping using the resources allocated in a previous dmamap_alloc. + * Return an appropriate crosstalk address list that maps to the specified physical + * address list. + */ +/* ARGSUSED */ +alenlist_t +hub_dmamap_list(hub_dmamap_t hub_dmamap, /* use these mapping resources */ + alenlist_t palenlist, /* map this area of memory */ + unsigned flags) +{ + devfs_handle_t vhdl; + + ASSERT(hub_dmamap->hdma_flags & HUB_DMAMAP_IS_VALID); + + if (hub_dmamap->hdma_flags & HUB_DMAMAP_USED) { + /* If the map is FIXED, re-use is OK. */ + if (!(hub_dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) { + vhdl = hub_dmamap->hdma_xtalk_info.xd_dev; +#if defined(SUPPORT_PRINTING_V_FORMAT) + cmn_err(CE_WARN,"%v: hub_dmamap_list re-uses dmamap\n",vhdl); +#else + cmn_err(CE_WARN,"0x%p: hub_dmamap_list re-uses dmamap\n", &vhdl); +#endif + } + } else { + hub_dmamap->hdma_flags |= HUB_DMAMAP_USED; + } + + /* There isn't actually any DMA mapping hardware on the hub. */ + return(palenlist); +} + +/* + * Driver indicates that it has completed whatever DMA it may have started + * after an earlier dmamap_addr or dmamap_list call. + */ +void +hub_dmamap_done(hub_dmamap_t hub_dmamap) /* done with these mapping resources */ +{ + devfs_handle_t vhdl; + + if (hub_dmamap->hdma_flags & HUB_DMAMAP_USED) { + hub_dmamap->hdma_flags &= ~HUB_DMAMAP_USED; + } else { + /* If the map is FIXED, re-done is OK. */ + if (!(hub_dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) { + vhdl = hub_dmamap->hdma_xtalk_info.xd_dev; +#if defined(SUPPORT_PRINTING_V_FORMAT) + cmn_err(CE_WARN, "%v: hub_dmamap_done already done with dmamap\n",vhdl); +#else + cmn_err(CE_WARN, "0x%p: hub_dmamap_done already done with dmamap\n", &vhdl); +#endif + } + } +} + +/* + * Translate a single system physical address into a crosstalk address. + */ +/* ARGSUSED */ +iopaddr_t +hub_dmatrans_addr( devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + paddr_t paddr, /* system physical address */ + size_t byte_count, /* length */ + unsigned flags) /* defined in dma.h */ +{ + /* no translation needed */ + return(paddr); +} + +/* + * Translate a list of IP27 addresses and lengths into a list of crosstalk + * addresses and lengths. No actual hardware mapping takes place; the hub + * has no DMA mapping registers -- crosstalk addresses map directly. + */ +/* ARGSUSED */ +alenlist_t +hub_dmatrans_list( devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + alenlist_t palenlist, /* system address/length list */ + unsigned flags) /* defined in dma.h */ +{ + /* no translation needed */ + return(palenlist); +} + +/*ARGSUSED*/ +void +hub_dmamap_drain( hub_dmamap_t map) +{ + /* XXX- flush caches, if cache coherency WAR is needed */ +} + +/*ARGSUSED*/ +void +hub_dmaaddr_drain( devfs_handle_t vhdl, + paddr_t addr, + size_t bytes) +{ + /* XXX- flush caches, if cache coherency WAR is needed */ +} + +/*ARGSUSED*/ +void +hub_dmalist_drain( devfs_handle_t vhdl, + alenlist_t list) +{ + /* XXX- flush caches, if cache coherency WAR is needed */ +} + + + +/* INTERRUPT MANAGEMENT */ + +/* ARGSUSED */ +static void +hub_intr_init(devfs_handle_t hubv) +{ +} + +/* + * hub_device_desc_update + * Update the passed in device descriptor with the actual the + * target cpu number and interrupt priority level. + * NOTE : These might be the same as the ones passed in thru + * the descriptor. + */ +static void +hub_device_desc_update(device_desc_t dev_desc, + ilvl_t intr_swlevel, + cpuid_t cpu) +{ + char cpuname[40]; + + /* Store the interrupt priority level in the device descriptor */ + device_desc_intr_swlevel_set(dev_desc, intr_swlevel); + + /* Convert the cpuid to the vertex handle in the hwgraph and + * save it in the device descriptor. + */ + sprintf(cpuname,"/hw/cpunum/%ld",cpu); + device_desc_intr_target_set(dev_desc, + hwgraph_path_to_dev(cpuname)); +} + +int allocate_my_bit = INTRCONNECT_ANYBIT; + +/* + * Allocate resources required for an interrupt as specified in dev_desc. + * Returns a hub interrupt handle on success, or 0 on failure. + */ +hub_intr_t +hub_intr_alloc( devfs_handle_t dev, /* which crosstalk device */ + device_desc_t dev_desc, /* device descriptor */ + devfs_handle_t owner_dev) /* owner of this interrupt, if known */ +{ + cpuid_t cpu; /* cpu to receive interrupt */ + int cpupicked = 0; + int bit; /* interrupt vector */ + /*REFERENCED*/ + int intr_resflags; + hub_intr_t intr_hdl; + cnodeid_t nodeid; /* node to receive interrupt */ + /*REFERENCED*/ + nasid_t nasid; /* nasid to receive interrupt */ + struct xtalk_intr_s *xtalk_info; + iopaddr_t xtalk_addr; /* xtalk addr on hub to set intr */ + xwidget_info_t xwidget_info; /* standard crosstalk widget info handle */ + char *intr_name = NULL; + ilvl_t intr_swlevel; + extern int default_intr_pri; +#ifdef CONFIG_IA64_SGI_SN1 + extern void synergy_intr_alloc(int, int); +#endif + + /* + * If caller didn't explicily specify a device descriptor, see if there's + * a default descriptor associated with the device. + */ + if (!dev_desc) + dev_desc = device_desc_default_get(dev); + + if (dev_desc) { + intr_name = device_desc_intr_name_get(dev_desc); + intr_swlevel = device_desc_intr_swlevel_get(dev_desc); + if (dev_desc->flags & D_INTR_ISERR) { + intr_resflags = II_ERRORINT; + } else if (!(dev_desc->flags & D_INTR_NOTHREAD)) { + intr_resflags = II_THREADED; + } else { + /* Neither an error nor a thread. */ + intr_resflags = 0; + } + } else { + intr_swlevel = default_intr_pri; + intr_resflags = II_THREADED; + } + + /* XXX - Need to determine if the interrupt should be threaded. */ + + /* If the cpu has not been picked already then choose a candidate + * interrupt target and reserve the interrupt bit + */ +#if defined(NEW_INTERRUPTS) + if (!cpupicked) { + cpu = intr_heuristic(dev,dev_desc,allocate_my_bit, + intr_resflags,owner_dev, + intr_name,&bit); + } +#endif + + /* At this point we SHOULD have a valid cpu */ + if (cpu == CPU_NONE) { +#if defined(SUPPORT_PRINTING_V_FORMAT) + cmn_err(CE_WARN, + "%v hub_intr_alloc could not allocate interrupt\n", + owner_dev); +#else + cmn_err(CE_WARN, + "0x%p hub_intr_alloc could not allocate interrupt\n", + &owner_dev); +#endif + return(0); + + } + + /* If the cpu has been picked already (due to the bridge data + * corruption bug) then try to reserve an interrupt bit . + */ +#if defined(NEW_INTERRUPTS) + if (cpupicked) { + bit = intr_reserve_level(cpu, allocate_my_bit, + intr_resflags, + owner_dev, intr_name); + if (bit < 0) { +#if defined(SUPPORT_PRINTING_V_FORMAT) + cmn_err(CE_WARN, + "Could not reserve an interrupt bit for cpu " + " %d and dev %v\n", + cpu,owner_dev); +#else + cmn_err(CE_WARN, + "Could not reserve an interrupt bit for cpu " + " %d and dev 0x%x\n", + cpu, &owner_dev); +#endif + + return(0); + } + } +#endif /* NEW_INTERRUPTS */ + + nodeid = cputocnode(cpu); + nasid = COMPACT_TO_NASID_NODEID(nodeid); +#ifdef CONFIG_SGI_IP27 + xtalk_addr = HUBREG_AS_XTALKADDR(nasid, PI_INT_PEND_MOD); +#else /* CONFIG_IA64_SGI_SN1 */ + xtalk_addr = HUBREG_AS_XTALKADDR(nasid, PIREG(PI_INT_PEND_MOD, cputosubnode(cpu))); +#endif /* CONFIG_IA64_SGI_SN1 */ + + /* + * Allocate an interrupt handle, and fill it in. There are two + * pieces to an interrupt handle: the piece needed by generic + * xtalk code which is used by crosstalk device drivers, and + * the piece needed by low-level IP27 hardware code. + */ + intr_hdl = kmem_alloc_node(sizeof(struct hub_intr_s), KM_NOSLEEP, nodeid); + ASSERT_ALWAYS(intr_hdl); + + /* + * Fill in xtalk information for generic xtalk interfaces that + * operate on xtalk_intr_hdl's. + */ + xtalk_info = &intr_hdl->i_xtalk_info; + xtalk_info->xi_dev = dev; + xtalk_info->xi_vector = bit; + xtalk_info->xi_addr = xtalk_addr; + xtalk_info->xi_flags = (intr_resflags == II_THREADED) ? + 0 : XTALK_INTR_NOTHREAD; + + /* + * Regardless of which CPU we ultimately interrupt, a given crosstalk + * widget always handles interrupts (and PIO and DMA) through its + * designated "master" crosstalk provider. + */ + xwidget_info = xwidget_info_get(dev); + if (xwidget_info) + xtalk_info->xi_target = xwidget_info_masterid_get(xwidget_info); + + /* Fill in low level hub information for hub_* interrupt interface */ + intr_hdl->i_swlevel = intr_swlevel; + intr_hdl->i_cpuid = cpu; + intr_hdl->i_bit = bit; + intr_hdl->i_flags = HUB_INTR_IS_ALLOCED; + + /* Store the actual interrupt priority level & interrupt target + * cpu back in the device descriptor. + */ + hub_device_desc_update(dev_desc, intr_swlevel, cpu); +#ifdef CONFIG_IA64_SGI_SN1 + synergy_intr_alloc((int)bit, (int)cpu); +#endif + return(intr_hdl); +} + + +/* + * Free resources consumed by intr_alloc. + */ +void +hub_intr_free(hub_intr_t intr_hdl) +{ + cpuid_t cpu = intr_hdl->i_cpuid; + int bit = intr_hdl->i_bit; + xtalk_intr_t xtalk_info; + + if (intr_hdl->i_flags & HUB_INTR_IS_CONNECTED) { + /* Setting the following fields in the xtalk interrupt info + * clears the interrupt target register in the xtalk user + */ + xtalk_info = &intr_hdl->i_xtalk_info; + xtalk_info->xi_dev = NODEV; + xtalk_info->xi_vector = 0; + xtalk_info->xi_addr = 0; + hub_intr_disconnect(intr_hdl); + } + + if (intr_hdl->i_flags & HUB_INTR_IS_ALLOCED) + kfree(intr_hdl); + +#if defined(NEW_INTERRUPTS) + intr_unreserve_level(cpu, bit); +#endif +} + + +/* + * Associate resources allocated with a previous hub_intr_alloc call with the + * described handler, arg, name, etc. + */ +/*ARGSUSED*/ +int +hub_intr_connect( hub_intr_t intr_hdl, /* xtalk intr resource handle */ + intr_func_t intr_func, /* xtalk intr handler */ + void *intr_arg, /* arg to intr handler */ + xtalk_intr_setfunc_t setfunc, /* func to set intr hw */ + void *setfunc_arg, /* arg to setfunc */ + void *thread) /* intr thread to use */ +{ + int rv; + cpuid_t cpu = intr_hdl->i_cpuid; + int bit = intr_hdl->i_bit; +#ifdef CONFIG_IA64_SGI_SN1 + extern int synergy_intr_connect(int, int); +#endif + + ASSERT(intr_hdl->i_flags & HUB_INTR_IS_ALLOCED); + +#if defined(NEW_INTERRUPTS) + rv = intr_connect_level(cpu, bit, intr_hdl->i_swlevel, + intr_func, intr_arg, NULL); + if (rv < 0) + return(rv); + +#endif + intr_hdl->i_xtalk_info.xi_setfunc = setfunc; + intr_hdl->i_xtalk_info.xi_sfarg = setfunc_arg; + + if (setfunc) (*setfunc)((xtalk_intr_t)intr_hdl); + + intr_hdl->i_flags |= HUB_INTR_IS_CONNECTED; +#ifdef CONFIG_IA64_SGI_SN1 + return(synergy_intr_connect((int)bit, (int)cpu)); +#endif +} + + +/* + * Disassociate handler with the specified interrupt. + */ +void +hub_intr_disconnect(hub_intr_t intr_hdl) +{ + /*REFERENCED*/ + int rv; + cpuid_t cpu = intr_hdl->i_cpuid; + int bit = intr_hdl->i_bit; + xtalk_intr_setfunc_t setfunc; + + setfunc = intr_hdl->i_xtalk_info.xi_setfunc; + + /* TBD: send disconnected interrupts somewhere harmless */ + if (setfunc) (*setfunc)((xtalk_intr_t)intr_hdl); + +#if defined(NEW_INTERRUPTS) + rv = intr_disconnect_level(cpu, bit); + ASSERT(rv == 0); +#endif + + intr_hdl->i_flags &= ~HUB_INTR_IS_CONNECTED; +} + + +/* + * Return a hwgraph vertex that represents the CPU currently + * targeted by an interrupt. + */ +devfs_handle_t +hub_intr_cpu_get(hub_intr_t intr_hdl) +{ + cpuid_t cpuid = intr_hdl->i_cpuid; + ASSERT(cpuid != CPU_NONE); + + return(cpuid_to_vertex(cpuid)); +} + + + +/* CONFIGURATION MANAGEMENT */ + +/* + * Perform initializations that allow this hub to start crosstalk support. + */ +void +hub_provider_startup(devfs_handle_t hubv) +{ + hub_pio_init(hubv); + hub_dma_init(hubv); + hub_intr_init(hubv); +} + +/* + * Shutdown crosstalk support from a hub. + */ +void +hub_provider_shutdown(devfs_handle_t hub) +{ + /* TBD */ + xtalk_provider_unregister(hub); +} + +/* + * Check that an address is in teh real small window widget 0 space + * or else in the big window we're using to emulate small window 0 + * in the kernel. + */ +int +hub_check_is_widget0(void *addr) +{ + nasid_t nasid = NASID_GET(addr); + + if (((__psunsigned_t)addr >= RAW_NODE_SWIN_BASE(nasid, 0)) && + ((__psunsigned_t)addr < RAW_NODE_SWIN_BASE(nasid, 1))) + return 1; +#if defined (CONFIG_SGI_IP27) + if ((__psunsigned_t)addr >= NODE_BWIN_BASE(nasid, SWIN0_BIGWIN) && + ((__psunsigned_t)addr < NODE_BWIN_BASE(nasid, SWIN0_BIGWIN + 1))) + return 1; +#endif + return 0; +} + + +/* + * Check that two addresses use the same widget + */ +int +hub_check_window_equiv(void *addra, void *addrb) +{ + if (hub_check_is_widget0(addra) && hub_check_is_widget0(addrb)) + return 1; + + /* XXX - Assume this is really a small window address */ + if (WIDGETID_GET((__psunsigned_t)addra) == + WIDGETID_GET((__psunsigned_t)addrb)) + return 1; + + return 0; +} + + +/* + * Determine whether two PCI addresses actually refer to the same device. + * This only works if both addresses are in small windows. It's used to + * determine whether prom addresses refer to particular PCI devices. + */ +/* + * XXX - This won't work as written if we ever have more than two nodes + * on a crossbow. In that case, we'll need an array or partners. + */ +int +hub_check_pci_equiv(void *addra, void *addrb) +{ + nasid_t nasida, nasidb; + + /* + * This is for a permanent workaround that causes us to use a + * big window in place of small window 0. + */ + if (!hub_check_window_equiv(addra, addrb)) + return 0; + + /* If the offsets aren't the same, forget it. */ + if (SWIN_WIDGETADDR((__psunsigned_t)addra) != + (SWIN_WIDGETADDR((__psunsigned_t)addrb))) + return 0; + + /* Now, check the nasids */ + nasida = NASID_GET(addra); + nasidb = NASID_GET(addrb); + + ASSERT(NASID_TO_COMPACT_NODEID(nasida) != INVALID_NASID); + ASSERT(NASID_TO_COMPACT_NODEID(nasidb) != INVALID_NASID); + + /* + * Either the NASIDs must be the same or they must be crossbow + * partners (on the same crossbow). + */ + return (check_nasid_equiv(nasida, nasidb)); +} + +/* + * hub_setup_prb(nasid, prbnum, credits, conveyor) + * + * Put a PRB into fire-and-forget mode if conveyor isn't set. Otehrwise, + * put it into conveyor belt mode with the specified number of credits. + */ +void +hub_setup_prb(nasid_t nasid, int prbnum, int credits, int conveyor) +{ + iprb_t prb; + int prb_offset; +#ifdef IRIX + extern int force_fire_and_forget; + extern volatile int ignore_conveyor_override; + + if (force_fire_and_forget && !ignore_conveyor_override) + if (conveyor == HUB_PIO_CONVEYOR) + conveyor = HUB_PIO_FIRE_N_FORGET; +#endif + + /* + * Get the current register value. + */ + prb_offset = IIO_IOPRB(prbnum); + prb.iprb_regval = REMOTE_HUB_L(nasid, prb_offset); + + /* + * Clear out some fields. + */ + prb.iprb_ovflow = 1; + prb.iprb_bnakctr = 0; + prb.iprb_anakctr = 0; + + /* + * Enable or disable fire-and-forget mode. + */ + prb.iprb_ff = ((conveyor == HUB_PIO_CONVEYOR) ? 0 : 1); + + /* + * Set the appropriate number of PIO cresits for the widget. + */ + prb.iprb_xtalkctr = credits; + + /* + * Store the new value to the register. + */ + REMOTE_HUB_S(nasid, prb_offset, prb.iprb_regval); +} + +/* + * hub_set_piomode() + * + * Put the hub into either "PIO conveyor belt" mode or "fire-and-forget" + * mode. To do this, we have to make absolutely sure that no PIOs + * are in progress so we turn off access to all widgets for the duration + * of the function. + * + * XXX - This code should really check what kind of widget we're talking + * to. Bridges can only handle three requests, but XG will do more. + * How many can crossbow handle to widget 0? We're assuming 1. + * + * XXX - There is a bug in the crossbow that link reset PIOs do not + * return write responses. The easiest solution to this problem is to + * leave widget 0 (xbow) in fire-and-forget mode at all times. This + * only affects pio's to xbow registers, which should be rare. + */ +void +hub_set_piomode(nasid_t nasid, int conveyor) +{ + hubreg_t ii_iowa; + int direct_connect; + hubii_wcr_t ii_wcr; + int prbnum; + int s, cons_lock = 0; + + ASSERT(NASID_TO_COMPACT_NODEID(nasid) != INVALID_CNODEID); + if (nasid == get_console_nasid()) { + PUTBUF_LOCK(s); + cons_lock = 1; + } + + ii_iowa = REMOTE_HUB_L(nasid, IIO_OUTWIDGET_ACCESS); + REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, 0); + + ii_wcr.wcr_reg_value = REMOTE_HUB_L(nasid, IIO_WCR); + direct_connect = ii_wcr.iwcr_dir_con; + + if (direct_connect) { + /* + * Assume a bridge here. + */ + hub_setup_prb(nasid, 0, 3, conveyor); + } else { + /* + * Assume a crossbow here. + */ + hub_setup_prb(nasid, 0, 1, conveyor); + } + + for (prbnum = HUB_WIDGET_ID_MIN; prbnum <= HUB_WIDGET_ID_MAX; prbnum++) { + /* + * XXX - Here's where we should take the widget type into + * when account assigning credits. + */ + /* Always set the PRBs in fire-and-forget mode */ + hub_setup_prb(nasid, prbnum, 3, conveyor); + } + +#ifdef IRIX + /* + * In direct connect mode, disable access to all widgets but 0. + * Later, the prom will do this for us. + */ + if (direct_connect) + ii_iowa = 1; +#endif + + REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, ii_iowa); + + if (cons_lock) + PUTBUF_UNLOCK(s); +} +/* Interface to allow special drivers to set hub specific + * device flags. + * Return 0 on failure , 1 on success + */ +int +hub_widget_flags_set(nasid_t nasid, + xwidgetnum_t widget_num, + hub_widget_flags_t flags) +{ + + ASSERT((flags & HUB_WIDGET_FLAGS) == flags); + + if (flags & HUB_PIO_CONVEYOR) { + hub_setup_prb(nasid,widget_num, + 3,HUB_PIO_CONVEYOR); /* set the PRB in conveyor + * belt mode with 3 credits + */ + } else if (flags & HUB_PIO_FIRE_N_FORGET) { + hub_setup_prb(nasid,widget_num, + 3,HUB_PIO_FIRE_N_FORGET); /* set the PRB in fire + * and forget mode + */ + } + + return 1; +} +/* Interface to allow special drivers to set hub specific + * device flags. + * Return 0 on failure , 1 on success + */ +int +hub_device_flags_set(devfs_handle_t widget_vhdl, + hub_widget_flags_t flags) +{ + xwidget_info_t widget_info = xwidget_info_get(widget_vhdl); + xwidgetnum_t widget_num = xwidget_info_id_get(widget_info); + devfs_handle_t hub_vhdl = xwidget_info_master_get(widget_info); + hubinfo_t hub_info = 0; + nasid_t nasid; + int s,rv; + + /* Use the nasid from the hub info hanging off the hub vertex + * and widget number from the widget vertex + */ + hubinfo_get(hub_vhdl, &hub_info); + /* Being over cautious by grabbing a lock */ + s = mutex_spinlock(&hub_info->h_bwlock); + nasid = hub_info->h_nasid; + rv = hub_widget_flags_set(nasid,widget_num,flags); + mutex_spinunlock(&hub_info->h_bwlock, s); + + return rv; +} + +#if ((defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)) && defined(BRINGUP)) +/* BRINGUP: This ought to be useful for IP27 too but, for now, + * make it SN1 only because `ii_ixtt_u_t' is not in IP27/hubio.h + * (or anywhere else :-). + */ +int +hubii_ixtt_set(devfs_handle_t widget_vhdl, ii_ixtt_u_t *ixtt) +{ + xwidget_info_t widget_info = xwidget_info_get(widget_vhdl); + devfs_handle_t hub_vhdl = xwidget_info_master_get(widget_info); + hubinfo_t hub_info = 0; + nasid_t nasid; + int s; + + /* Use the nasid from the hub info hanging off the hub vertex + * and widget number from the widget vertex + */ + hubinfo_get(hub_vhdl, &hub_info); + /* Being over cautious by grabbing a lock */ + s = mutex_spinlock(&hub_info->h_bwlock); + nasid = hub_info->h_nasid; + + REMOTE_HUB_S(nasid, IIO_IXTT, ixtt->ii_ixtt_regval); + + mutex_spinunlock(&hub_info->h_bwlock, s); + return 0; +} + +int +hubii_ixtt_get(devfs_handle_t widget_vhdl, ii_ixtt_u_t *ixtt) +{ + xwidget_info_t widget_info = xwidget_info_get(widget_vhdl); + devfs_handle_t hub_vhdl = xwidget_info_master_get(widget_info); + hubinfo_t hub_info = 0; + nasid_t nasid; + int s; + + /* Use the nasid from the hub info hanging off the hub vertex + * and widget number from the widget vertex + */ + hubinfo_get(hub_vhdl, &hub_info); + /* Being over cautious by grabbing a lock */ + s = mutex_spinlock(&hub_info->h_bwlock); + nasid = hub_info->h_nasid; + + ixtt->ii_ixtt_regval = REMOTE_HUB_L(nasid, IIO_IXTT); + + mutex_spinunlock(&hub_info->h_bwlock, s); + return 0; +} +#endif /* CONFIG_IA64_SGI_SN1 */ + +/* + * hub_device_inquiry + * Find out the xtalk widget related information stored in this + * hub's II. + */ +void +hub_device_inquiry(devfs_handle_t xbus_vhdl, xwidgetnum_t widget) +{ + devfs_handle_t xconn, hub_vhdl; + char widget_name[8]; + hubreg_t ii_iidem,ii_iiwa, ii_iowa; + hubinfo_t hubinfo; + nasid_t nasid; + int d; + + sprintf(widget_name, "%d", widget); + if (hwgraph_traverse(xbus_vhdl, widget_name, &xconn) + != GRAPH_SUCCESS) + return; + + hub_vhdl = device_master_get(xconn); + if (hub_vhdl == GRAPH_VERTEX_NONE) + return; + + hubinfo_get(hub_vhdl, &hubinfo); + if (!hubinfo) + return; + + nasid = hubinfo->h_nasid; + + ii_iidem = REMOTE_HUB_L(nasid, IIO_IIDEM); + ii_iiwa = REMOTE_HUB_L(nasid, IIO_IIWA); + ii_iowa = REMOTE_HUB_L(nasid, IIO_IOWA); + +#if defined(SUPPORT_PRINTING_V_FORMAT) + cmn_err(CE_CONT, "Inquiry Info for %v\n", xconn); +#else + cmn_err(CE_CONT, "Inquiry Info for 0x%p\n", &xconn); +#endif + + cmn_err(CE_CONT,"\tDevices shutdown [ "); + + for (d = 0 ; d <= 7 ; d++) + if (!(ii_iidem & (IIO_IIDEM_WIDGETDEV_MASK(widget,d)))) + cmn_err(CE_CONT, " %d", d); + + cmn_err(CE_CONT,"]\n"); + + cmn_err(CE_CONT, + "\tInbound access ? %s\n", + ii_iiwa & IIO_IIWA_WIDGET(widget) ? "yes" : "no"); + + cmn_err(CE_CONT, + "\tOutbound access ? %s\n", + ii_iowa & IIO_IOWA_WIDGET(widget) ? "yes" : "no"); + +} + +/* + * A pointer to this structure hangs off of every hub hwgraph vertex. + * The generic xtalk layer may indirect through it to get to this specific + * crosstalk bus provider. + */ +xtalk_provider_t hub_provider = { + (xtalk_piomap_alloc_f *) hub_piomap_alloc, + (xtalk_piomap_free_f *) hub_piomap_free, + (xtalk_piomap_addr_f *) hub_piomap_addr, + (xtalk_piomap_done_f *) hub_piomap_done, + (xtalk_piotrans_addr_f *) hub_piotrans_addr, + + (xtalk_dmamap_alloc_f *) hub_dmamap_alloc, + (xtalk_dmamap_free_f *) hub_dmamap_free, + (xtalk_dmamap_addr_f *) hub_dmamap_addr, + (xtalk_dmamap_list_f *) hub_dmamap_list, + (xtalk_dmamap_done_f *) hub_dmamap_done, + (xtalk_dmatrans_addr_f *) hub_dmatrans_addr, + (xtalk_dmatrans_list_f *) hub_dmatrans_list, + (xtalk_dmamap_drain_f *) hub_dmamap_drain, + (xtalk_dmaaddr_drain_f *) hub_dmaaddr_drain, + (xtalk_dmalist_drain_f *) hub_dmalist_drain, + + (xtalk_intr_alloc_f *) hub_intr_alloc, + (xtalk_intr_free_f *) hub_intr_free, + (xtalk_intr_connect_f *) hub_intr_connect, + (xtalk_intr_disconnect_f *) hub_intr_disconnect, + (xtalk_intr_cpu_get_f *) hub_intr_cpu_get, + + (xtalk_provider_startup_f *) hub_provider_startup, + (xtalk_provider_shutdown_f *) hub_provider_shutdown, +}; + diff -urN linux-2.4.0-test10/arch/ia64/sn/io/ip37.c linux-2.4.0-test10-lia/arch/ia64/sn/io/ip37.c --- linux-2.4.0-test10/arch/ia64/sn/io/ip37.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/ip37.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,133 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +/* + * ip37.c + * Support for IP35/IP37 machines + */ + +#include +#include + +#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) +#include +#include +#include +#include /* for bridge_t */ + + +xwidgetnum_t +hub_widget_id(nasid_t nasid) +{ + hubii_wcr_t ii_wcr; /* the control status register */ + + ii_wcr.wcr_reg_value = REMOTE_HUB_L(nasid,IIO_WCR); + + printk("hub_widget_id: Found Hub Widget ID 0x%x from Register 0x%p\n", ii_wcr.wcr_fields_s.wcr_widget_id, REMOTE_HUB_ADDR(nasid, IIO_WCR)); + + printk("hub_widget_id: Found Hub Widget 0x%lx wcr_reg_value 0x%lx\n", REMOTE_HUB_L(nasid,IIO_WCR), ii_wcr.wcr_reg_value); + + return ii_wcr.wcr_fields_s.wcr_widget_id; +} + +/* + * get_nasid() returns the physical node id number of the caller. + */ +nasid_t +get_nasid(void) +{ + + printk("get_nasid: Found nasid = %d", + (nasid_t)((LOCAL_HUB_L(LB_REV_ID) & LRI_NODEID_MASK) >> LRI_NODEID_SHFT) ); + + return (nasid_t)((LOCAL_HUB_L(LB_REV_ID) & LRI_NODEID_MASK) + >> LRI_NODEID_SHFT); + +} + +int +get_slice(void) +{ + return LOCAL_HUB_L(PI_CPU_NUM); +} + +int +is_fine_dirmode(void) +{ + return (((LOCAL_HUB_L(LB_REV_ID) & LRI_SYSTEM_SIZE_MASK) + >> LRI_SYSTEM_SIZE_SHFT) == SYSTEM_SIZE_SMALL); + +} + +hubreg_t +get_hub_chiprev(nasid_t nasid) +{ + + printk("get_hub_chiprev: Hub Chip Rev 0x%lx\n", + (REMOTE_HUB_L(nasid, LB_REV_ID) & LRI_REV_MASK) >> LRI_REV_SHFT); + return ((REMOTE_HUB_L(nasid, LB_REV_ID) & LRI_REV_MASK) + >> LRI_REV_SHFT); +} + +int +verify_snchip_rev(void) +{ + int hub_chip_rev; + int i; + static int min_hub_rev = 0; + nasid_t nasid; + static int first_time = 1; + extern int maxnodes; + + + if (first_time) { + for (i = 0; i < maxnodes; i++) { + nasid = COMPACT_TO_NASID_NODEID(i); + hub_chip_rev = get_hub_chiprev(nasid); + + if ((hub_chip_rev < min_hub_rev) || (i == 0)) + min_hub_rev = hub_chip_rev; + } + + + first_time = 0; + } + + return min_hub_rev; + +} + +#ifdef SN1_USE_POISON_BITS +int +hub_bte_poison_ok(void) +{ + /* + * For now, assume poisoning is ok. If it turns out there are chip + * bugs that prevent its use in early revs, there is some neat code + * to steal from the IP27 equivalent of this code. + */ + +#ifdef BRINGUP /* temp disable BTE poisoning - might be sw bugs in this area */ + return 0; +#else + return 1; +#endif +} +#endif /* SN1_USE_POISON_BITS */ + + +void +ni_reset_port(void) +{ + LOCAL_HUB_S(NI_RESET_ENABLE, NRE_RESETOK); + LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET); +} + +#endif /* CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 */ diff -urN linux-2.4.0-test10/arch/ia64/sn/io/klconflib.c linux-2.4.0-test10-lia/arch/ia64/sn/io/klconflib.c --- linux-2.4.0-test10/arch/ia64/sn/io/klconflib.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/klconflib.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,1341 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define printf printk +int hasmetarouter; + +#define LDEBUG 0 +#define NIC_UNKNOWN ((nic_t) -1) + +#undef DEBUG_KLGRAPH +#ifdef DEBUG_KLGRAPH +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif /* DEBUG_KLGRAPH */ + +static void sort_nic_names(lboard_t *) ; + +lboard_t * +find_lboard(lboard_t *start, unsigned char brd_type) +{ + /* Search all boards stored on this node. */ + while (start) { + if (start->brd_type == brd_type) + return start; + start = KLCF_NEXT(start); + } + + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +lboard_t * +find_lboard_class(lboard_t *start, unsigned char brd_type) +{ + /* Search all boards stored on this node. */ + while (start) { + if (KLCLASS(start->brd_type) == KLCLASS(brd_type)) + return start; + start = KLCF_NEXT(start); + } + + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +klinfo_t * +find_component(lboard_t *brd, klinfo_t *kli, unsigned char struct_type) +{ + int index, j; + + if (kli == (klinfo_t *)NULL) { + index = 0; + } else { + for (j = 0; j < KLCF_NUM_COMPS(brd); j++) { + if (kli == KLCF_COMP(brd, j)) + break; + } + index = j; + if (index == KLCF_NUM_COMPS(brd)) { + printf("find_component: Bad pointer: 0x%p\n", kli); + return (klinfo_t *)NULL; + } + index++; /* next component */ + } + + for (; index < KLCF_NUM_COMPS(brd); index++) { + kli = KLCF_COMP(brd, index); + DBG("find_component: brd %p kli %p request type = 0x%x kli type 0x%x\n", brd, kli, kli->struct_type, KLCF_COMP_TYPE(kli)); + if (KLCF_COMP_TYPE(kli) == struct_type) + return kli; + } + + /* Didn't find it. */ + return (klinfo_t *)NULL; +} + +klinfo_t * +find_first_component(lboard_t *brd, unsigned char struct_type) +{ + return find_component(brd, (klinfo_t *)NULL, struct_type); +} + +lboard_t * +find_lboard_modslot(lboard_t *start, moduleid_t mod, slotid_t slot) +{ + /* Search all boards stored on this node. */ + while (start) { + if (MODULE_MATCH(start->brd_module, mod) && + (start->brd_slot == slot)) + return start; + start = KLCF_NEXT(start); + } + + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +lboard_t * +find_lboard_module(lboard_t *start, moduleid_t mod) +{ + /* Search all boards stored on this node. */ + while (start) { + if (MODULE_MATCH(start->brd_module, mod)) + return start; + start = KLCF_NEXT(start); + } + + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +lboard_t * +find_lboard_module_class(lboard_t *start, moduleid_t mod, + unsigned char brd_type) +{ + while (start) { + + DBG("find_lboard_module_class: lboard 0x%p, start->brd_module 0x%x, mod 0x%x, start->brd_type 0x%x, brd_type 0x%x\n", start, start->brd_module, mod, start->brd_type, brd_type); + + if (MODULE_MATCH(start->brd_module, mod) && + (KLCLASS(start->brd_type) == KLCLASS(brd_type))) + return start; + start = KLCF_NEXT(start); + } + + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +#ifndef CONFIG_IA64_SGI_IO +#define tolower(c) (isupper(c) ? (c) - 'A' + 'a' : (c)) +#define toupper(c) (islower(c) ? (c) - 'a' + 'A' : (c)) +#endif + + +/* + * Convert a NIC name to a name for use in the hardware graph. + */ +void +nic_name_convert(char *old_name, char *new_name) +{ + int i; + char c; + char *compare_ptr; + + if ((old_name[0] == '\0') || (old_name[1] == '\0')) { + strcpy(new_name, EDGE_LBL_XWIDGET); + } else { + for (i = 0; i < strlen(old_name); i++) { + c = old_name[i]; + + if (isalpha(c)) + new_name[i] = tolower(c); + else if (isdigit(c)) + new_name[i] = c; + else + new_name[i] = '_'; + } + new_name[i] = '\0'; + } + + /* XXX - + * Since a bunch of boards made it out with weird names like + * IO6-fibbbed and IO6P2, we need to look for IO6 in a name and + * replace it with "baseio" to avoid confusion in the field. + * We also have to make sure we don't report media_io instead of + * baseio. + */ + + /* Skip underscores at the beginning of the name */ + for (compare_ptr = new_name; (*compare_ptr) == '_'; compare_ptr++) + ; + + /* + * Check for some names we need to replace. Early boards + * had junk following the name so check only the first + * characters. + */ + if (!strncmp(new_name, "io6", 3) || + !strncmp(new_name, "mio", 3) || + !strncmp(new_name, "media_io", 8)) + strcpy(new_name, "baseio"); +#if !defined(CONFIG_SGI_IP35) && !defined(CONFIG_IA64_SGI_SN1) && !defined(CONFIG_IA64_GENERIC) + else if (!strncmp(new_name, "ip29", 4)) + strcpy(new_name,SN00_MOTHERBOARD); +#endif + else if (!strncmp(new_name, "divo", 4)) + strcpy(new_name, "divo") ; + +} + +/* Check if the given board corresponds to the global + * master io6 + */ +int +is_master_baseio(nasid_t nasid,moduleid_t module,slotid_t slot) +{ + lboard_t *board; + +#if CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 || CONFIG_IA64_GENERIC +/* BRINGUP: If this works then look for callers of is_master_baseio() + * (e.g. iograph.c) and let them pass in a slot if they want + */ + board = find_lboard_module((lboard_t *)KL_CONFIG_INFO(nasid), module); +#else + board = find_lboard_modslot((lboard_t *)KL_CONFIG_INFO(nasid), + module, slot); +#endif + +#ifndef _STANDALONE + { + cnodeid_t cnode = NASID_TO_COMPACT_NODEID(nasid); + + if (!board && (NODEPDA(cnode)->xbow_peer != INVALID_NASID)) +#if CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 || CONFIG_IA64_GENERIC + board = find_lboard_module((lboard_t *) + KL_CONFIG_INFO(NODEPDA(cnode)->xbow_peer), + module); +#else + board = find_lboard_modslot((lboard_t *) + KL_CONFIG_INFO(NODEPDA(cnode)->xbow_peer), + module, slot); +#endif + } +#endif + if (!board) + return(0); + return(board->brd_flags & GLOBAL_MASTER_IO6); +} +/* + * Find the lboard structure and get the board name. + * If we can't find the structure or it's too low a revision, + * use default name. + */ +lboard_t * +get_board_name(nasid_t nasid, moduleid_t mod, slotid_t slot, char *name) +{ + lboard_t *brd; + + brd = find_lboard_modslot((lboard_t *)KL_CONFIG_INFO(nasid), + mod, slot); + +#ifndef _STANDALONE + { + cnodeid_t cnode = NASID_TO_COMPACT_NODEID(nasid); + + if (!brd && (NODEPDA(cnode)->xbow_peer != INVALID_NASID)) + brd = find_lboard_modslot((lboard_t *) + KL_CONFIG_INFO(NODEPDA(cnode)->xbow_peer), + mod, slot); + } +#endif + + if (!brd || (brd->brd_sversion < 2)) { + strcpy(name, EDGE_LBL_XWIDGET); + } else { + nic_name_convert(brd->brd_name, name); + } + + /* + * PV # 540860 + * If the name is not 'baseio' or SN00 MOTHERBOARD + * get the lowest of all the names in the nic string. + * This is needed for boards like divo, which can have + * a bunch of daughter cards, but would like to be called + * divo. We could do this for baseio and SN00 MOTHERBOARD + * but it has some special case names that we would not + * like to disturb at this point. + */ + + /* gfx boards don't need any of this name scrambling */ + if (brd && (KLCLASS(brd->brd_type) == KLCLASS_GFX)) { + return(brd); + } + + if (!(!strcmp(name, "baseio") )) { + if (brd) { + sort_nic_names(brd) ; + /* Convert to small case, '-' to '_' etc */ + nic_name_convert(brd->brd_name, name) ; + } + } + + return(brd); +} + +int +get_cpu_slice(cpuid_t cpu) +{ + klcpu_t *acpu; + if ((acpu = get_cpuinfo(cpu)) == NULL) + return -1; + return acpu->cpu_info.physid; +} + + +/* + * get_actual_nasid + * + * Completely disabled brds have their klconfig on + * some other nasid as they have no memory. But their + * actual nasid is hidden in the klconfig. Use this + * routine to get it. Works for normal boards too. + */ +nasid_t +get_actual_nasid(lboard_t *brd) +{ + klhub_t *hub ; + + if (!brd) + return INVALID_NASID ; + + /* find out if we are a completely disabled brd. */ + + hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB); + if (!hub) + return INVALID_NASID ; + if (!(hub->hub_info.flags & KLINFO_ENABLE)) /* disabled node brd */ + return hub->hub_info.physid ; + else + return brd->brd_nasid ; +} + +int +xbow_port_io_enabled(nasid_t nasid, int link) +{ + lboard_t *brd; + klxbow_t *xbow_p; + + /* + * look for boards that might contain an xbow or xbridge + */ +#if SN0 + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_MIDPLANE8); +#else + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_PBRICK_XBOW); +#endif + if (brd == NULL) return 0; + + if ((xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW)) + == NULL) + return 0; + + if (!XBOW_PORT_TYPE_IO(xbow_p, link) || !XBOW_PORT_IS_ENABLED(xbow_p, link)) + return 0; + + printf("xbow_port_io_enabled: brd 0x%p xbow_p 0x%p \n", brd, xbow_p); + + return 1; +} + +void +board_to_path(lboard_t *brd, char *path) +{ + moduleid_t modnum; + char *board_name; +#if !defined(CONFIG_SGI_IP35) && !defined(CONFIG_IA64_SGI_SN1) && !defined(CONFIG_IA64_GENERIC) + slotid_t slot; + char slot_name[SLOTNUM_MAXLENGTH]; +#endif + + ASSERT(brd); + + switch (KLCLASS(brd->brd_type)) { + + case KLCLASS_NODE: + board_name = EDGE_LBL_NODE; + break; + case KLCLASS_ROUTER: + if (brd->brd_type == KLTYPE_META_ROUTER) { + board_name = EDGE_LBL_META_ROUTER; + hasmetarouter++; + } else + board_name = EDGE_LBL_ROUTER; + break; + case KLCLASS_MIDPLANE: + board_name = EDGE_LBL_MIDPLANE; + break; + case KLCLASS_IO: + board_name = EDGE_LBL_IO; + break; + case KLCLASS_IOBRICK: + if (brd->brd_type == KLTYPE_PBRICK) + board_name = EDGE_LBL_PBRICK; + else if (brd->brd_type == KLTYPE_IBRICK) + board_name = EDGE_LBL_IBRICK; + else if (brd->brd_type == KLTYPE_XBRICK) + board_name = EDGE_LBL_XBRICK; + else + board_name = EDGE_LBL_IOBRICK; + break; + default: + board_name = EDGE_LBL_UNKNOWN; + } + + modnum = brd->brd_module; + +#if defined(SN0) + slot = brd->brd_slot; + get_slotname(slot, slot_name); + + ASSERT(modnum >= 0); + + sprintf(path, "%H/" EDGE_LBL_SLOT "/%s/%s", + modnum, slot_name, board_name); +#else + ASSERT(modnum != MODULE_UNKNOWN && modnum != INVALID_MODULE); +#ifdef BRINGUP /* fix IP35 hwgraph */ + sprintf(path, EDGE_LBL_MODULE "/%x/%s", modnum, board_name); +#else + sprintf(path, "%H/%s", modnum, board_name); +#endif +#endif +} + +/* + * Get the module number for a NASID. + */ +moduleid_t +get_module_id(nasid_t nasid) +{ + lboard_t *brd; + + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27); + + if (!brd) + return INVALID_MODULE; + else + return brd->brd_module; +} + + +#ifndef CONFIG_IA64_SGI_IO +#if 1 +/* + * find_gfxpipe(#) + * + * XXXmacko + * This is only used by graphics drivers, and should be moved + * over to gfx/kern/graphics/SN0 as soon as it's convenient. + */ +static klgfx_t *graphics_pipe_list = NULL; +static devfs_handle_t hwgraph_all_gfxids = GRAPH_VERTEX_NONE; + +void +setup_gfxpipe_link(devfs_handle_t vhdl,int pipenum) +{ + char idbuf[8]; + extern graph_hdl_t hwgraph; + + graph_info_add_LBL(hwgraph, vhdl, INFO_LBL_GFXID, INFO_DESC_EXPORT, + (arbitrary_info_t)pipenum); + if (hwgraph_all_gfxids == GRAPH_VERTEX_NONE) + hwgraph_path_add(hwgraph_root, EDGE_LBL_GFX, &hwgraph_all_gfxids); + sprintf(idbuf, "%d", pipenum); + hwgraph_edge_add(hwgraph_all_gfxids, vhdl, idbuf); + +} +#endif + +/* + * find the pipenum'th logical graphics pipe (KLCLASS_GFX) + */ +lboard_t * +find_gfxpipe(int pipenum) +{ + gda_t *gdap; + cnodeid_t cnode; + nasid_t nasid; + lboard_t *lb; + klgfx_t *kg,**pkg; + int i; + + gdap = (gda_t *)GDA_ADDR(get_nasid()); + if (gdap->g_magic != GDA_MAGIC) + return NULL; + + if (!graphics_pipe_list) { + /* for all nodes */ + for (cnode = 0; cnode < MAX_COMPACT_NODES; cnode ++) { + nasid = gdap->g_nasidtable[cnode]; + if (nasid == INVALID_NASID) + continue; + lb = KL_CONFIG_INFO(nasid) ; + while (lb = find_lboard_class(lb, KLCLASS_GFX)) { + moduleid_t kgm, pkgm; + int kgs, pkgs; + +#if defined(DEBUG) && (defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1 || defined(CONFIG_IA64_GENERIC))) && defined(BRINGUP) + printf("find_gfxpipe(): PIPE: %s mod %M slot %d\n",lb?lb->brd_name:"!LBRD", + lb->brd_module,lb->brd_slot); +#endif + /* insert lb into list */ + if (!(kg = (klgfx_t*)find_first_component(lb,KLSTRUCT_GFX))) { + lb = KLCF_NEXT(lb); + continue; + } + /* set moduleslot now that we have brd_module set */ + kg->moduleslot = (lb->brd_module << 8) | SLOTNUM_GETSLOT(lb->brd_slot); + /* make sure board has device flag set */ + kg->gfx_info.flags |= KLINFO_DEVICE; + if (kg->cookie < KLGFX_COOKIE) { + kg->gfx_next_pipe = NULL; + kg->cookie = KLGFX_COOKIE; + } + + kgm = kg->moduleslot>>8; + kgs = kg->moduleslot&0xff; + pkg = &graphics_pipe_list; + while (*pkg) { + pkgm = (*pkg)->moduleslot>>8; + pkgs = (*pkg)->moduleslot&0xff; + + if (!(MODULE_CMP(kgm, pkgm) > 0 || + (MODULE_CMP(kgm, pkgm) == 0 && + kgs > pkgs))) + break; + + pkg = &(*pkg)->gfx_next_pipe; + } + kg->gfx_next_pipe = *pkg; + *pkg = kg; + lb = KLCF_NEXT(lb); + } + } +#ifdef FIND_GFXPIPE_DEBUG + i = 0; + kg = graphics_pipe_list; + while (kg) { + lboard_t *lb; +#if defined(CONFIG_SGI_IP27) + lb = find_lboard_modslot(KL_CONFIG_INFO(kg->gfx_info.nasid), + (kg->moduleslot>>8),SLOTNUM_XTALK_CLASS|(kg->moduleslot&0xff)); +#elif defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) + lb = find_lboard_class(KL_CONFIG_INFO(kg->gfx_info.nasid), KLCLASS_GFX); +#else +#error Need to figure out how to find graphics boards ... +#endif +#if defined(SUPPORT_PRINTING_M_FORMAT) + printf("find_gfxpipe(): %s pipe %d mod %M slot %d\n",lb?lb->brd_name:"!LBRD",i, + (kg->moduleslot>>8),(kg->moduleslot&0xff)); +#else + printf("find_gfxpipe(): %s pipe %d mod 0x%x slot %d\n",lb?lb->brd_name:"!LBRD",i, + (kg->moduleslot>>8),(kg->moduleslot&0xff)); +#endif + kg = kg->gfx_next_pipe; + i++; + } +#endif + } + + i = 0; + kg = graphics_pipe_list; + while (kg && (i < pipenum)) { + kg = kg->gfx_next_pipe; + i++; + } + + if (!kg) return NULL; + +#if defined(SN0) + return find_lboard_modslot(KL_CONFIG_INFO(kg->gfx_info.nasid), + (kg->moduleslot>>8), + SLOTNUM_XTALK_CLASS|(kg->moduleslot&0xff)); +#elif defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) + return find_lboard_class(KL_CONFIG_INFO(kg->gfx_info.nasid), KLCLASS_GFX); +#else +#error Need to figure out how to find graphics boards ... +#endif +} +#endif + + +#define MHZ 1000000 + +#ifndef CONFIG_IA64_SGI_IO +uint +cpu_cycles_adjust(uint orig_cycles) +{ + klcpu_t *acpu; + uint speed; + + acpu = nasid_slice_to_cpuinfo(get_nasid(), get_slice()); + + if (acpu == NULL) return orig_cycles; + + /* + * cpu cycles seem to be half of the real value, hack and mult by 2 + * for now. + */ + speed = (orig_cycles * 2) / MHZ; + + /* + * if the cpu thinks its running at some random speed nowhere close + * the programmed speed, do nothing. + */ + if ((speed < (acpu->cpu_speed - 2)) || (speed > (acpu->cpu_speed + 2))) + return orig_cycles; + return (acpu->cpu_speed * MHZ/2); +} +#endif /* CONFIG_IA64_SGI_IO */ + +/* Get the canonical hardware graph name for the given pci component + * on the given io board. + */ +void +device_component_canonical_name_get(lboard_t *brd, + klinfo_t *component, + char *name) +{ + moduleid_t modnum; + slotid_t slot; + char board_name[20]; +#ifdef SN0 + char slot_name[SLOTNUM_MAXLENGTH]; +#endif + + ASSERT(brd); + + /* Get the module number of this board */ + modnum = brd->brd_module; + + /* Convert the [ CLASS | TYPE ] kind of slotid + * into a string + */ + slot = brd->brd_slot; +#ifdef SN0 + get_slotname(slot, slot_name); + + ASSERT(modnum >= 0); +#else + ASSERT(modnum != MODULE_UNKNOWN && modnum != INVALID_MODULE); +#endif + + /* Get the io board name */ + if (!brd || (brd->brd_sversion < 2)) { + strcpy(name, EDGE_LBL_XWIDGET); + } else { + nic_name_convert(brd->brd_name, board_name); + } + + /* Give out the canonical name of the pci device*/ +#ifdef SN0 + sprintf(name, + "/hw/"EDGE_LBL_MODULE "/%M/"EDGE_LBL_SLOT"/%s/%s/" + EDGE_LBL_PCI"/%d", + modnum, slot_name, board_name,KLCF_BRIDGE_W_ID(component)); +#elif defined (CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) + sprintf(name, + "/dev/hw/"EDGE_LBL_MODULE "/%x/"EDGE_LBL_SLOT"/%s/" + EDGE_LBL_PCI"/%d", + modnum, board_name,KLCF_BRIDGE_W_ID(component)); +#endif + +} + +/* + * Get the serial number of the main component of a board + * Returns 0 if a valid serial number is found + * 1 otherwise. + * Assumptions: Nic manufacturing string has the following format + * *Serial:;* + */ +static int +component_serial_number_get(lboard_t *board, + klconf_off_t mfg_nic_offset, + char *serial_number, + char *key_pattern) +{ + + char *mfg_nic_string; + char *serial_string,*str; + int i; + char *serial_pattern = "Serial:"; + + /* We have an error on a null mfg nic offset */ + if (!mfg_nic_offset) + return(1); + /* Get the hub's manufacturing nic information + * which is in the form of a pre-formatted string + */ + mfg_nic_string = + (char *)NODE_OFFSET_TO_K1(NASID_GET(board), + mfg_nic_offset); + /* There is no manufacturing nic info */ + if (!mfg_nic_string) + return(1); + + str = mfg_nic_string; + /* Look for the key pattern first (if it is specified) + * and then print the serial number corresponding to that. + */ + if (strcmp(key_pattern,"") && + !(str = strstr(mfg_nic_string,key_pattern))) + return(1); + + /* There is no serial number info in the manufacturing + * nic info + */ + if (!(serial_string = strstr(str,serial_pattern))) + return(1); + + serial_string = serial_string + strlen(serial_pattern); + /* Copy the serial number information from the klconfig */ + i = 0; + while (serial_string[i] != ';') { + serial_number[i] = serial_string[i]; + i++; + } + serial_number[i] = 0; + + return(0); +} +/* + * Get the serial number of a board + * Returns 0 if a valid serial number is found + * 1 otherwise. + */ + +int +board_serial_number_get(lboard_t *board,char *serial_number) +{ + ASSERT(board && serial_number); + if (!board || !serial_number) + return(1); + + strcpy(serial_number,""); + switch(KLCLASS(board->brd_type)) { + case KLCLASS_CPU: { /* Node board */ + klhub_t *hub; + + /* Get the hub component information */ + hub = (klhub_t *)find_first_component(board, + KLSTRUCT_HUB); + /* If we don't have a hub component on an IP27 + * then we have a weird klconfig. + */ + if (!hub) + return(1); + /* Get the serial number information from + * the hub's manufacturing nic info + */ + if (component_serial_number_get(board, + hub->hub_mfg_nic, + serial_number, +#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) + "IP35")) +#else + "IP27")) + /* Try with IP31 key if IP27 key fails */ + if (component_serial_number_get(board, + hub->hub_mfg_nic, + serial_number, + "IP31")) +#endif /* CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 */ + return(1); + break; + } + case KLCLASS_IO: { /* IO board */ + if (KLTYPE(board->brd_type) == KLTYPE_TPU) { + /* Special case for TPU boards */ + kltpu_t *tpu; + + /* Get the tpu component information */ + tpu = (kltpu_t *)find_first_component(board, + KLSTRUCT_TPU); + /* If we don't have a tpu component on a tpu board + * then we have a weird klconfig. + */ + if (!tpu) + return(1); + /* Get the serial number information from + * the tpu's manufacturing nic info + */ + if (component_serial_number_get(board, + tpu->tpu_mfg_nic, + serial_number, + "")) + return(1); + break; + } else if ((KLTYPE(board->brd_type) == KLTYPE_GSN_A) || + (KLTYPE(board->brd_type) == KLTYPE_GSN_B)) { + /* Special case for GSN boards */ + klgsn_t *gsn; + + /* Get the gsn component information */ + gsn = (klgsn_t *)find_first_component(board, + ((KLTYPE(board->brd_type) == KLTYPE_GSN_A) ? + KLSTRUCT_GSN_A : KLSTRUCT_GSN_B)); + /* If we don't have a gsn component on a gsn board + * then we have a weird klconfig. + */ + if (!gsn) + return(1); + /* Get the serial number information from + * the gsn's manufacturing nic info + */ + if (component_serial_number_get(board, + gsn->gsn_mfg_nic, + serial_number, + "")) + return(1); + break; + } else { + klbri_t *bridge; + + /* Get the bridge component information */ + bridge = (klbri_t *)find_first_component(board, + KLSTRUCT_BRI); + /* If we don't have a bridge component on an IO board + * then we have a weird klconfig. + */ + if (!bridge) + return(1); + /* Get the serial number information from + * the bridge's manufacturing nic info + */ + if (component_serial_number_get(board, + bridge->bri_mfg_nic, + serial_number, + "")) + return(1); + break; + } + } + case KLCLASS_ROUTER: { /* Router board */ + klrou_t *router; + + /* Get the router component information */ + router = (klrou_t *)find_first_component(board, + KLSTRUCT_ROU); + /* If we don't have a router component on a router board + * then we have a weird klconfig. + */ + if (!router) + return(1); + /* Get the serial number information from + * the router's manufacturing nic info + */ + if (component_serial_number_get(board, + router->rou_mfg_nic, + serial_number, + "")) + return(1); + break; + } + case KLCLASS_GFX: { /* Gfx board */ + klgfx_t *graphics; + + /* Get the graphics component information */ + graphics = (klgfx_t *)find_first_component(board, KLSTRUCT_GFX); + /* If we don't have a gfx component on a gfx board + * then we have a weird klconfig. + */ + if (!graphics) + return(1); + /* Get the serial number information from + * the graphics's manufacturing nic info + */ + if (component_serial_number_get(board, + graphics->gfx_mfg_nic, + serial_number, + "")) + return(1); + break; + } + default: + strcpy(serial_number,""); + break; + } + return(0); +} + +#ifndef _STANDALONE + +#include "asm/sn/sn_private.h" +#ifndef CONFIG_IA64_SGI_IO +/* + * Given a physical address get the name of memory dimm bank + * in a hwgraph name format. + */ +void +membank_pathname_get(paddr_t paddr,char *name) +{ + cnodeid_t cnode; + char slotname[SLOTNUM_MAXLENGTH]; + + cnode = paddr_cnode(paddr); + /* Make sure that we have a valid name buffer */ + if (!name) + return; + + name[0] = 0; + /* Make sure that the cnode is valid */ + if ((cnode == CNODEID_NONE) || (cnode > numnodes)) + return; + /* Given a slotid(class:type) get the slotname */ +#if defined (SN0) + get_slotname(NODE_SLOTID(cnode),slotname); + sprintf(name, + "/hw/"EDGE_LBL_MODULE"/%M/"EDGE_LBL_SLOT"/%s/"EDGE_LBL_NODE + "/"EDGE_LBL_MEMORY"/dimm_bank/%d", + NODE_MODULEID(cnode),slotname,paddr_dimm(paddr)); +#elif defined (CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) + sprintf(name, + "/dev/hw/"EDGE_LBL_MODULE"/%M/"EDGE_LBL_NODE + "/"EDGE_LBL_MEMORY"/dimm_bank/%d", + NODE_MODULEID(cnode),paddr_dimm(paddr)); +#endif +} + + + +int +membank_check_mixed_hidensity(nasid_t nasid) +{ + lboard_t *brd; + klmembnk_t *mem; + int min_size = 1024, max_size = 0; + int bank, mem_size; + + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27); + ASSERT(brd); + + mem = (klmembnk_t *)find_first_component(brd, KLSTRUCT_MEMBNK); + ASSERT(mem); + + + for (mem_size = 0, bank = 0; bank < MD_MEM_BANKS; bank++) { + mem_size = KLCONFIG_MEMBNK_SIZE(mem, bank); + if (mem_size < min_size) + min_size = mem_size; + if (mem_size > max_size) + max_size = mem_size; + } + + if ((max_size == 512) && (max_size != min_size)) + return 1; + + return 0; +} + + +int +mem_mixed_hidensity_banks(void) +{ + cnodeid_t cnode; + nasid_t nasid; + + for (cnode = 0; cnode < maxnodes; cnode++) { + nasid = COMPACT_TO_NASID_NODEID(cnode); + if (nasid == INVALID_NASID) + continue; + if (membank_check_mixed_hidensity(nasid)) + return 1; + } + return 0; + +} +#endif /* CONFIG_IA64_SGI_IO */ + +xwidgetnum_t +nodevertex_widgetnum_get(devfs_handle_t node_vtx) +{ + hubinfo_t hubinfo_p; + + hwgraph_info_get_LBL(node_vtx, INFO_LBL_NODE_INFO, + (arbitrary_info_t *) &hubinfo_p); + return(hubinfo_p->h_widgetid); +} + +devfs_handle_t +nodevertex_xbow_peer_get(devfs_handle_t node_vtx) +{ + hubinfo_t hubinfo_p; + nasid_t xbow_peer_nasid; + cnodeid_t xbow_peer; + + hwgraph_info_get_LBL(node_vtx, INFO_LBL_NODE_INFO, + (arbitrary_info_t *) &hubinfo_p); + xbow_peer_nasid = hubinfo_p->h_nodepda->xbow_peer; + if(xbow_peer_nasid == INVALID_NASID) + return ( (devfs_handle_t)-1); + xbow_peer = NASID_TO_COMPACT_NODEID(xbow_peer_nasid); + return(NODEPDA(xbow_peer)->node_vertex); +} + +#endif /* !_STANDALONE */ + +/* NIC Sorting Support */ + +#define MAX_NICS_PER_STRING 32 +#define MAX_NIC_NAME_LEN 32 + +static char * +get_nic_string(lboard_t *lb) +{ + int i; + klinfo_t *k = NULL ; + klconf_off_t mfg_off = 0 ; + char *mfg_nic = NULL ; + + for (i = 0; i < KLCF_NUM_COMPS(lb); i++) { + k = KLCF_COMP(lb, i) ; + switch(k->struct_type) { + case KLSTRUCT_BRI: + mfg_off = ((klbri_t *)k)->bri_mfg_nic ; + break ; + + case KLSTRUCT_HUB: + mfg_off = ((klhub_t *)k)->hub_mfg_nic ; + break ; + + case KLSTRUCT_ROU: + mfg_off = ((klrou_t *)k)->rou_mfg_nic ; + break ; + + case KLSTRUCT_GFX: + mfg_off = ((klgfx_t *)k)->gfx_mfg_nic ; + break ; + + case KLSTRUCT_TPU: + mfg_off = ((kltpu_t *)k)->tpu_mfg_nic ; + break ; + + case KLSTRUCT_GSN_A: + case KLSTRUCT_GSN_B: + mfg_off = ((klgsn_t *)k)->gsn_mfg_nic ; + break ; + + case KLSTRUCT_XTHD: + mfg_off = ((klxthd_t *)k)->xthd_mfg_nic ; + break; + + default: + mfg_off = 0 ; + break ; + } + if (mfg_off) + break ; + } + + if ((mfg_off) && (k)) + mfg_nic = (char *)NODE_OFFSET_TO_K1(k->nasid, mfg_off) ; + + return mfg_nic ; +} + +char * +get_first_string(char **ptrs, int n) +{ + int i ; + char *tmpptr ; + + if ((ptrs == NULL) || (n == 0)) + return NULL ; + + tmpptr = ptrs[0] ; + + if (n == 1) + return tmpptr ; + + for (i = 0 ; i < n ; i++) { + if (strcmp(tmpptr, ptrs[i]) > 0) + tmpptr = ptrs[i] ; + } + + return tmpptr ; +} + +int +get_ptrs(char *idata, char **ptrs, int n, char *label) +{ + int i = 0 ; + char *tmp = idata ; + + if ((ptrs == NULL) || (idata == NULL) || (label == NULL) || (n == 0)) + return 0 ; + + while ( (tmp = strstr(tmp, label)) ){ + tmp += strlen(label) ; + /* check for empty name field, and last NULL ptr */ + if ((i < (n-1)) && (*tmp != ';')) { + ptrs[i++] = tmp ; + } + } + + ptrs[i] = NULL ; + + return i ; +} + +/* + * sort_nic_names + * + * Does not really do sorting. Find the alphabetically lowest + * name among all the nic names found in a nic string. + * + * Return: + * Nothing + * + * Side Effects: + * + * lb->brd_name gets the new name found + */ + +static void +sort_nic_names(lboard_t *lb) +{ + char *nic_str ; + char *ptrs[MAX_NICS_PER_STRING] ; + char name[MAX_NIC_NAME_LEN] ; + char *tmp, *tmp1 ; + + *name = 0 ; + + /* Get the nic pointer from the lb */ + + if ((nic_str = get_nic_string(lb)) == NULL) + return ; + + tmp = get_first_string(ptrs, + get_ptrs(nic_str, ptrs, MAX_NICS_PER_STRING, "Name:")) ; + + if (tmp == NULL) + return ; + + if ( (tmp1 = strchr(tmp, ';')) ){ + strncpy(name, tmp, tmp1-tmp) ; + name[tmp1-tmp] = 0 ; + } else { + strncpy(name, tmp, (sizeof(name) -1)) ; + name[sizeof(name)-1] = 0 ; + } + + strcpy(lb->brd_name, name) ; +} + + +#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) + +char brick_types[MAX_BRICK_TYPES + 1] = "crikxdp789012345"; + +/* + * Format a module id for printing. + */ +void +format_module_id(char *buffer, moduleid_t m, int fmt) +{ + int rack, position; + char brickchar; + + rack = MODULE_GET_RACK(m); + ASSERT(MODULE_GET_BTYPE(m) < MAX_BRICK_TYPES); + brickchar = MODULE_GET_BTCHAR(m); + position = MODULE_GET_BPOS(m); + + if (fmt == MODULE_FORMAT_BRIEF) { + /* Brief module number format, eg. 002c15 */ + + /* Decompress the rack number */ + *buffer++ = '0' + RACK_GET_CLASS(rack); + *buffer++ = '0' + RACK_GET_GROUP(rack); + *buffer++ = '0' + RACK_GET_NUM(rack); + + /* Add the brick type */ + *buffer++ = brickchar; + } + else if (fmt == MODULE_FORMAT_LONG) { + /* Fuller hwgraph format, eg. rack/002/bay/15 */ + + strcpy(buffer, EDGE_LBL_RACK "/"); buffer += strlen(buffer); + + *buffer++ = '0' + RACK_GET_CLASS(rack); + *buffer++ = '0' + RACK_GET_GROUP(rack); + *buffer++ = '0' + RACK_GET_NUM(rack); + + strcpy(buffer, "/" EDGE_LBL_RPOS "/"); buffer += strlen(buffer); + } + + /* Add the bay position, using at least two digits */ + if (position < 10) + *buffer++ = '0'; + sprintf(buffer, "%d", position); + +} + +/* + * Parse a module id, in either brief or long form. + * Returns < 0 on error. + * The long form does not include a brick type, so it defaults to 0 (CBrick) + */ +int +parse_module_id(char *buffer) +{ + unsigned int v, rack, bay, type, form; + moduleid_t m; + char c; + + if (strstr(buffer, EDGE_LBL_RACK "/") == buffer) { + form = MODULE_FORMAT_LONG; + buffer += strlen(EDGE_LBL_RACK "/"); + + /* A long module ID must be exactly 5 non-template chars. */ + if (strlen(buffer) != strlen("/" EDGE_LBL_RPOS "/") + 5) + return -1; + } + else { + form = MODULE_FORMAT_BRIEF; + + /* A brief module id must be exactly 6 characters */ + if (strlen(buffer) != 6) + return -2; + } + + /* The rack number must be exactly 3 digits */ + if (!(isdigit(buffer[0]) && isdigit(buffer[1]) && isdigit(buffer[2]))) + return -3; + + rack = 0; + v = *buffer++ - '0'; + if (v > RACK_CLASS_MASK(rack) >> RACK_CLASS_SHFT(rack)) + return -4; + RACK_ADD_CLASS(rack, v); + + v = *buffer++ - '0'; + if (v > RACK_GROUP_MASK(rack) >> RACK_GROUP_SHFT(rack)) + return -5; + RACK_ADD_GROUP(rack, v); + + v = *buffer++ - '0'; + /* rack numbers are 1-based */ + if (v-1 > RACK_NUM_MASK(rack) >> RACK_NUM_SHFT(rack)) + return -6; + RACK_ADD_NUM(rack, v); + + if (form == MODULE_FORMAT_BRIEF) { + /* Next should be a module type character. Accept ucase or lcase. */ + c = *buffer++; + if (!isalpha(c)) + return -7; + + /* strchr() returns a pointer into brick_types[], or NULL */ + type = (unsigned int)(strchr(brick_types, tolower(c)) - brick_types); + if (type > MODULE_BTYPE_MASK >> MODULE_BTYPE_SHFT) + return -8; + } + else { + /* Hardcode the module type, and skip over the boilerplate */ + type = MODULE_CBRICK; + + if (strstr(buffer, "/" EDGE_LBL_RPOS "/") != buffer) + return -9; + + buffer += strlen("/" EDGE_LBL_RPOS "/"); + } + + /* The bay number is last. Make sure it's exactly two digits */ + + if (!(isdigit(buffer[0]) && isdigit(buffer[1]) && !buffer[2])) + return -10; + + bay = 10 * (buffer[0] - '0') + (buffer[1] - '0'); + + if (bay > MODULE_BPOS_MASK >> MODULE_BPOS_SHFT) + return -11; + + m = RBT_TO_MODULE(rack, bay, type); + + /* avoid sign extending the moduleid_t */ + return (int)(unsigned short)m; +} + +#else /* CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 */ + +/* + * Format a module id for printing. + */ +void +format_module_id(char *buffer, moduleid_t m, int fmt) +{ + if (fmt == MODULE_FORMAT_BRIEF) { + sprintf(buffer, "%d", m); + } + else if (fmt == MODULE_FORMAT_LONG) { + sprintf(buffer, EDGE_LBL_MODULE "/%d", m); + } +} + +/* + * Parse a module id, in either brief or long form. + * Returns < 0 on error. + */ +int +parse_module_id(char *buffer) +{ + moduleid_t m; + char c; + + if (strstr(buffer, EDGE_LBL_MODULE "/") == buffer) + buffer += strlen(EDGE_LBL_MODULE "/"); + + m = 0; + while(c = *buffer++) { + if (!isdigit(c)) + return -1; + m = 10 * m + (c - '0'); + } + + /* avoid sign extending the moduleid_t */ + return (int)(unsigned short)m; +} + +#endif /* CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 */ + + diff -urN linux-2.4.0-test10/arch/ia64/sn/io/klgraph.c linux-2.4.0-test10-lia/arch/ia64/sn/io/klgraph.c --- linux-2.4.0-test10/arch/ia64/sn/io/klgraph.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/klgraph.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,1088 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +/* + * klgraph.c- + * This file specifies the interface between the kernel and the PROM's + * configuration data structures. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#ifdef CONFIG_IA64_SGI_IO +#include +#endif +#include +#include +#include +#include +#include + +#define KLGRAPH_DEBUG 1 +#ifdef KLGRAPH_DEBUG +#define GRPRINTF(x) printk x +#define CE_GRPANIC CE_PANIC +#else +#define GRPRINTF(x) +#define CE_GRPANIC CE_PANIC +#endif + +#include + +extern char arg_maxnodes[]; +extern int maxnodes; + +#ifndef BRINGUP +/* + * Gets reason for diagval using table lookup. + */ +static char* +get_diag_string(uint diagcode) +{ + int num_entries; + int i; + num_entries = sizeof(diagval_map) / sizeof(diagval_t); + for (i = 0; i < num_entries; i++){ + if ((unchar)diagval_map[i].dv_code == (unchar)diagcode) + return diagval_map[i].dv_msg; + } + return "Unknown"; +} + +#endif /* ndef BRINGUP */ + + +/* + * Support for verbose inventory via hardware graph. + * klhwg_invent_alloc allocates the necessary size of inventory information + * and fills in the generic information. + */ +invent_generic_t * +klhwg_invent_alloc(cnodeid_t cnode, int class, int size) +{ + invent_generic_t *invent; + + invent = kern_malloc(size); + if (!invent) return NULL; + + invent->ig_module = NODE_MODULEID(cnode); + invent->ig_slot = SLOTNUM_GETSLOT(NODE_SLOTID(cnode)); + invent->ig_invclass = class; + + return invent; +} + +/* + * Add information about the baseio prom version number + * as a part of detailed inventory info in the hwgraph. + */ +void +klhwg_baseio_inventory_add(devfs_handle_t baseio_vhdl,cnodeid_t cnode) +{ + invent_miscinfo_t *baseio_inventory; + unsigned char version = 0,revision = 0; + + /* Allocate memory for the "detailed inventory" info + * for the baseio + */ + baseio_inventory = (invent_miscinfo_t *) + klhwg_invent_alloc(cnode, INV_PROM, sizeof(invent_miscinfo_t)); + baseio_inventory->im_type = INV_IO6PROM; + /* Read the io6prom revision from the nvram */ +#ifndef CONFIG_IA64_SGI_IO + nvram_prom_version_get(&version,&revision); +#endif + /* Store the revision info in the inventory */ + baseio_inventory->im_version = version; + baseio_inventory->im_rev = revision; + /* Put the inventory info in the hardware graph */ + hwgraph_info_add_LBL(baseio_vhdl, INFO_LBL_DETAIL_INVENT, + (arbitrary_info_t) baseio_inventory); + /* Make the information available to the user programs + * thru hwgfs. + */ + hwgraph_info_export_LBL(baseio_vhdl, INFO_LBL_DETAIL_INVENT, + sizeof(invent_miscinfo_t)); +} + +char *hub_rev[] = { + "0.0", + "1.0", + "2.0", + "2.1", + "2.2", + "2.3" +}; + +/* + * Add detailed cpu inventory info to the hardware graph. + */ +void +klhwg_hub_invent_info(devfs_handle_t hubv, + cnodeid_t cnode, + klhub_t *hub) +{ + invent_miscinfo_t *hub_invent; +#if defined (CONFIG_SGI_IP27) + extern int maxcpus; +#endif + + hub_invent = (invent_miscinfo_t *) + klhwg_invent_alloc(cnode, INV_MISC, sizeof(invent_miscinfo_t)); + if (!hub_invent) + return; + + if (KLCONFIG_INFO_ENABLED((klinfo_t *)hub)) + hub_invent->im_gen.ig_flag = INVENT_ENABLED; + + hub_invent->im_type = INV_HUB; + hub_invent->im_rev = hub->hub_info.revision; + hub_invent->im_speed = hub->hub_speed; +#if defined (CONFIG_SGI_IP27) /* SN0 specific */ + if (hub_invent->im_rev < HUB_REV_2_1) +#ifdef SUPPORT_PRINTING_V_FORMAT + cmn_err(CE_WARN, + "INVALID CUSTOMER CONFIGURATION - " + "DOWNREV Hub ASIC: rev %s (code=%d) at %v.", + hub_rev[hub_invent->im_rev], + hub_invent->im_rev, hubv); +#else + cmn_err(CE_WARN, + "INVALID CUSTOMER CONFIGURATION - " + "DOWNREV Hub ASIC: rev %s (code=%d) at 0x%x.", + hub_rev[hub_invent->im_rev], + hub_invent->im_rev, &hubv); +#endif + + if ((hub_invent->im_rev < HUB_REV_2_3) && (maxcpus > 32)) +#ifdef SUPPORT_PRINTING_V_FORMAT + cmn_err(CE_WARN, + "INVALID CUSTOMER CONFIGURATION - All Hub ASICs need to " + "be at least rev 2.3 for configurations exceeding 32 CPUs." + "\n\tDOWNREV Hub ASIC: rev %s (code=%d) at %v.", + hub_rev[hub_invent->im_rev], + hub_invent->im_rev, hubv); +#else + cmn_err(CE_WARN, + "INVALID CUSTOMER CONFIGURATION - All Hub ASICs need to " + "be at least rev 2.3 for configurations exceeding 32 CPUs." + "\n\tDOWNREV Hub ASIC: rev %s (code=%d) at 0x%x.", + hub_rev[hub_invent->im_rev], + hub_invent->im_rev, &hubv); +#endif +#endif /* SN0 specific */ + + hwgraph_info_add_LBL(hubv, INFO_LBL_DETAIL_INVENT, + (arbitrary_info_t) hub_invent); + hwgraph_info_export_LBL(hubv, INFO_LBL_DETAIL_INVENT, + sizeof(invent_miscinfo_t)); +} + +/* ARGSUSED */ +void +klhwg_add_hub(devfs_handle_t node_vertex, klhub_t *hub, cnodeid_t cnode) +{ + devfs_handle_t myhubv; + int rc; + + GRPRINTF(("klhwg_add_hub: adding %s\n", EDGE_LBL_HUB)); + + (void) hwgraph_path_add(node_vertex, EDGE_LBL_HUB, &myhubv); + rc = device_master_set(myhubv, node_vertex); + +#ifndef CONFIG_IA64_SGI_IO + /* + * Activate when we support hub stats. + */ + rc = hwgraph_info_add_LBL(myhubv, INFO_LBL_HUB_INFO, + (arbitrary_info_t)(&NODEPDA(cnode)->hubstats)); +#endif + + if (rc != GRAPH_SUCCESS) { + cmn_err(CE_WARN, + "klhwg_add_hub: Can't add hub info label 0x%p, code %d", + myhubv, rc); + } + + klhwg_hub_invent_info(myhubv, cnode, hub); + +#ifndef BRINGUP + init_hub_stats(cnode, NODEPDA(cnode)); +#endif /* ndef BRINGUP */ + +#ifndef CONFIG_IA64_SGI_IO + sndrv_attach(myhubv); +#else + /* + * Need to call our driver to do the attach? + */ + printk("klhwg_add_hub: Need to add code to do the attach.\n"); +#endif +} + +#ifndef BRINGUP + +void +klhwg_add_rps(devfs_handle_t node_vertex, cnodeid_t cnode, int flag) +{ + devfs_handle_t myrpsv; + invent_rpsinfo_t *rps_invent; + int rc; + + if(cnode == CNODEID_NONE) + return; + + GRPRINTF(("klhwg_add_rps: adding %s to vertex 0x%x\n", EDGE_LBL_RPS, + node_vertex)); + + rc = hwgraph_path_add(node_vertex, EDGE_LBL_RPS, &myrpsv); + if (rc != GRAPH_SUCCESS) + return; + + device_master_set(myrpsv, node_vertex); + + rps_invent = (invent_rpsinfo_t *) + klhwg_invent_alloc(cnode, INV_RPS, sizeof(invent_rpsinfo_t)); + + if (!rps_invent) + return; + + rps_invent->ir_xbox = 0; /* not an xbox RPS */ + + if (flag) + rps_invent->ir_gen.ig_flag = INVENT_ENABLED; + else + rps_invent->ir_gen.ig_flag = 0x0; + + hwgraph_info_add_LBL(myrpsv, INFO_LBL_DETAIL_INVENT, + (arbitrary_info_t) rps_invent); + hwgraph_info_export_LBL(myrpsv, INFO_LBL_DETAIL_INVENT, + sizeof(invent_rpsinfo_t)); + +} + +/* + * klhwg_update_rps gets invoked when the system controller sends an + * interrupt indicating the power supply has lost/regained the redundancy. + * It's responsible for updating the Hardware graph information. + * rps_state = 0 -> if the rps lost the redundancy + * = 1 -> If it is redundant. + */ +void +klhwg_update_rps(cnodeid_t cnode, int rps_state) +{ + devfs_handle_t node_vertex; + devfs_handle_t rpsv; + invent_rpsinfo_t *rps_invent; + int rc; + if(cnode == CNODEID_NONE) + return; + + node_vertex = cnodeid_to_vertex(cnode); + rc = hwgraph_edge_get(node_vertex, EDGE_LBL_RPS, &rpsv); + if (rc != GRAPH_SUCCESS) { + return; + } + + rc = hwgraph_info_get_LBL(rpsv, INFO_LBL_DETAIL_INVENT, + (arbitrary_info_t *)&rps_invent); + if (rc != GRAPH_SUCCESS) { + return; + } + + if (rps_state == 0 ) + rps_invent->ir_gen.ig_flag = 0; + else + rps_invent->ir_gen.ig_flag = INVENT_ENABLED; +} + +void +klhwg_add_xbox_rps(devfs_handle_t node_vertex, cnodeid_t cnode, int flag) +{ + devfs_handle_t myrpsv; + invent_rpsinfo_t *rps_invent; + int rc; + + if(cnode == CNODEID_NONE) + return; + + GRPRINTF(("klhwg_add_rps: adding %s to vertex 0x%x\n", + EDGE_LBL_XBOX_RPS, node_vertex)); + + rc = hwgraph_path_add(node_vertex, EDGE_LBL_XBOX_RPS, &myrpsv); + if (rc != GRAPH_SUCCESS) + return; + + device_master_set(myrpsv, node_vertex); + + rps_invent = (invent_rpsinfo_t *) + klhwg_invent_alloc(cnode, INV_RPS, sizeof(invent_rpsinfo_t)); + + if (!rps_invent) + return; + + rps_invent->ir_xbox = 1; /* xbox RPS */ + + if (flag) + rps_invent->ir_gen.ig_flag = INVENT_ENABLED; + else + rps_invent->ir_gen.ig_flag = 0x0; + + hwgraph_info_add_LBL(myrpsv, INFO_LBL_DETAIL_INVENT, + (arbitrary_info_t) rps_invent); + hwgraph_info_export_LBL(myrpsv, INFO_LBL_DETAIL_INVENT, + sizeof(invent_rpsinfo_t)); + +} + +/* + * klhwg_update_xbox_rps gets invoked when the xbox system controller + * polls the status register and discovers that the power supply has + * lost/regained the redundancy. + * It's responsible for updating the Hardware graph information. + * rps_state = 0 -> if the rps lost the redundancy + * = 1 -> If it is redundant. + */ +void +klhwg_update_xbox_rps(cnodeid_t cnode, int rps_state) +{ + devfs_handle_t node_vertex; + devfs_handle_t rpsv; + invent_rpsinfo_t *rps_invent; + int rc; + if(cnode == CNODEID_NONE) + return; + + node_vertex = cnodeid_to_vertex(cnode); + rc = hwgraph_edge_get(node_vertex, EDGE_LBL_XBOX_RPS, &rpsv); + if (rc != GRAPH_SUCCESS) { + return; + } + + rc = hwgraph_info_get_LBL(rpsv, INFO_LBL_DETAIL_INVENT, + (arbitrary_info_t *)&rps_invent); + if (rc != GRAPH_SUCCESS) { + return; + } + + if (rps_state == 0 ) + rps_invent->ir_gen.ig_flag = 0; + else + rps_invent->ir_gen.ig_flag = INVENT_ENABLED; +} + +#endif /* ndef BRINGUP */ + +void +klhwg_add_xbow(cnodeid_t cnode, nasid_t nasid) +{ + lboard_t *brd; + klxbow_t *xbow_p; + nasid_t hub_nasid; + cnodeid_t hub_cnode; + int widgetnum; + devfs_handle_t xbow_v, hubv; + /*REFERENCED*/ + graph_error_t err; + +#if CONFIG_SGI_IP27 + if ((brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), + KLTYPE_MIDPLANE8)) == NULL) + return; +#elif CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 || defined(CONFIG_IA64_GENERIC) + if ((brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), + KLTYPE_PBRICK_XBOW)) == NULL) + return; +#endif + + if (KL_CONFIG_DUPLICATE_BOARD(brd)) + return; + + GRPRINTF(("klhwg_add_xbow: adding cnode %d nasid %d xbow edges\n", + cnode, nasid)); + + if ((xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW)) + == NULL) + return; + +#ifndef CONFIG_IA64_SGI_IO + /* + * We cannot support this function in devfs .. see below where + * we use hwgraph_path_add() to create this vertex with a known + * name. + */ + err = hwgraph_vertex_create(&xbow_v); + ASSERT(err == GRAPH_SUCCESS); + + xswitch_vertex_init(xbow_v); +#endif /* !CONFIG_IA64_SGI_IO */ + + for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) { + if (!XBOW_PORT_TYPE_HUB(xbow_p, widgetnum)) + continue; + + hub_nasid = XBOW_PORT_NASID(xbow_p, widgetnum); + printk("klhwg_add_xbow: Found xbow port type hub hub_nasid %d widgetnum %d\n", hub_nasid, widgetnum); + if (hub_nasid == INVALID_NASID) { + cmn_err(CE_WARN, "hub widget %d, skipping xbow graph\n", widgetnum); + continue; + } + +#ifdef CONFIG_SGI_IP27 + /* + * This code makes no sense for IP35. + */ + (void)hwgraph_info_add_LBL(xbow_v, INFO_LBL_XSWITCH_ID, + (arbitrary_info_t)hub_slot_to_crossbow(NODEPDA(cnode)->slotdesc)); +#endif /* CONFIG_SGI_IP27 */ + hub_cnode = NASID_TO_COMPACT_NODEID(hub_nasid); + printk("klhwg_add_xbow: cnode %d cnode %d\n", nasid_to_compact_node[0], nasid_to_compact_node[1]); + + if (is_specified(arg_maxnodes) && hub_cnode == INVALID_CNODEID) { + continue; + } + + hubv = cnodeid_to_vertex(hub_cnode); + +#ifdef CONFIG_IA64_SGI_IO + printk("klhwg_add_xbow: Hub Vertex found = %p hub_cnode %d\n", hubv, hub_cnode); + err = hwgraph_path_add(hubv, EDGE_LBL_XTALK, &xbow_v); + if (err != GRAPH_SUCCESS) { + if (err == GRAPH_DUP) + cmn_err(CE_WARN, "klhwg_add_xbow: Check for " + "working routers and router links!"); + + cmn_err(CE_GRPANIC, "klhwg_add_xbow: Failed to add " + "edge: vertex 0x%p (0x%p) to vertex 0x%p (0x%p)," + "error %d\n", + hubv, hubv, xbow_v, xbow_v, err); + } + xswitch_vertex_init(xbow_v); +#endif + + NODEPDA(hub_cnode)->xbow_vhdl = xbow_v; + + /* + * XXX - This won't work is we ever hook up two hubs + * by crosstown through a crossbow. + */ + if (hub_nasid != nasid) { + NODEPDA(hub_cnode)->xbow_peer = nasid; + NODEPDA(NASID_TO_COMPACT_NODEID(nasid))->xbow_peer = + hub_nasid; + } + + GRPRINTF(("klhwg_add_xbow: adding port nasid %d %s to vertex 0x%p\n", + hub_nasid, EDGE_LBL_XTALK, hubv)); + +#ifndef CONFIG_IA64_SGI_IO + err = hwgraph_edge_add(hubv, xbow_v, EDGE_LBL_XTALK); + if (err != GRAPH_SUCCESS) { + if (err == GRAPH_DUP) + cmn_err(CE_WARN, "klhwg_add_xbow: Check for " + "working routers and router links!"); + + cmn_err(CE_GRPANIC, "klhwg_add_xbow: Failed to add " + "edge: vertex 0x%p (0x%p) to vertex 0x%p (0x%p), " + "error %d\n", + hubv, hubv, xbow_v, xbow_v, err); + } +#endif + } +} + + +/* ARGSUSED */ +void +klhwg_add_node(devfs_handle_t hwgraph_root, cnodeid_t cnode, gda_t *gdap) +{ + nasid_t nasid; + lboard_t *brd; + klhub_t *hub; + devfs_handle_t node_vertex = NULL; + char path_buffer[100]; + int rv; + char *s; + int board_disabled = 0; + + nasid = COMPACT_TO_NASID_NODEID(cnode); + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27); + GRPRINTF(("klhwg_add_node: Adding cnode %d, nasid %d, brd 0x%p\n", + cnode, nasid, brd)); + ASSERT(brd); + + do { + + /* Generate a hardware graph path for this board. */ + board_to_path(brd, path_buffer); + + GRPRINTF(("klhwg_add_node: adding %s to vertex 0x%p\n", + path_buffer, hwgraph_root)); + rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex); + + printk("klhwg_add_node: rv = %d graph success %d node_vertex 0x%p\n", rv, GRAPH_SUCCESS, node_vertex); + if (rv != GRAPH_SUCCESS) + cmn_err(CE_PANIC, "Node vertex creation failed. " + "Path == %s", + path_buffer); + + hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB); + ASSERT(hub); + if(hub->hub_info.flags & KLINFO_ENABLE) + board_disabled = 0; + else + board_disabled = 1; + + if(!board_disabled) { + mark_nodevertex_as_node(node_vertex, + cnode + board_disabled * numnodes); + printk("klhwg_add_node: node_vertex %p, cnode %d numnodes %d\n", node_vertex, cnode, numnodes); + + s = dev_to_name(node_vertex, path_buffer, sizeof(path_buffer)); + printk("klhwg_add_node: s %s\n", s); + + NODEPDA(cnode)->hwg_node_name = + kmalloc(strlen(s) + 1, + GFP_KERNEL); + ASSERT_ALWAYS(NODEPDA(cnode)->hwg_node_name != NULL); + strcpy(NODEPDA(cnode)->hwg_node_name, s); + + hubinfo_set(node_vertex, NODEPDA(cnode)->pdinfo); + + /* Set up node board's slot */ + NODEPDA(cnode)->slotdesc = brd->brd_slot; + + /* Set up the module we're in */ + NODEPDA(cnode)->module_id = brd->brd_module; + NODEPDA(cnode)->module = module_lookup(brd->brd_module); + } + + if(!board_disabled) + klhwg_add_hub(node_vertex, hub, cnode); + + brd = KLCF_NEXT(brd); + if (brd) + brd = find_lboard(brd, KLTYPE_IP27); + else + break; + } while(brd); +} + + +/* ARGSUSED */ +void +klhwg_add_all_routers(devfs_handle_t hwgraph_root) +{ + nasid_t nasid; + cnodeid_t cnode; + lboard_t *brd; + devfs_handle_t node_vertex; + char path_buffer[100]; +#ifdef CONFIG_SGI_IP27 + lboard_t *node_brd; + klhub_t *hub; + int i, pn; + char *nic_info, *c; + char sname[32]; + klrou_t *rou; +#endif + int rv; + + for (cnode = 0; cnode < maxnodes; cnode++) { + nasid = COMPACT_TO_NASID_NODEID(cnode); + + GRPRINTF(("klhwg_add_all_routers: adding router on cnode %d\n", + cnode)); + + brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid), + KLTYPE_ROUTER); + + if (!brd) + /* No routers stored in this node's memory */ + continue; + + do { + ASSERT(brd); + GRPRINTF(("Router board struct is %p\n", brd)); + + /* Don't add duplicate boards. */ + if (brd->brd_flags & DUPLICATE_BOARD) + continue; + +#ifdef CONFIG_SGI_IP27 + nasid = COMPACT_TO_NASID_NODEID(cnode); + /* with IP31 boards, routers with part numbers + * 030-0841-002 and down do not work well. We + * need to warn users about that */ + rou = (klrou_t *)find_component(brd, NULL, KLSTRUCT_ROU); + pn = 3; + if(rou) { + if(rou->rou_mfg_nic != NULL) + { + nic_info = (char *)NODE_OFFSET_TO_K1(nasid, rou->rou_mfg_nic); + if(nic_info && (c = strstr(nic_info,"Part"))) + { + if(strstr(c,"030-0841")) /* current router's part number */ + { + c+= 14; + pn = atoi(c); + } + } + else { +#ifdef SUPPORT_PRINTING_M_FORMAT + cmn_err(CE_WARN, "Cannot read router nic in module %M, slot r%d\n", brd->brd_module, SLOTNUM_GETSLOT(brd->brd_slot)); +#else + cmn_err(CE_WARN, "Cannot read router nic in module %d, slot r%d\n", brd->brd_module, SLOTNUM_GETSLOT(brd->brd_slot)); +#endif + } + } + for(i=1; i<=MAX_ROUTER_PORTS; i++) + { + if(rou->rou_port[i].port_nasid != INVALID_NASID) + { + node_brd = (lboard_t *)NODE_OFFSET_TO_K1(rou->rou_port[i].port_nasid, rou->rou_port[i].port_offset); + if(!node_brd || node_brd->brd_type != KLTYPE_IP27) + continue; + hub = (klhub_t *)find_first_component(node_brd, KLSTRUCT_HUB); + if (hub && (KLCONFIG_INFO_ENABLED(&hub->hub_info))) + { + if(hub->hub_speed == 100 * 1000000 && pn <= 2) + { + get_slotname(brd->brd_slot, sname); +#ifdef SUPPORT_PRINTING_M_FORMAT + cmn_err(CE_WARN, "downrev router board in module %M slot %s\n", brd->brd_module, sname); +#else + cmn_err(CE_WARN, "downrev router board in module %d slot %s\n", brd->brd_module, sname); +#endif + } + + } + } + } + + } +#endif /* CONFIG_SGI_IP27 */ + GRPRINTF(("Router 0x%p module number is %d\n", brd, brd->brd_module)); + /* Generate a hardware graph path for this board. */ + board_to_path(brd, path_buffer); + + GRPRINTF(("Router path is %s\n", path_buffer)); + + /* Add the router */ + GRPRINTF(("klhwg_add_all_routers: adding %s to vertex 0x%p\n", + path_buffer, hwgraph_root)); + rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex); + + if (rv != GRAPH_SUCCESS) + cmn_err(CE_PANIC, "Router vertex creation " + "failed. Path == %s", + path_buffer); + + GRPRINTF(("klhwg_add_all_routers: get next board from 0x%p\n", + brd)); + /* Find the rest of the routers stored on this node. */ + } while ( (brd = find_lboard_class(KLCF_NEXT(brd), + KLTYPE_ROUTER)) ); + + GRPRINTF(("klhwg_add_all_routers: Done.\n")); + } + +} + +/* ARGSUSED */ +void +klhwg_connect_one_router(devfs_handle_t hwgraph_root, lboard_t *brd, + cnodeid_t cnode, nasid_t nasid) +{ + klrou_t *router; + char path_buffer[50]; + char dest_path[50]; + devfs_handle_t router_hndl; + devfs_handle_t dest_hndl; + int rc; + int port; + lboard_t *dest_brd; + + GRPRINTF(("klhwg_connect_one_router: Connecting router on cnode %d\n", + cnode)); + + /* Don't add duplicate boards. */ + if (brd->brd_flags & DUPLICATE_BOARD) { + GRPRINTF(("klhwg_connect_one_router: Duplicate router 0x%p on cnode %d\n", + brd, cnode)); + return; + } + + /* Generate a hardware graph path for this board. */ + board_to_path(brd, path_buffer); + + rc = hwgraph_traverse(hwgraph_root, path_buffer, &router_hndl); + + if (rc != GRAPH_SUCCESS && is_specified(arg_maxnodes)) + return; + + if (rc != GRAPH_SUCCESS) + cmn_err(CE_WARN, "Can't find router: %s", path_buffer); + + /* We don't know what to do with multiple router components */ + if (brd->brd_numcompts != 1) { + cmn_err(CE_PANIC, + "klhwg_connect_one_router: %d cmpts on router\n", + brd->brd_numcompts); + return; + } + + + /* Convert component 0 to klrou_t ptr */ + router = (klrou_t *)NODE_OFFSET_TO_K1(NASID_GET(brd), + brd->brd_compts[0]); + + for (port = 1; port <= MAX_ROUTER_PORTS; port++) { + /* See if the port's active */ + if (router->rou_port[port].port_nasid == INVALID_NASID) { + GRPRINTF(("klhwg_connect_one_router: port %d inactive.\n", + port)); + continue; + } + if (is_specified(arg_maxnodes) && NASID_TO_COMPACT_NODEID(router->rou_port[port].port_nasid) + == INVALID_CNODEID) { + continue; + } + + dest_brd = (lboard_t *)NODE_OFFSET_TO_K1( + router->rou_port[port].port_nasid, + router->rou_port[port].port_offset); + + /* Generate a hardware graph path for this board. */ + board_to_path(dest_brd, dest_path); + + rc = hwgraph_traverse(hwgraph_root, dest_path, &dest_hndl); + + if (rc != GRAPH_SUCCESS) { + if (is_specified(arg_maxnodes) && KL_CONFIG_DUPLICATE_BOARD(dest_brd)) + continue; + cmn_err(CE_PANIC, "Can't find router: %s", dest_path); + } + GRPRINTF(("klhwg_connect_one_router: Link from %s/%d to %s\n", + path_buffer, port, dest_path)); + + sprintf(dest_path, "%d", port); + + rc = hwgraph_edge_add(router_hndl, dest_hndl, dest_path); + + if (rc == GRAPH_DUP) { + GRPRINTF(("Skipping port %d. nasid %d %s/%s\n", + port, router->rou_port[port].port_nasid, + path_buffer, dest_path)); + continue; + } + + if (rc != GRAPH_SUCCESS && !is_specified(arg_maxnodes)) + cmn_err(CE_GRPANIC, "Can't create edge: %s/%s to vertex 0x%p error 0x%x\n", + path_buffer, dest_path, dest_hndl, rc); + + } +} + + +void +klhwg_connect_routers(devfs_handle_t hwgraph_root) +{ + nasid_t nasid; + cnodeid_t cnode; + lboard_t *brd; + + for (cnode = 0; cnode < maxnodes; cnode++) { + nasid = COMPACT_TO_NASID_NODEID(cnode); + + GRPRINTF(("klhwg_connect_routers: Connecting routers on cnode %d\n", + cnode)); + + brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid), + KLTYPE_ROUTER); + + if (!brd) + continue; + + do { + + nasid = COMPACT_TO_NASID_NODEID(cnode); + + klhwg_connect_one_router(hwgraph_root, brd, + cnode, nasid); + + /* Find the rest of the routers stored on this node. */ + } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) ); + } +} + + + +void +klhwg_connect_hubs(devfs_handle_t hwgraph_root) +{ + nasid_t nasid; + cnodeid_t cnode; + lboard_t *brd; + klhub_t *hub; + lboard_t *dest_brd; + devfs_handle_t hub_hndl; + devfs_handle_t dest_hndl; + char path_buffer[50]; + char dest_path[50]; + graph_error_t rc; + + for (cnode = 0; cnode < maxnodes; cnode++) { + nasid = COMPACT_TO_NASID_NODEID(cnode); + + GRPRINTF(("klhwg_connect_hubs: Connecting hubs on cnode %d\n", + cnode)); + + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), + KLTYPE_IP27); + ASSERT(brd); + + hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB); + ASSERT(hub); + + /* See if the port's active */ + if (hub->hub_port.port_nasid == INVALID_NASID) { + GRPRINTF(("klhwg_connect_hubs: port inactive.\n")); + continue; + } + + if (is_specified(arg_maxnodes) && NASID_TO_COMPACT_NODEID(hub->hub_port.port_nasid) == INVALID_CNODEID) + continue; + + /* Generate a hardware graph path for this board. */ + board_to_path(brd, path_buffer); + + GRPRINTF(("klhwg_connect_hubs: Hub path is %s.\n", path_buffer)); + rc = hwgraph_traverse(hwgraph_root, path_buffer, &hub_hndl); + + if (rc != GRAPH_SUCCESS) + cmn_err(CE_WARN, "Can't find hub: %s", path_buffer); + + dest_brd = (lboard_t *)NODE_OFFSET_TO_K1( + hub->hub_port.port_nasid, + hub->hub_port.port_offset); + + /* Generate a hardware graph path for this board. */ + board_to_path(dest_brd, dest_path); + + rc = hwgraph_traverse(hwgraph_root, dest_path, &dest_hndl); + + if (rc != GRAPH_SUCCESS) { + if (is_specified(arg_maxnodes) && KL_CONFIG_DUPLICATE_BOARD(dest_brd)) + continue; + cmn_err(CE_PANIC, "Can't find board: %s", dest_path); + } else { + + + GRPRINTF(("klhwg_connect_hubs: Link from %s to %s.\n", + path_buffer, dest_path)); + + rc = hwgraph_edge_add(hub_hndl, dest_hndl, EDGE_LBL_INTERCONNECT); + + if (rc != GRAPH_SUCCESS) + cmn_err(CE_GRPANIC, "Can't create edge: %s/%s to vertex 0x%p, error 0x%x\n", + path_buffer, dest_path, dest_hndl, rc); + + } + } +} + +/* Store the pci/vme disabled board information as extended administrative + * hints which can later be used by the drivers using the device/driver + * admin interface. + */ +void +klhwg_device_disable_hints_add(void) +{ + cnodeid_t cnode; /* node we are looking at */ + nasid_t nasid; /* nasid of the node */ + lboard_t *board; /* board we are looking at */ + int comp_index; /* component index */ + klinfo_t *component; /* component in the board we are + * looking at + */ + char device_name[MAXDEVNAME]; + +#ifndef CONFIG_IA64_SGI_IO + device_admin_table_init(); +#endif + for(cnode = 0; cnode < numnodes; cnode++) { + nasid = COMPACT_TO_NASID_NODEID(cnode); + board = (lboard_t *)KL_CONFIG_INFO(nasid); + /* Check out all the board info stored on a node */ + while(board) { + /* No need to look at duplicate boards or non-io + * boards + */ + if (KL_CONFIG_DUPLICATE_BOARD(board) || + KLCLASS(board->brd_type) != KLCLASS_IO) { + board = KLCF_NEXT(board); + continue; + } + /* Check out all the components of a board */ + for (comp_index = 0; + comp_index < KLCF_NUM_COMPS(board); + comp_index++) { + component = KLCF_COMP(board,comp_index); + /* If the component is enabled move on to + * the next component + */ + if (KLCONFIG_INFO_ENABLED(component)) + continue; + /* NOTE : Since the prom only supports + * the disabling of pci devices the following + * piece of code makes sense. + * Make sure that this assumption is valid + */ + /* This component is disabled. Store this + * hint in the extended device admin table + */ + /* Get the canonical name of the pci device */ + device_component_canonical_name_get(board, + component, + device_name); +#ifndef CONFIG_IA64_SGI_IO + device_admin_table_update(device_name, + ADMIN_LBL_DISABLED, + "yes"); +#endif +#ifdef DEBUG + printf("%s DISABLED\n",device_name); +#endif + } + /* go to the next board info stored on this + * node + */ + board = KLCF_NEXT(board); + } + } +} + +void +klhwg_add_all_modules(devfs_handle_t hwgraph_root) +{ + cmoduleid_t cm; + char name[128]; + devfs_handle_t vhdl; + int rc; + + /* Add devices under each module */ + + for (cm = 0; cm < nummodules; cm++) { + /* Use module as module vertex fastinfo */ + + sprintf(name, EDGE_LBL_MODULE "/%x", modules[cm]->id); + + rc = hwgraph_path_add(hwgraph_root, name, &vhdl); + ASSERT(rc == GRAPH_SUCCESS); + rc = rc; + + hwgraph_fastinfo_set(vhdl, (arbitrary_info_t) modules[cm]); + + /* Add system controller */ + + sprintf(name, +#if defined(CONFIG_SGI_IP27) +#ifdef SUPPORT_PRINTING_M_FORMAT + EDGE_LBL_MODULE "/%M/" EDGE_LBL_ELSC, +#else + EDGE_LBL_MODULE "/%x/" EDGE_LBL_ELSC, +#endif /* SUPPORT_PRINTING_M_FORMAT */ +#else + EDGE_LBL_MODULE "/%x/" EDGE_LBL_L1, +#endif /* CONFIG_SGI_IP27 */ + modules[cm]->id); + + rc = hwgraph_path_add(hwgraph_root, name, &vhdl); + ASSERT_ALWAYS(rc == GRAPH_SUCCESS); + rc = rc; + + hwgraph_info_add_LBL(vhdl, + INFO_LBL_ELSC, + (arbitrary_info_t) (__psint_t) 1); + +#ifndef CONFIG_IA64_SGI_IO + sndrv_attach(vhdl); +#else + /* + * We need to call the drivers attach routine .. + */ + FIXME("klhwg_add_all_modules: Need code to call driver attach.\n"); +#endif + } +} + +void +klhwg_add_all_nodes(devfs_handle_t hwgraph_root) +{ + //gda_t *gdap = GDA; + gda_t *gdap; + cnodeid_t cnode; + +#ifdef SIMULATED_KLGRAPH + //gdap = 0xa800000000011000; + gdap = (gda_t *)0xe000000000011000; + printk("klhwg_add_all_nodes: SIMULATED_KLGRAPH FIXME: gdap= 0x%p\n", gdap); +#else + gdap = GDA; +#endif /* SIMULATED_KLGRAPH */ + for (cnode = 0; cnode < numnodes; cnode++) { + ASSERT(gdap->g_nasidtable[cnode] != INVALID_NASID); + klhwg_add_node(hwgraph_root, cnode, gdap); + } + + for (cnode = 0; cnode < numnodes; cnode++) { + ASSERT(gdap->g_nasidtable[cnode] != INVALID_NASID); + +#ifndef CONFIG_IA64_SGI_IO + klhwg_add_xbow(cnode, gdap->g_nasidtable[cnode]); +#else + printk("klhwg_add_all_nodes: Fix me by getting real nasid\n"); + klhwg_add_xbow(cnode, 0); +#endif + } + + /* + * As for router hardware inventory information, we set this + * up in router.c. + */ + + klhwg_add_all_routers(hwgraph_root); + klhwg_connect_routers(hwgraph_root); + klhwg_connect_hubs(hwgraph_root); + + /* Assign guardian nodes to each of the + * routers in the system. + */ + +#ifndef CONFIG_IA64_SGI_IO + router_guardians_set(hwgraph_root); +#endif + + /* Go through the entire system's klconfig + * to figure out which pci components have been disabled + */ + klhwg_device_disable_hints_add(); + +} diff -urN linux-2.4.0-test10/arch/ia64/sn/io/klgraph_hack.c linux-2.4.0-test10-lia/arch/ia64/sn/io/klgraph_hack.c --- linux-2.4.0-test10/arch/ia64/sn/io/klgraph_hack.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/klgraph_hack.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,834 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + + +/* + * This is a temporary file that statically initializes the expected + * initial klgraph information that is normally provided by prom. + */ + +#include +#include +#include +#include +#include +#include + +void * real_port; +void * real_io_base; +void * real_addr; + +kl_config_hdr_t *linux_klcfg; +char *BW0 = NULL; + +#ifdef BRINGUP +/* forward declarations */ +extern void dump_ii(void), dump_lb(void), dump_crossbow(void); +extern void clear_ii_error(void); +#endif /* BRINGUP */ + +void +simulated_BW0_init(void) +{ + + unsigned long *cnode0_hub; + unsigned long hub_widget = 0x1000000; + unsigned long hub_offset = 0x800000; + unsigned long hub_reg_base = 0; + extern void * vmalloc(unsigned long); + + memset(&nasid_to_compact_node[0], 0, sizeof(cnodeid_t) * MAX_NASIDS); + + BW0 = vmalloc(0x10000000); + if (BW0 == NULL) { + printk("Darn it .. cannot create space for Big Window 0\n"); + } + printk("BW0: Start Address %p\n", BW0); + + memset(BW0+(0x10000000 - 8), 0xf, 0x8); + + printk("BW0: Last WORD address %p has value 0x%lx\n", (char *)(BW0 +(0x10000000 - 8)), *(long *)(BW0 +(0x10000000 - 8))); + + printk("XWIDGET 8 Address = 0x%p\n", (unsigned long *)(NODE_SWIN_BASE(0, 8)) ); + + /* + * Do some HUB Register Hack .. + */ + hub_reg_base = (unsigned long)BW0 + hub_widget + hub_offset; + cnode0_hub = (unsigned long *)(hub_reg_base + IIO_WID); *cnode0_hub = 0x1c110049; + cnode0_hub = (unsigned long *)(hub_reg_base + IIO_WSTAT); *cnode0_hub = 0x0; + cnode0_hub = (unsigned long *)(hub_reg_base + IIO_WCR); *cnode0_hub = 0x401b; + printk("IIO_WCR address = 0x%p\n", cnode0_hub); + + cnode0_hub = (unsigned long *)(hub_reg_base + IIO_ILAPR); *cnode0_hub = 0xffffffffffffffff; + cnode0_hub = (unsigned long *)(hub_reg_base + IIO_ILAPO); *cnode0_hub = 0x0; + cnode0_hub = (unsigned long *)(hub_reg_base + IIO_IOWA); *cnode0_hub = 0xff01; + cnode0_hub = (unsigned long *)(hub_reg_base + IIO_IIWA); *cnode0_hub = 0xff01; + cnode0_hub = (unsigned long *)(hub_reg_base + IIO_IIDEM); *cnode0_hub = 0xffffffffffffffff; + cnode0_hub = (unsigned long *)(hub_reg_base + IIO_ILCSR); *cnode0_hub = 0x3fc03ff640a; + cnode0_hub = (unsigned long *)(hub_reg_base + IIO_ILLR); *cnode0_hub = 0x0; + cnode0_hub = (unsigned long *)(hub_reg_base + IIO_IIDSR); *cnode0_hub = 0x1000040; +#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) + cnode0_hub = (unsigned long *)(hub_reg_base + IIO_IGFX0); *cnode0_hub = 0x0; + cnode0_hub = (unsigned long *)(hub_reg_base + IIO_IGFX1); *cnode0_hub = 0x0; + cnode0_hub = (unsigned long *)(hub_reg_base + IIO_ISCR0); *cnode0_hub = 0x23d; + cnode0_hub = (unsigned long *)(hub_reg_base + IIO_ISCR1); *cnode0_hub = 0x0; +#endif /* CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 */ +} + +#define SYNERGY_WIDGET ((char *)0xc0000e0000000000) +#define SYNERGY_SWIZZLE ((char *)0xc0000e0000000400) +#define HUBREG ((char *)0xc0000a0001e00000) +#define WIDGET0 ((char *)0xc0000a0000000000) +#define WIDGET4 ((char *)0xc0000a0000000004) + +#define SYNERGY_WIDGET ((char *)0xc0000e0000000000) +#define SYNERGY_SWIZZLE ((char *)0xc0000e0000000400) +#define HUBREG ((char *)0xc0000a0001e00000) +#define WIDGET0 ((char *)0xc0000a0000000000) + +int test = 0; + +/* + * Hack to loop for test. + */ +void +test_io_regs(void) +{ + + uint32_t reg_32bits; + uint64_t reg_64bits; + + while (test) { + + reg_32bits = (uint32_t)(*(volatile uint32_t *) SYNERGY_WIDGET); + reg_64bits = (uint64_t) (*(volatile uint64_t *) SYNERGY_WIDGET); + + } + + printk("Synergy Widget Address = 0x%p, Value = 0x%lx\n", SYNERGY_WIDGET, (uint64_t)*(SYNERGY_WIDGET)); + + printk("Synergy swizzle Address = 0x%p, Value = 0x%lx\n", SYNERGY_SWIZZLE, (uint64_t)*(SYNERGY_SWIZZLE)); + printk("HUBREG Address = 0x%p, Value = 0x%lx\n", HUBREG, (uint64_t)*(HUBREG)); + printk("WIDGET0 Address = 0x%p, Value = 0x%lx\n", WIDGET0, (uint64_t)*(WIDGET0)); + printk("WIDGET4 Address = 0x%p, Value = 0x%x\n", WIDGET4, (uint32_t)*(WIDGET4)); + +} + +void +klgraph_hack_init(void) +{ + + kl_config_hdr_t *kl_hdr_ptr; + lboard_t *lb_ptr; + lboard_t *temp_ptr; + klhub_t *klhub_ptr; + klioc3_t *klioc3_ptr; + klbri_t *klbri_ptr; + klxbow_t *klxbow_ptr; + klinfo_t *klinfo_ptr; + klcomp_t *klcomp_ptr; + uint64_t *tmp; + volatile u32 *tmp32; + + /* Preset some values */ + /* Write IOERR clear to clear the CRAZY bit in the status */ + tmp = (uint64_t *)0xc0000a0001c001f8; *tmp = (uint64_t)0xffffffff; + /* set widget control register...setting bedrock widget id to b */ + tmp = (uint64_t *)0xc0000a0001c00020; *tmp = (uint64_t)0x801b; + /* set io outbound widget access...allow all */ + tmp = (uint64_t *)0xc0000a0001c00110; *tmp = (uint64_t)0xff01; + /* set io inbound widget access...allow all */ + tmp = (uint64_t *)0xc0000a0001c00118; *tmp = (uint64_t)0xff01; + /* set io crb timeout to max */ + tmp = (uint64_t *)0xc0000a0001c003c0; *tmp = (uint64_t)0xffffff; + tmp = (uint64_t *)0xc0000a0001c003c0; *tmp = (uint64_t)0xffffff; + + /* set local block io permission...allow all */ + tmp = (uint64_t *)0xc0000a0001e04010; *tmp = (uint64_t)0xfffffffffffffff; + + /* clear any errors */ + clear_ii_error(); + + /* set default read response buffers in bridge */ + tmp32 = (volatile u32 *)0xc0000a000f000280L; + *tmp32 = 0xba98; + tmp32 = (volatile u32 *)0xc0000a000f000288L; + *tmp32 = 0xba98; + +printk("Widget ID Address 0x%p Value 0x%lx\n", (uint64_t *)0xc0000a0001e00000, *( (volatile uint64_t *)0xc0000a0001e00000) ); + +printk("Widget ID Address 0x%p Value 0x%lx\n", (uint64_t *)0xc0000a0001c00000, *( (volatile uint64_t *)0xc0000a0001c00000) ); + +printk("Widget ID Address 0x%p Value 0x%lx\n", (uint64_t *)0xc000020001e00000, *( (volatile uint64_t *)0xc000020001e00000) ); + + +printk("Widget ID Address 0x%p Value 0x%lx\n", (uint64_t *)0xc000020001c00000, *( (volatile uint64_t *)0xc000020001c00000) ); + +printk("Widget ID Address 0x%p Value 0x%lx\n", (uint64_t *)0xc0000a0001e00000, *( (volatile uint64_t *)0xc0000a0001e00000) ); + +printk("Xbow ID Address 0x%p Value 0x%x\n", (uint64_t *)0xc0000a0000000000, *( (volatile uint32_t *)0xc0000a0000000000) ); + +printk("Xbow ID Address 0x%p Value 0x%x\n", (uint64_t *)0xc000020000000004, *( (volatile uint32_t *)0xc000020000000004) ); + + + if ( test ) + test_io_regs(); + /* + * Klconfig header. + */ + kl_hdr_ptr = kmalloc(sizeof(kl_config_hdr_t), GFP_KERNEL); + kl_hdr_ptr->ch_magic = 0xbeedbabe; + kl_hdr_ptr->ch_version = 0x0; + kl_hdr_ptr->ch_malloc_hdr_off = 0x48; + kl_hdr_ptr->ch_cons_off = 0x18; + kl_hdr_ptr->ch_board_info = 0x0; + kl_hdr_ptr->ch_cons_info.uart_base = 0x920000000f820178; + kl_hdr_ptr->ch_cons_info.config_base = 0x920000000f024000; + kl_hdr_ptr->ch_cons_info.memory_base = 0x920000000f800000; + kl_hdr_ptr->ch_cons_info.baud = 0x2580; + kl_hdr_ptr->ch_cons_info.flag = 0x1; + kl_hdr_ptr->ch_cons_info.type = 0x300fafa; + kl_hdr_ptr->ch_cons_info.nasid = 0x0; + kl_hdr_ptr->ch_cons_info.wid = 0xf; + kl_hdr_ptr->ch_cons_info.npci = 0x4; + kl_hdr_ptr->ch_cons_info.baseio_nic = 0x0; + + linux_klcfg = kl_hdr_ptr; + + /* + * lboard KLTYPE_IP35 + */ + lb_ptr = kmalloc(sizeof(lboard_t), GFP_KERNEL); + kl_hdr_ptr->ch_board_info = (klconf_off_t) lb_ptr; + temp_ptr = lb_ptr; + printk("First Lboard = %p\n", temp_ptr); + + lb_ptr->brd_next = 0; + lb_ptr->struct_type = 0x1; + lb_ptr->brd_type = 0x11; + lb_ptr->brd_sversion = 0x3; + lb_ptr->brd_brevision = 0x1; + lb_ptr->brd_promver = 0x1; + lb_ptr->brd_promver = 0x1; + lb_ptr->brd_slot = 0x0; + lb_ptr->brd_debugsw = 0x0; + lb_ptr->brd_module = 0x145; + lb_ptr->brd_partition = 0x0; + lb_ptr->brd_diagval = 0x0; + lb_ptr->brd_diagparm = 0x0; + lb_ptr->brd_inventory = 0x0; + lb_ptr->brd_numcompts = 0x5; + lb_ptr->brd_nic = 0x2a0aed35; + lb_ptr->brd_nasid = 0x0; + lb_ptr->brd_errinfo = 0x0; + lb_ptr->brd_parent = 0x0; + lb_ptr->brd_graph_link = (devfs_handle_t)0x26; + lb_ptr->brd_owner = 0x0; + lb_ptr->brd_nic_flags = 0x0; + memcpy(&lb_ptr->brd_name[0], "IP35", 4); + + /* + * Hub Component + */ + klcomp_ptr = kmalloc(sizeof(klcomp_t), GFP_KERNEL); + klhub_ptr = (klhub_t *)klcomp_ptr; + klinfo_ptr = (klinfo_t *)klcomp_ptr; + lb_ptr->brd_compts[0] = (klconf_off_t)klcomp_ptr; + printk("hub info = %p lboard = %p\n", klhub_ptr, lb_ptr); + + klinfo_ptr = (klinfo_t *)klhub_ptr; + klinfo_ptr->struct_type = 0x2; + klinfo_ptr->struct_version = 0x1; + klinfo_ptr->flags = 0x1; + klinfo_ptr->revision = 0x1; + klinfo_ptr->diagval = 0x0; + klinfo_ptr->diagparm = 0x0; + klinfo_ptr->inventory = 0x0; + klinfo_ptr->partid = 0x0; + klinfo_ptr->nic = 0x2a0aed35; + klinfo_ptr->physid = 0x0; + klinfo_ptr->virtid = 0x0; + klinfo_ptr->widid = 0x0; + klinfo_ptr->nasid = 0x0; + + klhub_ptr->hub_flags = 0x0; + klhub_ptr->hub_port.port_nasid = (nasid_t)0x0ffffffff; + klhub_ptr->hub_port.port_flag = 0x0; + klhub_ptr->hub_port.port_offset = 0x0; + klhub_ptr->hub_box_nic = 0x0; + klhub_ptr->hub_mfg_nic = 0x3f420; + klhub_ptr->hub_speed = 0xbebc200; + + /* + * Memory Component + */ + klcomp_ptr = kmalloc(sizeof(klcomp_t), GFP_KERNEL); + klinfo_ptr = (klinfo_t *)klcomp_ptr; + lb_ptr->brd_compts[1] = (klconf_off_t)klcomp_ptr; + + klinfo_ptr->struct_type = 0x3; + klinfo_ptr->struct_version = 0x2; + klinfo_ptr->flags = 0x1; + klinfo_ptr->revision = 0xff; + klinfo_ptr->diagval = 0x0; + klinfo_ptr->diagparm = 0x0; + klinfo_ptr->inventory = 0x0; + klinfo_ptr->partid = 0x0; + klinfo_ptr->nic = 0xffffffffffffffff; + klinfo_ptr->physid = 0xff; + klinfo_ptr->virtid = 0xffffffff; + klinfo_ptr->widid = 0x0; + klinfo_ptr->nasid = 0x0; + + /* + * KLSTRUCT_HUB_UART Component + */ + klcomp_ptr = kmalloc(sizeof(klcomp_t), GFP_KERNEL); + klinfo_ptr = (klinfo_t *)klcomp_ptr; + lb_ptr->brd_compts[2] = (klconf_off_t)klcomp_ptr; + + klinfo_ptr->struct_type = 0x11; + klinfo_ptr->struct_version = 0x1; + klinfo_ptr->flags = 0x31; + klinfo_ptr->revision = 0xff; + klinfo_ptr->diagval = 0x0; + klinfo_ptr->diagparm = 0x0; + klinfo_ptr->inventory = 0x0; + klinfo_ptr->partid = 0x0; + klinfo_ptr->nic = 0xffffffffffffffff; + klinfo_ptr->physid = 0x0; + klinfo_ptr->virtid = 0x0; + klinfo_ptr->widid = 0x0; + klinfo_ptr->nasid = 0x0; + + /* + * KLSTRUCT_CPU Component + */ + klcomp_ptr = kmalloc(sizeof(klcomp_t), GFP_KERNEL); + klinfo_ptr = (klinfo_t *)klcomp_ptr; + lb_ptr->brd_compts[3] = (klconf_off_t)klcomp_ptr; + + klinfo_ptr->struct_type = 0x1; + klinfo_ptr->struct_version = 0x2; + klinfo_ptr->flags = 0x1; + klinfo_ptr->revision = 0xff; + klinfo_ptr->diagval = 0x0; + klinfo_ptr->diagparm = 0x0; + klinfo_ptr->inventory = 0x0; + klinfo_ptr->partid = 0x0; + klinfo_ptr->nic = 0xffffffffffffffff; + klinfo_ptr->physid = 0x0; + klinfo_ptr->virtid = 0x0; + klinfo_ptr->widid = 0x0; + klinfo_ptr->nasid = 0x0; + + /* + * KLSTRUCT_CPU Component + */ + klcomp_ptr = kmalloc(sizeof(klcomp_t), GFP_KERNEL); + klinfo_ptr = (klinfo_t *)klcomp_ptr; + lb_ptr->brd_compts[4] = (klconf_off_t)klcomp_ptr; + + klinfo_ptr->struct_type = 0x1; + klinfo_ptr->struct_version = 0x2; + klinfo_ptr->flags = 0x1; + klinfo_ptr->revision = 0xff; + klinfo_ptr->diagval = 0x0; + klinfo_ptr->diagparm = 0x0; + klinfo_ptr->inventory = 0x0; + klinfo_ptr->partid = 0x0; + klinfo_ptr->nic = 0xffffffffffffffff; + klinfo_ptr->physid = 0x1; + klinfo_ptr->virtid = 0x1; + klinfo_ptr->widid = 0x0; + klinfo_ptr->nasid = 0x0; + + lb_ptr->brd_compts[5] = 0; /* Set the next one to 0 .. end */ + lb_ptr->brd_numcompts = 5; /* 0 to 4 */ + + /* + * lboard(0x42) KLTYPE_PBRICK_XBOW + */ + lb_ptr = kmalloc(sizeof(lboard_t), GFP_KERNEL); + temp_ptr->brd_next = (klconf_off_t)lb_ptr; /* Let the previous point at the new .. */ + temp_ptr = lb_ptr; + printk("Second Lboard = %p\n", temp_ptr); + + lb_ptr->brd_next = 0; + lb_ptr->struct_type = 0x1; + lb_ptr->brd_type = 0x42; + lb_ptr->brd_sversion = 0x2; + lb_ptr->brd_brevision = 0x0; + lb_ptr->brd_promver = 0x1; + lb_ptr->brd_promver = 0x1; + lb_ptr->brd_slot = 0x0; + lb_ptr->brd_debugsw = 0x0; + lb_ptr->brd_module = 0x145; + lb_ptr->brd_partition = 0x1; + lb_ptr->brd_diagval = 0x0; + lb_ptr->brd_diagparm = 0x0; + lb_ptr->brd_inventory = 0x0; + lb_ptr->brd_numcompts = 0x1; + lb_ptr->brd_nic = 0xffffffffffffffff; + lb_ptr->brd_nasid = 0x0; + lb_ptr->brd_errinfo = 0x0; + lb_ptr->brd_parent = (struct lboard_s *)0x9600000000030070; + lb_ptr->brd_graph_link = (devfs_handle_t)0xffffffff; + lb_ptr->brd_owner = 0x0; + lb_ptr->brd_nic_flags = 0x0; + memcpy(&lb_ptr->brd_name[0], "IOBRICK", 7); + + /* + * KLSTRUCT_XBOW Component + */ + klcomp_ptr = kmalloc(sizeof(klcomp_t), GFP_KERNEL); + memset(klcomp_ptr, 0, sizeof(klcomp_t)); + klxbow_ptr = (klxbow_t *)klcomp_ptr; + klinfo_ptr = (klinfo_t *)klcomp_ptr; + lb_ptr->brd_compts[0] = (klconf_off_t)klcomp_ptr; + printk("xbow_p 0x%p\n", klcomp_ptr); + + klinfo_ptr->struct_type = 0x4; + klinfo_ptr->struct_version = 0x1; + klinfo_ptr->flags = 0x1; + klinfo_ptr->revision = 0x2; + klinfo_ptr->diagval = 0x0; + klinfo_ptr->diagparm = 0x0; + klinfo_ptr->inventory = 0x0; + klinfo_ptr->partid = 0x0; + klinfo_ptr->nic = 0xffffffffffffffff; + klinfo_ptr->physid = 0xff; + klinfo_ptr->virtid = 0x0; + klinfo_ptr->widid = 0x0; + klinfo_ptr->nasid = 0x0; + + klxbow_ptr->xbow_master_hub_link = 0xb; + klxbow_ptr->xbow_port_info[0].port_nasid = 0x0; + klxbow_ptr->xbow_port_info[0].port_flag = 0x0; + klxbow_ptr->xbow_port_info[0].port_offset = 0x0; + + klxbow_ptr->xbow_port_info[1].port_nasid = 0x401; + klxbow_ptr->xbow_port_info[1].port_flag = 0x0; + klxbow_ptr->xbow_port_info[1].port_offset = 0x0; + + klxbow_ptr->xbow_port_info[2].port_nasid = 0x0; + klxbow_ptr->xbow_port_info[2].port_flag = 0x0; + klxbow_ptr->xbow_port_info[2].port_offset = 0x0; + + klxbow_ptr->xbow_port_info[3].port_nasid = 0x0; /* ffffffff */ + klxbow_ptr->xbow_port_info[3].port_flag = 0x6; + klxbow_ptr->xbow_port_info[3].port_offset = 0x30070; + + klxbow_ptr->xbow_port_info[4].port_nasid = 0x0; /* ffffff00; */ + klxbow_ptr->xbow_port_info[4].port_flag = 0x0; + klxbow_ptr->xbow_port_info[4].port_offset = 0x0; + + klxbow_ptr->xbow_port_info[5].port_nasid = 0x0; + klxbow_ptr->xbow_port_info[5].port_flag = 0x0; + klxbow_ptr->xbow_port_info[5].port_offset = 0x0; + klxbow_ptr->xbow_port_info[6].port_nasid = 0x0; + klxbow_ptr->xbow_port_info[6].port_flag = 0x5; + klxbow_ptr->xbow_port_info[6].port_offset = 0x30210; + klxbow_ptr->xbow_port_info[7].port_nasid = 0x3; + klxbow_ptr->xbow_port_info[7].port_flag = 0x5; + klxbow_ptr->xbow_port_info[7].port_offset = 0x302e0; + + lb_ptr->brd_compts[1] = 0; + lb_ptr->brd_numcompts = 1; + + + /* + * lboard KLTYPE_PBRICK + */ + lb_ptr = kmalloc(sizeof(lboard_t), GFP_KERNEL); + temp_ptr->brd_next = (klconf_off_t)lb_ptr; /* Let the previous point at the new .. */ + temp_ptr = lb_ptr; + printk("Third Lboard %p\n", lb_ptr); + + lb_ptr->brd_next = 0; + lb_ptr->struct_type = 0x1; + lb_ptr->brd_type = 0x72; + lb_ptr->brd_sversion = 0x2; + lb_ptr->brd_brevision = 0x0; + lb_ptr->brd_promver = 0x1; + lb_ptr->brd_promver = 0x41; + lb_ptr->brd_slot = 0xe; + lb_ptr->brd_debugsw = 0x0; + lb_ptr->brd_module = 0x145; + lb_ptr->brd_partition = 0x1; + lb_ptr->brd_diagval = 0x0; + lb_ptr->brd_diagparm = 0x0; + lb_ptr->brd_inventory = 0x0; + lb_ptr->brd_numcompts = 0x1; + lb_ptr->brd_nic = 0x30e3fd; + lb_ptr->brd_nasid = 0x0; + lb_ptr->brd_errinfo = 0x0; + lb_ptr->brd_parent = (struct lboard_s *)0x9600000000030140; + lb_ptr->brd_graph_link = (devfs_handle_t)0xffffffff; + lb_ptr->brd_owner = 0x0; + lb_ptr->brd_nic_flags = 0x0; + memcpy(&lb_ptr->brd_name[0], "IP35", 4); + + /* + * KLSTRUCT_BRI Component + */ + klcomp_ptr = kmalloc(sizeof(klcomp_t), GFP_KERNEL); + klbri_ptr = (klbri_t *)klcomp_ptr; + klinfo_ptr = (klinfo_t *)klcomp_ptr; + lb_ptr->brd_compts[0] = (klconf_off_t)klcomp_ptr; + + klinfo_ptr->struct_type = 0x5; + klinfo_ptr->struct_version = 0x2; + klinfo_ptr->flags = 0x1; + klinfo_ptr->revision = 0x2; + klinfo_ptr->diagval = 0x0; + klinfo_ptr->diagparm = 0x0; + klinfo_ptr->inventory = 0x0; + klinfo_ptr->partid = 0xd002; + klinfo_ptr->nic = 0x30e3fd; + klinfo_ptr->physid = 0xe; + klinfo_ptr->virtid = 0xe; + klinfo_ptr->widid = 0xe; + klinfo_ptr->nasid = 0x0; + + klbri_ptr->bri_eprominfo = 0xff; + klbri_ptr->bri_bustype = 0x7; + klbri_ptr->bri_mfg_nic = 0x3f4a8; + + lb_ptr->brd_compts[1] = 0; + lb_ptr->brd_numcompts = 1; + + /* + * lboard KLTYPE_PBRICK + */ + lb_ptr = kmalloc(sizeof(lboard_t), GFP_KERNEL); + temp_ptr->brd_next = (klconf_off_t)lb_ptr; /* Let the previous point at the new .. */ + temp_ptr = lb_ptr; + printk("Fourth Lboard %p\n", lb_ptr); + + lb_ptr->brd_next = 0x0; + lb_ptr->struct_type = 0x1; + lb_ptr->brd_type = 0x72; + lb_ptr->brd_sversion = 0x2; + lb_ptr->brd_brevision = 0x0; + lb_ptr->brd_promver = 0x1; + lb_ptr->brd_promver = 0x31; + lb_ptr->brd_slot = 0xf; + lb_ptr->brd_debugsw = 0x0; + lb_ptr->brd_module = 0x145; + lb_ptr->brd_partition = 0x1; + lb_ptr->brd_diagval = 0x0; + lb_ptr->brd_diagparm = 0x0; + lb_ptr->brd_inventory = 0x0; + lb_ptr->brd_numcompts = 0x6; + lb_ptr->brd_nic = 0x30e3fd; + lb_ptr->brd_nasid = 0x0; + lb_ptr->brd_errinfo = 0x0; + lb_ptr->brd_parent = (struct lboard_s *)0x9600000000030140; + lb_ptr->brd_graph_link = (devfs_handle_t)0xffffffff; + lb_ptr->brd_owner = 0x0; + lb_ptr->brd_nic_flags = 0x0; + memcpy(&lb_ptr->brd_name[0], "IP35", 4); + + + /* + * KLSTRUCT_BRI Component + */ + klcomp_ptr = kmalloc(sizeof(klcomp_t), GFP_KERNEL); + klbri_ptr = (klbri_t *)klcomp_ptr; + klinfo_ptr = (klinfo_t *)klcomp_ptr; + lb_ptr->brd_compts[0] = (klconf_off_t)klcomp_ptr; + + klinfo_ptr->struct_type = 0x5; + klinfo_ptr->struct_version = 0x2; + klinfo_ptr->flags = 0x1; + klinfo_ptr->revision = 0x2; + klinfo_ptr->diagval = 0x0; + klinfo_ptr->diagparm = 0x0; + klinfo_ptr->inventory = 0x0; + klinfo_ptr->partid = 0xd002; + klinfo_ptr->nic = 0x30e3fd; + klinfo_ptr->physid = 0xf; + klinfo_ptr->virtid = 0xf; + klinfo_ptr->widid = 0xf; + klinfo_ptr->nasid = 0x0; + + klbri_ptr->bri_eprominfo = 0xff; + klbri_ptr->bri_bustype = 0x7; + klbri_ptr->bri_mfg_nic = 0x3f528; + + /* + * KLSTRUCT_SCSI component + */ + klcomp_ptr = kmalloc(sizeof(klcomp_t), GFP_KERNEL); + klinfo_ptr = (klinfo_t *)klcomp_ptr; + lb_ptr->brd_compts[1] = (klconf_off_t)klcomp_ptr; + + klinfo_ptr->struct_type = 0xb; + klinfo_ptr->struct_version = 0x1; + klinfo_ptr->flags = 0x31; + klinfo_ptr->revision = 0x5; + klinfo_ptr->diagval = 0x0; + klinfo_ptr->diagparm = 0x0; + klinfo_ptr->inventory = 0x0; + klinfo_ptr->partid = 0x0; + klinfo_ptr->nic = 0xffffffffffffffff; + klinfo_ptr->physid = 0x1; + klinfo_ptr->virtid = 0x0; + klinfo_ptr->widid = 0xf; + klinfo_ptr->nasid = 0x0; + + /* + * KLSTRUCT_IOC3 Component + */ + klcomp_ptr = kmalloc(sizeof(klcomp_t), GFP_KERNEL); + klioc3_ptr = (klioc3_t *)klcomp_ptr; + klinfo_ptr = (klinfo_t *)klcomp_ptr; + lb_ptr->brd_compts[2] = (klconf_off_t)klcomp_ptr; + + klinfo_ptr->struct_type = 0x6; + klinfo_ptr->struct_version = 0x1; + klinfo_ptr->flags = 0x31; + klinfo_ptr->revision = 0x1; + klinfo_ptr->diagval = 0x0; + klinfo_ptr->diagparm = 0x0; + klinfo_ptr->inventory = 0x0; + klinfo_ptr->partid = 0x0; + klinfo_ptr->nic = 0xffffffffffffffff; + klinfo_ptr->physid = 0x4; + klinfo_ptr->virtid = 0x0; + klinfo_ptr->widid = 0xf; + klinfo_ptr->nasid = 0x0; + + klioc3_ptr->ioc3_ssram = 0x0; + klioc3_ptr->ioc3_nvram = 0x0; + + /* + * KLSTRUCT_UNKNOWN Component + */ + klcomp_ptr = kmalloc(sizeof(klcomp_t), GFP_KERNEL); + klinfo_ptr = (klinfo_t *)klcomp_ptr; + lb_ptr->brd_compts[3] = (klconf_off_t)klcomp_ptr; + + klinfo_ptr->struct_type = 0x0; + klinfo_ptr->struct_version = 0x1; + klinfo_ptr->flags = 0x31; + klinfo_ptr->revision = 0xff; + klinfo_ptr->diagval = 0x0; + klinfo_ptr->diagparm = 0x0; + klinfo_ptr->inventory = 0x0; + klinfo_ptr->partid = 0x0; + klinfo_ptr->nic = 0xffffffffffffffff; + klinfo_ptr->physid = 0x5; + klinfo_ptr->virtid = 0x0; + klinfo_ptr->widid = 0xf; + klinfo_ptr->nasid = 0x0; + + /* + * KLSTRUCT_SCSI Component + */ + klcomp_ptr = kmalloc(sizeof(klcomp_t), GFP_KERNEL); + klinfo_ptr = (klinfo_t *)klcomp_ptr; + lb_ptr->brd_compts[4] = (klconf_off_t)klcomp_ptr; + + klinfo_ptr->struct_type = 0xb; + klinfo_ptr->struct_version = 0x1; + klinfo_ptr->flags = 0x31; + klinfo_ptr->revision = 0x1; + klinfo_ptr->diagval = 0x0; + klinfo_ptr->diagparm = 0x0; + klinfo_ptr->inventory = 0x0; + klinfo_ptr->partid = 0x0; + klinfo_ptr->nic = 0xffffffffffffffff; + klinfo_ptr->physid = 0x6; + klinfo_ptr->virtid = 0x5; + klinfo_ptr->widid = 0xf; + klinfo_ptr->nasid = 0x0; + + /* + * KLSTRUCT_UNKNOWN + */ + klcomp_ptr = kmalloc(sizeof(klcomp_t), GFP_KERNEL); + klinfo_ptr = (klinfo_t *)klcomp_ptr; + lb_ptr->brd_compts[5] = (klconf_off_t)klcomp_ptr; + + klinfo_ptr->struct_type = 0x0; + klinfo_ptr->struct_version = 0x1; + klinfo_ptr->flags = 0x31; + klinfo_ptr->revision = 0xff; + klinfo_ptr->diagval = 0x0; + klinfo_ptr->diagparm = 0x0; + klinfo_ptr->inventory = 0x0; + klinfo_ptr->partid = 0x0; + klinfo_ptr->nic = 0xffffffffffffffff; + klinfo_ptr->physid = 0x7; + klinfo_ptr->virtid = 0x0; + klinfo_ptr->widid = 0xf; + klinfo_ptr->nasid = 0x0; + + lb_ptr->brd_compts[6] = 0; + lb_ptr->brd_numcompts = 6; + +} + + + + + +#ifdef BRINGUP +/* + * these were useful for printing out registers etc + * during bringup + */ + +void +xdump(long long *addr, int count) +{ + int ii; + volatile long long *xx = addr; + + for ( ii = 0; ii < count; ii++, xx++ ) { + printk("0x%p : 0x%p\n", xx, *xx); + } +} + +void +xdump32(unsigned int *addr, int count) +{ + int ii; + volatile unsigned int *xx = addr; + + for ( ii = 0; ii < count; ii++, xx++ ) { + printk("0x%p : 0x%0x\n", xx, *xx); + } +} + + + +void +clear_ii_error(void) +{ + volatile long long *tmp; + + printk("... WSTAT "); + xdump((long long *)0xc0000a0001c00008, 1); + printk("... WCTRL "); + xdump((long long *)0xc0000a0001c00020, 1); + printk("... WLCSR "); + xdump((long long *)0xc0000a0001c00128, 1); + printk("... IIDSR "); + xdump((long long *)0xc0000a0001c00138, 1); + printk("... IOPRBs "); + xdump((long long *)0xc0000a0001c00198, 9); + printk("... IXSS "); + xdump((long long *)0xc0000a0001c00210, 1); + printk("... IBLS0 "); + xdump((long long *)0xc0000a0001c10000, 1); + printk("... IBLS1 "); + xdump((long long *)0xc0000a0001c20000, 1); + + /* Write IOERR clear to clear the CRAZY bit in the status */ + tmp = (long long *)0xc0000a0001c001f8; *tmp = (long long)0xffffffff; + + /* dump out local block error registers */ + printk("... "); + xdump((long long *)0xc0000a0001e04040, 1); /* LB_ERROR_BITS */ + printk("... "); + xdump((long long *)0xc0000a0001e04050, 1); /* LB_ERROR_HDR1 */ + printk("... "); + xdump((long long *)0xc0000a0001e04058, 1); /* LB_ERROR_HDR2 */ + /* and clear the LB_ERROR_BITS */ + tmp = (long long *)0xc0000a0001e04040; *tmp = 0x0; + printk("clr: "); + xdump((long long *)0xc0000a0001e04040, 1); /* LB_ERROR_BITS */ + tmp = (long long *)0xc0000a0001e04050; *tmp = 0x0; + tmp = (long long *)0xc0000a0001e04058; *tmp = 0x0; +} + + +void +dump_ii() +{ + printk("===== Dump the II regs =====\n"); + xdump((long long *)0xc0000a0001c00000, 2); + xdump((long long *)0xc0000a0001c00020, 1); + xdump((long long *)0xc0000a0001c00100, 37); + xdump((long long *)0xc0000a0001c00300, 98); + xdump((long long *)0xc0000a0001c10000, 6); + xdump((long long *)0xc0000a0001c20000, 6); + xdump((long long *)0xc0000a0001c30000, 2); + + xdump((long long *)0xc0000a0000000000, 1); + xdump((long long *)0xc0000a0001000000, 1); + xdump((long long *)0xc0000a0002000000, 1); + xdump((long long *)0xc0000a0003000000, 1); + xdump((long long *)0xc0000a0004000000, 1); + xdump((long long *)0xc0000a0005000000, 1); + xdump((long long *)0xc0000a0006000000, 1); + xdump((long long *)0xc0000a0007000000, 1); + xdump((long long *)0xc0000a0008000000, 1); + xdump((long long *)0xc0000a0009000000, 1); + xdump((long long *)0xc0000a000a000000, 1); + xdump((long long *)0xc0000a000b000000, 1); + xdump((long long *)0xc0000a000c000000, 1); + xdump((long long *)0xc0000a000d000000, 1); + xdump((long long *)0xc0000a000e000000, 1); + xdump((long long *)0xc0000a000f000000, 1); +} + +void +dump_lb() +{ + printk("===== Dump the LB regs =====\n"); + xdump((long long *)0xc0000a0001e00000, 1); + xdump((long long *)0xc0000a0001e04000, 13); + xdump((long long *)0xc0000a0001e04100, 2); + xdump((long long *)0xc0000a0001e04200, 2); + xdump((long long *)0xc0000a0001e08000, 5); + xdump((long long *)0xc0000a0001e08040, 2); + xdump((long long *)0xc0000a0001e08050, 3); + xdump((long long *)0xc0000a0001e0c000, 3); + xdump((long long *)0xc0000a0001e0c020, 4); +} + +void +dump_crossbow() +{ + printk("===== Dump the Crossbow regs =====\n"); + clear_ii_error(); + xdump32((unsigned int *)0xc0000a0000000004, 1); + clear_ii_error(); + xdump32((unsigned int *)0xc0000a0000000000, 1); + printk("and again..\n"); + xdump32((unsigned int *)0xc0000a0000000000, 1); + xdump32((unsigned int *)0xc0000a0000000000, 1); + + + clear_ii_error(); + + xdump32((unsigned int *)0xc000020000000004, 1); + clear_ii_error(); + xdump32((unsigned int *)0xc000020000000000, 1); + clear_ii_error(); + + xdump32((unsigned int *)0xc0000a0000800004, 1); + clear_ii_error(); + xdump32((unsigned int *)0xc0000a0000800000, 1); + clear_ii_error(); + + xdump32((unsigned int *)0xc000020000800004, 1); + clear_ii_error(); + xdump32((unsigned int *)0xc000020000800000, 1); + clear_ii_error(); + + +} +#endif /* BRINGUP */ diff -urN linux-2.4.0-test10/arch/ia64/sn/io/labelcl.c linux-2.4.0-test10-lia/arch/ia64/sn/io/labelcl.c --- linux-2.4.0-test10/arch/ia64/sn/io/labelcl.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/labelcl.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,667 @@ +/* labelcl - SGI's Hwgraph Compatibility Layer. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + Colin Ngam may be reached by email at cngam@sgi.com + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* +** Very simple and dumb string table that supports only find/insert. +** In practice, if this table gets too large, we may need a more +** efficient data structure. Also note that currently there is no +** way to delete an item once it's added. Therefore, name collision +** will return an error. +*/ + +struct string_table label_string_table; + + + +/* + * string_table_init - Initialize the given string table. + */ +void +string_table_init(struct string_table *string_table) +{ + string_table->string_table_head = NULL; + string_table->string_table_generation = 0; + + /* + * We nedd to initialize locks here! + */ + + return; +} + + +/* + * string_table_destroy - Destroy the given string table. + */ +void +string_table_destroy(struct string_table *string_table) +{ + struct string_table_item *item, *next_item; + + item = string_table->string_table_head; + while (item) { + next_item = item->next; + + STRTBL_FREE(item); + item = next_item; + } + + /* + * We need to destroy whatever lock we have here + */ + + return; +} + + + +/* + * string_table_insert - Insert an entry in the string table .. duplicate + * names are not allowed. + */ +char * +string_table_insert(struct string_table *string_table, char *name) +{ + struct string_table_item *item, *new_item = NULL, *last_item = NULL; + +again: + /* + * Need to lock the table .. + */ + item = string_table->string_table_head; + last_item = NULL; + + while (item) { + if (!strcmp(item->string, name)) { + /* + * If we allocated space for the string and the found that + * someone else already entered it into the string table, + * free the space we just allocated. + */ + if (new_item) + STRTBL_FREE(new_item); + + + /* + * Search optimization: move the found item to the head + * of the list. + */ + if (last_item != NULL) { + last_item->next = item->next; + item->next = string_table->string_table_head; + string_table->string_table_head = item; + } + goto out; + } + last_item = item; + item=item->next; + } + + /* + * name was not found, so add it to the string table. + */ + if (new_item == NULL) { + long old_generation = string_table->string_table_generation; + + new_item = STRTBL_ALLOC(strlen(name)); + + strcpy(new_item->string, name); + + /* + * While we allocated memory for the new string, someone else + * changed the string table. + */ + if (old_generation != string_table->string_table_generation) { + goto again; + } + } else { + /* At this we only have the string table lock in access mode. + * Promote the access lock to an update lock for the string + * table insertion below. + */ + long old_generation = + string_table->string_table_generation; + + /* + * After we did the unlock and wer waiting for update + * lock someone could have potentially updated + * the string table. Check the generation number + * for this case. If it is the case we have to + * try all over again. + */ + if (old_generation != + string_table->string_table_generation) { + goto again; + } + } + + /* + * At this point, we're committed to adding new_item to the string table. + */ + new_item->next = string_table->string_table_head; + item = string_table->string_table_head = new_item; + string_table->string_table_generation++; + +out: + /* + * Need to unlock here. + */ + return(item->string); +} + +/* + * labelcl_info_create - Creates the data structure that will hold the + * device private information asscoiated with a devfs entry. + * The pointer to this structure is what gets stored in the devfs + * (void * info). + */ +labelcl_info_t * +labelcl_info_create() +{ + + labelcl_info_t *new = NULL; + + /* Initial allocation does not include any area for labels */ + if ( ( new = (labelcl_info_t *)kmalloc (sizeof(labelcl_info_t), GFP_KERNEL) ) == NULL ) + return NULL; + + memset (new, 0, sizeof(labelcl_info_t)); + new->hwcl_magic = LABELCL_MAGIC; + return( new); + +} + +/* + * labelcl_info_destroy - Frees the data structure that holds the + * device private information asscoiated with a devfs entry. This + * data structure was created by device_info_create(). + * + * The caller is responsible for nulling the (void *info) in the + * corresponding devfs entry. + */ +int +labelcl_info_destroy(labelcl_info_t *labelcl_info) +{ + + if (labelcl_info == NULL) + return(0); + + /* Free the label list */ + if (labelcl_info->label_list) + kfree(labelcl_info->label_list); + + /* Now free the label info area */ + labelcl_info->hwcl_magic = 0; + kfree(labelcl_info); + + return(0); +} + +/* + * labelcl_info_add_LBL - Adds a new label entry in the labelcl info + * structure. + * + * Error is returned if we find another label with the same name. + */ +int +labelcl_info_add_LBL(devfs_handle_t de, + char *info_name, + arb_info_desc_t info_desc, + arbitrary_info_t info) +{ + labelcl_info_t *labelcl_info = NULL; + int num_labels; + int new_label_list_size; + label_info_t *old_label_list, *new_label_list = NULL; + char *name; + int i; + + if (de == NULL) + return(-1); + + labelcl_info = devfs_get_info(de); + if (labelcl_info == NULL) + return(-1); + + if (labelcl_info->hwcl_magic != LABELCL_MAGIC) + return(-1); + + if (info_name == NULL) + return(-1); + + if (strlen(info_name) >= LABEL_LENGTH_MAX) + return(-1); + + name = string_table_insert(&label_string_table, info_name); + + num_labels = labelcl_info->num_labels; + new_label_list_size = sizeof(label_info_t) * (num_labels+1); + + /* + * Create a new label info area. + */ + if (new_label_list_size != 0) { + new_label_list = (label_info_t *) kmalloc(new_label_list_size, GFP_KERNEL); + + if (new_label_list == NULL) + return(-1); + } + + /* + * At this point, we are committed to adding the labelled info, + * if there isn't already information there with the same name. + */ + old_label_list = labelcl_info->label_list; + + /* + * Look for matching info name. + */ + for (i=0; inum_labels = num_labels+1; + labelcl_info->label_list = new_label_list; + + if (old_label_list != NULL) + kfree(old_label_list); + + return(0); +} + +/* + * labelcl_info_remove_LBL - Remove a label entry. + */ +int +labelcl_info_remove_LBL(devfs_handle_t de, + char *info_name, + arb_info_desc_t *info_desc, + arbitrary_info_t *info) +{ + labelcl_info_t *labelcl_info = NULL; + int num_labels; + int new_label_list_size; + label_info_t *old_label_list, *new_label_list = NULL; + arb_info_desc_t label_desc_found; + arbitrary_info_t label_info_found; + int i; + + if (de == NULL) + return(-1); + + labelcl_info = devfs_get_info(de); + if (labelcl_info == NULL) + return(-1); + + if (labelcl_info->hwcl_magic != LABELCL_MAGIC) + return(-1); + + num_labels = labelcl_info->num_labels; + if (num_labels == 0) { + return(-1); + } + + /* + * Create a new info area. + */ + new_label_list_size = sizeof(label_info_t) * (num_labels-1); + if (new_label_list_size) { + new_label_list = (label_info_t *) kmalloc(new_label_list_size, GFP_KERNEL); + if (new_label_list == NULL) + return(-1); + } + + /* + * At this point, we are committed to removing the labelled info, + * if it still exists. + */ + old_label_list = labelcl_info->label_list; + + /* + * Find matching info name. + */ + for (i=0; inum_labels = num_labels+1; + labelcl_info->label_list = new_label_list; + + kfree(old_label_list); + + if (info != NULL) + *info = label_info_found; + + if (info_desc != NULL) + *info_desc = label_desc_found; + + return(0); +} + + +/* + * labelcl_info_replace_LBL - Replace an existing label entry with the + * given new information. + * + * Label entry must exist. + */ +int +labelcl_info_replace_LBL(devfs_handle_t de, + char *info_name, + arb_info_desc_t info_desc, + arbitrary_info_t info, + arb_info_desc_t *old_info_desc, + arbitrary_info_t *old_info) +{ + labelcl_info_t *labelcl_info = NULL; + int num_labels; + label_info_t *label_list; + int i; + + if (de == NULL) + return(-1); + + labelcl_info = devfs_get_info(de); + if (labelcl_info == NULL) + return(-1); + + if (labelcl_info->hwcl_magic != LABELCL_MAGIC) + return(-1); + + num_labels = labelcl_info->num_labels; + if (num_labels == 0) { + return(-1); + } + + if (info_name == NULL) + return(-1); + + label_list = labelcl_info->label_list; + + /* + * Verify that information under info_name already exists. + */ + for (i=0; ihwcl_magic != LABELCL_MAGIC) + return(-1); + + num_labels = labelcl_info->num_labels; + if (num_labels == 0) { + return(-1); + } + + label_list = labelcl_info->label_list; + + /* + * Find information under info_name. + */ + for (i=0; ihwcl_magic != LABELCL_MAGIC) + return(-1); + + which_info = *placeptr; + + if (which_info >= labelcl_info->num_labels) { + return(-1); + } + + label_list = (label_info_t *) labelcl_info->label_list; + + if (buffer != NULL) + strcpy(buffer, label_list[which_info].name); + + if (infop) + *infop = label_list[which_info].info; + + if (info_descp) + *info_descp = label_list[which_info].desc; + + *placeptr = which_info + 1; + + return(0); +} + + +int +labelcl_info_replace_IDX(devfs_handle_t de, + int index, + arbitrary_info_t info, + arbitrary_info_t *old_info) +{ + arbitrary_info_t *info_list_IDX; + labelcl_info_t *labelcl_info = NULL; + + if (de == NULL) { + printk(KERN_ALERT "labelcl: NULL devfs handle given.\n"); + return(-1); + } + + labelcl_info = devfs_get_info(de); + if (labelcl_info == NULL) { + printk(KERN_ALERT "labelcl: Entry does not have info pointer.\n"); + return(-1); + } + + if (labelcl_info->hwcl_magic != LABELCL_MAGIC) + return(-1); + + if ( (index < 0) || (index >= HWGRAPH_NUM_INDEX_INFO) ) + return(-1); + + /* + * Replace information at the appropriate index in this vertex with + * the new info. + */ + info_list_IDX = labelcl_info->IDX_list; + if (old_info != NULL) + *old_info = info_list_IDX[index]; + info_list_IDX[index] = info; + + return(0); + +} + +/* + * labelcl_info_connectpt_set - Sets the connectpt. + */ +int +labelcl_info_connectpt_set(struct devfs_entry *de, + struct devfs_entry *connect_de) +{ + arbitrary_info_t old_info; + int rv; + + rv = labelcl_info_replace_IDX(de, HWGRAPH_CONNECTPT, + (arbitrary_info_t) connect_de, &old_info); + + if (rv) { + return(rv); + } + + return(0); +} + + +/* + * labelcl_info_get_IDX - Returns the information pointed at by index. + * + */ +int +labelcl_info_get_IDX(devfs_handle_t de, + int index, + arbitrary_info_t *info) +{ + arbitrary_info_t *info_list_IDX; + labelcl_info_t *labelcl_info = NULL; + + if (de == NULL) + return(-1); + + labelcl_info = devfs_get_info(de); + if (labelcl_info == NULL) + return(-1); + + if (labelcl_info->hwcl_magic != LABELCL_MAGIC) + return(-1); + + if ( (index < 0) || (index >= HWGRAPH_NUM_INDEX_INFO) ) + return(-1); + + /* + * Return information at the appropriate index in this vertex. + */ + info_list_IDX = labelcl_info->IDX_list; + if (info != NULL) + *info = info_list_IDX[index]; + + return(0); +} + +/* + * labelcl_info_connectpt_get - Retrieve the connect point for a device entry. + */ +struct devfs_entry * +labelcl_info_connectpt_get(struct devfs_entry *de) +{ + int rv; + arbitrary_info_t info; + + rv = labelcl_info_get_IDX(de, HWGRAPH_CONNECTPT, &info); + if (rv) + return(NULL); + + return((struct devfs_entry *)info); +} diff -urN linux-2.4.0-test10/arch/ia64/sn/io/mem_refcnt.c linux-2.4.0-test10-lia/arch/ia64/sn/io/mem_refcnt.c --- linux-2.4.0-test10/arch/ia64/sn/io/mem_refcnt.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/mem_refcnt.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,234 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// From numa_hw.h + +#define MIGR_COUNTER_MAX_GET(nodeid) \ + (NODEPDA_MCD((nodeid))->migr_system_kparms.migr_threshold_reference) +/* + * Get the Absolute Theshold + */ +#define MIGR_THRESHOLD_ABS_GET(nodeid) ( \ + MD_MIG_VALUE_THRESH_GET(COMPACT_TO_NASID_NODEID(nodeid))) +/* + * Get the current Differential Threshold + */ +#define MIGR_THRESHOLD_DIFF_GET(nodeid) \ + (NODEPDA_MCD(nodeid)->migr_as_kparms.migr_base_threshold) + +#define NUM_OF_HW_PAGES_PER_SW_PAGE() (NBPP / MD_PAGE_SIZE) + +// #include "migr_control.h" + +int +mem_refcnt_attach(devfs_handle_t hub) +{ + devfs_handle_t refcnt_dev; + + hwgraph_char_device_add(hub, + "refcnt", + "hubspc_", + &refcnt_dev); + device_info_set(refcnt_dev, (void*)(ulong)HUBSPC_REFCOUNTERS); + + return (0); +} + + +/*ARGSUSED*/ +int +mem_refcnt_open(devfs_handle_t *devp, mode_t oflag, int otyp, cred_t *crp) +{ + cnodeid_t node; +#ifndef CONFIG_IA64_SGI_SN1 + extern int numnodes; +#endif + + ASSERT( (hubspc_subdevice_t)(ulong)device_info_get(*devp) == HUBSPC_REFCOUNTERS ); + + if (!cap_able(CAP_MEMORY_MGT)) { + return (EPERM); + } + + node = master_node_get(*devp); + + ASSERT( (node >= 0) && (node < numnodes) ); + + if (NODEPDA(node)->migr_refcnt_counterbuffer == NULL) { + return (ENODEV); + } + + ASSERT( NODEPDA(node)->migr_refcnt_counterbase != NULL ); + ASSERT( NODEPDA(node)->migr_refcnt_cbsize != (size_t)0 ); + + return (0); +} + +/*ARGSUSED*/ +int +mem_refcnt_close(devfs_handle_t dev, int oflag, int otyp, cred_t *crp) +{ + return 0; +} + +/*ARGSUSED*/ +int +mem_refcnt_mmap(devfs_handle_t dev, vhandl_t *vt, off_t off, size_t len, uint prot) +{ + cnodeid_t node; + int errcode; + char* buffer; + size_t blen; +#ifndef CONFIG_IA64_SGI_SN1 + extern int numnodes; +#endif + + ASSERT( (hubspc_subdevice_t)(ulong)device_info_get(dev) == HUBSPC_REFCOUNTERS ); + + node = master_node_get(dev); + + ASSERT( (node >= 0) && (node < numnodes) ); + + ASSERT( NODEPDA(node)->migr_refcnt_counterbuffer != NULL); + ASSERT( NODEPDA(node)->migr_refcnt_counterbase != NULL ); + ASSERT( NODEPDA(node)->migr_refcnt_cbsize != 0 ); + + /* + * XXXX deal with prot's somewhere around here.... + */ + + buffer = NODEPDA(node)->migr_refcnt_counterbuffer; + blen = NODEPDA(node)->migr_refcnt_cbsize; + + /* + * Force offset to be a multiple of sizeof(refcnt_t) + * We round up. + */ + + off = (((off - 1)/sizeof(refcnt_t)) + 1) * sizeof(refcnt_t); + + if ( ((buffer + blen) - (buffer + off + len)) < 0 ) { + return (EPERM); + } + + errcode = v_mapphys(vt, + buffer + off, + len); + + return errcode; +} + +/*ARGSUSED*/ +int +mem_refcnt_unmap(devfs_handle_t dev, vhandl_t *vt) +{ + return 0; +} + +/* ARGSUSED */ +int +mem_refcnt_ioctl(devfs_handle_t dev, + int cmd, + void *arg, + int mode, + cred_t *cred_p, + int *rvalp) +{ + cnodeid_t node; + int errcode; + extern int numnodes; + + ASSERT( (hubspc_subdevice_t)(ulong)device_info_get(dev) == HUBSPC_REFCOUNTERS ); + + node = master_node_get(dev); + + ASSERT( (node >= 0) && (node < numnodes) ); + + ASSERT( NODEPDA(node)->migr_refcnt_counterbuffer != NULL); + ASSERT( NODEPDA(node)->migr_refcnt_counterbase != NULL ); + ASSERT( NODEPDA(node)->migr_refcnt_cbsize != 0 ); + + errcode = 0; + + switch (cmd) { + case RCB_INFO_GET: + { + rcb_info_t rcb; + + rcb.rcb_len = NODEPDA(node)->migr_refcnt_cbsize; + + rcb.rcb_sw_sets = NODEPDA(node)->migr_refcnt_numsets; + rcb.rcb_sw_counters_per_set = numnodes; + rcb.rcb_sw_counter_size = sizeof(refcnt_t); + + rcb.rcb_base_pages = NODEPDA(node)->migr_refcnt_numsets / + NUM_OF_HW_PAGES_PER_SW_PAGE(); + rcb.rcb_base_page_size = NBPP; + rcb.rcb_base_paddr = ctob(slot_getbasepfn(node, 0)); + + rcb.rcb_cnodeid = node; + rcb.rcb_granularity = MD_PAGE_SIZE; +#ifdef notyet + rcb.rcb_hw_counter_max = MIGR_COUNTER_MAX_GET(node); + rcb.rcb_diff_threshold = MIGR_THRESHOLD_DIFF_GET(node); +#endif + rcb.rcb_abs_threshold = MIGR_THRESHOLD_ABS_GET(node); + rcb.rcb_num_slots = node_getnumslots(node); + + if (COPYOUT(&rcb, arg, sizeof(rcb_info_t))) { + errcode = EFAULT; + } + + break; + } + case RCB_SLOT_GET: + { + rcb_slot_t slot[MAX_MEM_SLOTS]; + int s; + int nslots; + + nslots = node_getnumslots(node); + ASSERT(nslots <= MAX_MEM_SLOTS); + for (s = 0; s < nslots; s++) { + slot[s].base = (uint64_t)ctob(slot_getbasepfn(node, s)); +#ifdef notyet + slot[s].size = (uint64_t)ctob(slot_getsize(node, s)); +#else + slot[s].size = (uint64_t)1; +#endif + } + if (COPYOUT(&slot[0], arg, nslots * sizeof(rcb_slot_t))) { + errcode = EFAULT; + } + + *rvalp = nslots; + break; + } + + default: + errcode = EINVAL; + break; + + } + + return errcode; +} diff -urN linux-2.4.0-test10/arch/ia64/sn/io/ml_SN_init.c linux-2.4.0-test10-lia/arch/ia64/sn/io/ml_SN_init.c --- linux-2.4.0-test10/arch/ia64/sn/io/ml_SN_init.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/ml_SN_init.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,654 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#if defined (CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) +#include +#include +#include +#endif /* CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 */ + + +extern int numcpus; +extern char arg_maxnodes[]; +extern cpuid_t master_procid; +extern void * kmem_alloc_node(register size_t, register int , cnodeid_t); + +extern int hasmetarouter; + +int maxcpus; +cpumask_t boot_cpumask; +hubreg_t region_mask = 0; + + +extern xwidgetnum_t hub_widget_id(nasid_t); + +#ifndef CONFIG_IA64_SGI_IO +#if defined (IP27) +short cputype = CPU_IP27; +#elif defined (IP33) +short cputype = CPU_IP33; +#elif defined (IP35) +short cputype = CPU_IP35; +#else +#error +#endif +#endif /* CONFIG_IA64_SGI_IO */ + +static int fine_mode = 0; + +#ifndef CONFIG_IA64_SGI_IO +/* Global variables */ +pdaindr_t pdaindr[MAXCPUS]; +#endif + +static cnodemask_t hub_init_mask; /* Mask of cpu in a node doing init */ +static volatile cnodemask_t hub_init_done_mask; + /* Node mask where we wait for + * per hub initialization + */ +spinlock_t hub_mask_lock; /* Lock for hub_init_mask above. */ + +extern int valid_icache_reasons; /* Reasons to flush the icache */ +extern int valid_dcache_reasons; /* Reasons to flush the dcache */ +extern int numnodes; +extern u_char miniroot; +extern volatile int need_utlbmiss_patch; +extern void iograph_early_init(void); + +nasid_t master_nasid = INVALID_NASID; + + +/* + * mlreset(int slave) + * very early machine reset - at this point NO interrupts have been + * enabled; nor is memory, tlb, p0, etc setup. + * + * slave is zero when mlreset is called for the master processor and + * is nonzero thereafter. + */ + + +void +mlreset(int slave) +{ + if (!slave) { + /* + * We are the master cpu and node. + */ + master_nasid = get_nasid(); + set_master_bridge_base(); + FIXME("mlreset: Enable when we support ioc3 .."); +#ifndef CONFIG_IA64_SGI_IO + if (get_console_nasid() == master_nasid) + /* Set up the IOC3 */ + ioc3_mlreset((ioc3_cfg_t *)KL_CONFIG_CH_CONS_INFO(master_nasid)->config_base, + (ioc3_mem_t *)KL_CONFIG_CH_CONS_INFO(master_nasid)->memory_base); + + /* + * Initialize Master nvram base. + */ + nvram_baseinit(); + + fine_mode = is_fine_dirmode(); +#endif /* CONFIG_IA64_SGI_IO */ + + /* We're the master processor */ + master_procid = smp_processor_id(); + master_nasid = cpuid_to_nasid(master_procid); + + /* + * master_nasid we get back better be same as one from + * get_nasid() + */ + ASSERT_ALWAYS(master_nasid == get_nasid()); + +#ifndef CONFIG_IA64_SGI_IO + + /* + * Activate when calias is implemented. + */ + /* Set all nodes' calias sizes to 8k */ + for (i = 0; i < maxnodes; i++) { + nasid_t nasid; + int sn; + + nasid = COMPACT_TO_NASID_NODEID(i); + + /* + * Always have node 0 in the region mask, otherwise CALIAS accesses + * get exceptions since the hub thinks it is a node 0 address. + */ + for (sn=0; snpdinfo = (void *)hubinfo; + hubinfo->h_nodepda = npda; + hubinfo->h_cnodeid = node; + hubinfo->h_nasid = COMPACT_TO_NASID_NODEID(node); + + printk("init_platform_nodepda: hubinfo 0x%p, &hubinfo->h_crblock 0x%p\n", hubinfo, &hubinfo->h_crblock); + + spin_lock_init(&hubinfo->h_crblock); + + hubinfo->h_widgetid = hub_widget_id(hubinfo->h_nasid); + npda->xbow_peer = INVALID_NASID; + /* Initialize the linked list of + * router info pointers to the dependent routers + */ + npda->npda_rip_first = NULL; + /* npda_rip_last always points to the place + * where the next element is to be inserted + * into the list + */ + npda->npda_rip_last = &npda->npda_rip_first; + npda->dependent_routers = 0; + npda->module_id = INVALID_MODULE; + + /* + * Initialize the subnodePDA. + */ + for (sn=0; snprof_count = 0; + SNPDA(npda,sn)->next_prof_timeout = 0; +// ajm +#ifndef CONFIG_IA64_SGI_IO + intr_init_vecblk(npda, node, sn); +#endif + } + + npda->vector_unit_busy = 0; + + spin_lock_init(&npda->vector_lock); + init_MUTEX_LOCKED(&npda->xbow_sema); /* init it locked? */ + spin_lock_init(&npda->fprom_lock); + + spin_lock_init(&npda->node_utlbswitchlock); + npda->ni_error_print = 0; +#ifndef CONFIG_IA64_SGI_IO + if (need_utlbmiss_patch) { + npda->node_need_utlbmiss_patch = 1; + npda->node_utlbmiss_patched = 1; + } +#endif + + /* + * Clear out the nasid mask. + */ + for (i = 0; i < NASID_MASK_BYTES; i++) + npda->nasid_mask[i] = 0; + + for (i = 0; i < numnodes; i++) { + nasid_t nasid = COMPACT_TO_NASID_NODEID(i); + + /* Set my mask bit */ + npda->nasid_mask[nasid / 8] |= (1 << nasid % 8); + } + +#ifndef CONFIG_IA64_SGI_IO + npda->node_first_cpu = get_cnode_cpu(node); +#endif + + if (npda->node_first_cpu != CPU_NONE) { + /* + * Count number of cpus only if first CPU is valid. + */ + numcpus_p = &npda->node_num_cpus; + *numcpus_p = 0; + for (i = npda->node_first_cpu; i < MAXCPUS; i++) { + if (CPUID_TO_COMPACT_NODEID(i) != node) + break; + else + (*numcpus_p)++; + } + } else { + npda->node_num_cpus = 0; + } + + /* Allocate memory for the dump stack on each node + * This is useful during nmi handling since we + * may not be guaranteed shared memory at that time + * which precludes depending on a global dump stack + */ +#ifndef CONFIG_IA64_SGI_IO + npda->dump_stack = (uint64_t *)kmem_zalloc_node(DUMP_STACK_SIZE,VM_NOSLEEP, + node); + ASSERT_ALWAYS(npda->dump_stack); + ASSERT(npda->dump_stack); +#endif + /* Initialize the counter which prevents + * both the cpus on a node to proceed with nmi + * handling. + */ +#ifndef CONFIG_IA64_SGI_IO + npda->dump_count = 0; + + /* Setup the (module,slot) --> nic mapping for all the routers + * in the system. This is useful during error handling when + * there is no shared memory. + */ + router_map_init(npda); + + /* Allocate memory for the per-node router traversal queue */ + router_queue_init(npda,node); + npda->sbe_info = kmem_zalloc_node_hint(sizeof (sbe_info_t), 0, node); + ASSERT(npda->sbe_info); + +#ifdef CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 || CONFIG_IA64_GENERIC + /* + * Initialize bte info pointers to NULL + */ + for (i = 0; i < BTES_PER_NODE; i++) { + npda->node_bte_info[i] = (bteinfo_t *)NULL; + } +#endif +#endif /* CONFIG_IA64_SGI_IO */ +} + +#ifndef CONFIG_IA64_SGI_IO +/* XXX - Move the interrupt stuff to intr.c ? */ +/* + * Set up the platform-dependent fields in the processor pda. + * Must be done _after_ init_platform_nodepda(). + * If we need a lock here, something else is wrong! + */ +void init_platform_pda(pda_t *ppda, cpuid_t cpu) +{ + hub_intmasks_t *intmasks; + cpuinfo_t cpuinfo; + int i; + cnodeid_t cnode; + synergy_da_t *sda; + int which_synergy; + + /* Allocate per-cpu platform-dependent data */ + cpuinfo = (cpuinfo_t)kmem_alloc_node(sizeof(struct cpuinfo_s), GFP_ATOMIC, cputocnode(cpu)); + ASSERT_ALWAYS(cpuinfo); + ppda->pdinfo = (void *)cpuinfo; + cpuinfo->ci_cpupda = ppda; + cpuinfo->ci_cpuid = cpu; + + cnode = cpuid_to_cnode(cpu); + which_synergy = cpuid_to_synergy(cpu); + sda = Synergy_da_indr[(cnode * 2) + which_synergy]; + // intmasks = &ppda->p_intmasks; + intmasks = &sda->s_intmasks; + + ASSERT_ALWAYS(&ppda->p_nodepda); + + /* Clear INT_PEND0 masks. */ + for (i = 0; i < N_INTPEND0_MASKS; i++) + intmasks->intpend0_masks[i] = 0; + + /* Set up pointer to the vector block in the nodepda. */ + /* (Cant use SUBNODEPDA - not working yet) */ + intmasks->dispatch0 = &ppda->p_nodepda->snpda[cputosubnode(cpu)].intr_dispatch0; + intmasks->dispatch1 = &ppda->p_nodepda->snpda[cputosubnode(cpu)].intr_dispatch1; + + /* Clear INT_PEND1 masks. */ + for (i = 0; i < N_INTPEND1_MASKS; i++) + intmasks->intpend1_masks[i] = 0; + + + /* Don't read the routers unless we're the master. */ + ppda->p_routertick = 0; + +} +#endif /* CONFIG_IA64_SGI_IO */ + +#if (defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)) && !defined(BRINGUP) /* protect low mem for IP35/7 */ +#error "need protect_hub_calias, protect_nmi_handler_data" +#endif + +#ifndef CONFIG_IA64_SGI_IO +/* + * For now, just protect the first page (exception handlers). We + * may want to protect more stuff later. + */ +void +protect_hub_calias(nasid_t nasid) +{ + paddr_t pa = NODE_OFFSET(nasid) + 0; /* page 0 on node nasid */ + int i; + + for (i = 0; i < MAX_REGIONS; i++) { + if (i == nasid_to_region(nasid)) + continue; +#ifndef BRINGUP + /* Protect the exception handlers. */ + *(__psunsigned_t *)BDPRT_ENTRY(pa, i) = MD_PROT_NO; + + /* Protect the ARCS SPB. */ + *(__psunsigned_t *)BDPRT_ENTRY(pa + 4096, i) = MD_PROT_NO; +#endif + } +} + +/* + * Protect the page of low memory used to communicate with the NMI handler. + */ +void +protect_nmi_handler_data(nasid_t nasid, int slice) +{ + paddr_t pa = NODE_OFFSET(nasid) + NMI_OFFSET(nasid, slice); + int i; + + for (i = 0; i < MAX_REGIONS; i++) { + if (i == nasid_to_region(nasid)) + continue; +#ifndef BRINGUP + *(__psunsigned_t *)BDPRT_ENTRY(pa, i) = MD_PROT_NO; +#endif + } +} +#endif /* CONFIG_IA64_SGI_IO */ + + +#ifdef IRIX +/* + * Protect areas of memory that we access uncached by marking them as + * poisoned so the T5 can't read them speculatively and erroneously + * mark them dirty in its cache only to write them back with old data + * later. + */ +static void +protect_low_memory(nasid_t nasid) +{ + /* Protect low memory directory */ + poison_state_alter_range(KLDIR_ADDR(nasid), KLDIR_SIZE, 1); + + /* Protect klconfig area */ + poison_state_alter_range(KLCONFIG_ADDR(nasid), KLCONFIG_SIZE(nasid), 1); + + /* Protect the PI error spool area. */ + poison_state_alter_range(PI_ERROR_ADDR(nasid), PI_ERROR_SIZE(nasid), 1); + + /* Protect CPU A's cache error eframe area. */ + poison_state_alter_range(TO_NODE_UNCAC(nasid, CACHE_ERR_EFRAME), + CACHE_ERR_AREA_SIZE, 1); + + /* Protect CPU B's area */ + poison_state_alter_range(TO_NODE_UNCAC(nasid, CACHE_ERR_EFRAME) + ^ UALIAS_FLIP_BIT, + CACHE_ERR_AREA_SIZE, 1); +#error "SN1 not handled correctly" +} +#endif /* IRIX */ + +/* + * per_hub_init + * + * This code is executed once for each Hub chip. + */ +void +per_hub_init(cnodeid_t cnode) +{ + uint64_t done; + nasid_t nasid; + nodepda_t *npdap; +#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) /* SN1 specific */ + ii_icmr_u_t ii_icmr; + ii_ibcr_u_t ii_ibcr; +#endif +#ifndef CONFIG_IA64_SGI_IO + int i; +#endif + +#ifdef SIMULATED_KLGRAPH + compact_to_nasid_node[0] = 0; + nasid_to_compact_node[0] = 0; + FIXME("per_hub_init: SIMULATED_KLCONFIG: compact_to_nasid_node[0] = 0\n"); +#endif /* SIMULATED_KLGRAPH */ + nasid = COMPACT_TO_NASID_NODEID(cnode); + + ASSERT(nasid != INVALID_NASID); + ASSERT(NASID_TO_COMPACT_NODEID(nasid) == cnode); + + /* Grab the hub_mask lock. */ + spin_lock(&hub_mask_lock); + + /* Test our bit. */ + if (!(done = CNODEMASK_TSTB(hub_init_mask, cnode))) { + + /* Turn our bit on in the mask. */ + CNODEMASK_SETB(hub_init_mask, cnode); + } + +#if defined(SN0_HWDEBUG) + hub_config_setup(); +#endif + /* Release the hub_mask lock. */ + spin_unlock(&hub_mask_lock); + + /* + * Do the actual initialization if it hasn't been done yet. + * We don't need to hold a lock for this work. + */ + if (!done) { + npdap = NODEPDA(cnode); + + npdap->hub_chip_rev = get_hub_chiprev(nasid); + +#ifndef CONFIG_IA64_SGI_IO + for (i = 0; i < CPUS_PER_NODE; i++) { + cpu = cnode_slice_to_cpuid(cnode, i); + if (!cpu_enabled(cpu)) + SET_CPU_LEDS(nasid, i, 0xf); + } +#endif /* CONFIG_IA64_SGI_IO */ + +#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) /* SN1 specific */ + + /* + * Set the total number of CRBs that can be used. + */ + ii_icmr.ii_icmr_regval= 0x0; + ii_icmr.ii_icmr_fld_s.i_c_cnt = 0xF; + REMOTE_HUB_S(nasid, IIO_ICMR, ii_icmr.ii_icmr_regval); + + /* + * Set the number of CRBs that both of the BTEs combined + * can use minus 1. + */ + ii_ibcr.ii_ibcr_regval= 0x0; + ii_ibcr.ii_ibcr_fld_s.i_count = 0x8; + REMOTE_HUB_S(nasid, IIO_IBCR, ii_ibcr.ii_ibcr_regval); + + /* + * Set CRB timeout to be 10ms. + */ + REMOTE_HUB_S(nasid, IIO_ICTP, 0x1000 ); + REMOTE_HUB_S(nasid, IIO_ICTO, 0xff); + +#endif /* SN0_HWDEBUG */ + + +#ifndef CONFIG_IA64_SGI_IO + + /* Reserve all of the hardwired interrupt levels. */ + intr_reserve_hardwired(cnode); + + /* Initialize error interrupts for this hub. */ + hub_error_init(cnode); + + /* Set up correctable memory/directory ECC error interrupt. */ + install_eccintr(cnode); + + /* Protect our exception vectors from accidental corruption. */ + protect_hub_calias(nasid); + + /* Enable RT clock interrupts */ + hub_rtc_init(cnode); + hub_migrintr_init(cnode); /* Enable migration interrupt */ +#endif + + spin_lock(&hub_mask_lock); + CNODEMASK_SETB(hub_init_done_mask, cnode); + spin_unlock(&hub_mask_lock); + + } else { + /* + * Wait for the other CPU to complete the initialization. + */ + while (CNODEMASK_TSTB(hub_init_done_mask, cnode) == 0) + /* LOOP */ + ; + } +} + +extern void +update_node_information(cnodeid_t cnodeid) +{ + nodepda_t *npda = NODEPDA(cnodeid); + nodepda_router_info_t *npda_rip; + + /* Go through the list of router info + * structures and copy some frequently + * accessed info from the info hanging + * off the corresponding router vertices + */ + npda_rip = npda->npda_rip_first; + while(npda_rip) { + if (npda_rip->router_infop) { + npda_rip->router_portmask = + npda_rip->router_infop->ri_portmask; + npda_rip->router_slot = + npda_rip->router_infop->ri_slotnum; + } else { + /* No router, no ports. */ + npda_rip->router_portmask = 0; + } + npda_rip = npda_rip->router_next; + } +} + +hubreg_t +get_region(cnodeid_t cnode) +{ + if (fine_mode) + return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_FINEREG_SHFT; + else + return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_COARSEREG_SHFT; +} + +hubreg_t +nasid_to_region(nasid_t nasid) +{ + if (fine_mode) + return nasid >> NASID_TO_FINEREG_SHFT; + else + return nasid >> NASID_TO_COARSEREG_SHFT; +} + diff -urN linux-2.4.0-test10/arch/ia64/sn/io/ml_SN_intr.c linux-2.4.0-test10-lia/arch/ia64/sn/io/ml_SN_intr.c --- linux-2.4.0-test10/arch/ia64/sn/io/ml_SN_intr.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/ml_SN_intr.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,1735 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Alan Mayer + */ + +/* + * intr.c- + * This file contains all of the routines necessary to set up and + * handle interrupts on an IP27 board. + */ + +#ident "$Revision: 1.167 $" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#if defined (CONFIG_SGI_IP35) + +#include /* For SN1 + pcibr Addressing Limitation */ +#include /* For SN1 + pcibr Addressing Limitation */ +#include /* For SN1 + pcibr Addressing Limitation */ +#endif /* SN1 */ + +#if DEBUG_INTR_TSTAMP_DEBUG +#include +#include +#include +void do_splx_log(int, int); +void spldebug_log_event(int); +#endif + +// FIXME - BRINGUP +extern unsigned long cpu_online_map; +#define cpu_enabled(cpu) (test_bit(cpu, &cpu_online_map)) +#define cpu_allows_intr(cpu) 1 +// If I understand what's going on with this, 32 should work. +// physmem_maxradius seems to be the maximum number of router +// hops to get from one end of the system to the other. With +// a maximally configured machine, with the dumbest possible +// topology, we would make 32 router hops. For what we're using +// it for, the dumbest possible should suffice. +#define physmem_maxradius() 32 + +#define SUBNODE_ANY -1 + +extern int nmied; +extern int hub_intr_wakeup_cnt; +extern synergy_da_t *Synergy_da_indr[]; +extern cpuid_t master_procid; + +extern cnodeid_t master_node_get(devfs_handle_t vhdl); + + +#define INTR_LOCK(vecblk) \ + (s = mutex_spinlock(&(vecblk)->vector_lock)) +#define INTR_UNLOCK(vecblk) \ + mutex_spinunlock(&(vecblk)->vector_lock, s) + +/* + * REACT/Pro + */ + + + +/* + * Find first bit set + * Used outside this file also + */ +int ms1bit(unsigned long x) +{ + int b; + + if (x >> 32) b = 32, x >>= 32; + else b = 0; + if (x >> 16) b += 16, x >>= 16; + if (x >> 8) b += 8, x >>= 8; + if (x >> 4) b += 4, x >>= 4; + if (x >> 2) b += 2, x >>= 2; + + return b + (int) (x >> 1); +} + +/* ARGSUSED */ +void +intr_stray(void *lvl) +{ + printk("Stray Interrupt - level %ld to cpu %d", (long)lvl, cpuid()); +} + +#if defined(DEBUG) + +/* Infrastructure to gather the device - target cpu mapping info */ +#define MAX_DEVICES 1000 /* Reasonable large number . Need not be + * the exact maximum # devices possible. + */ +#define MAX_NAME 100 +typedef struct { + dev_t dev; /* device */ + cpuid_t cpuid; /* target cpu */ + cnodeid_t cnodeid;/* node on which the target cpu is present */ + int bit; /* intr bit reserved */ + char intr_name[MAX_NAME]; /* name of the interrupt */ +} intr_dev_targ_map_t; + +intr_dev_targ_map_t intr_dev_targ_map[MAX_DEVICES]; +uint64_t intr_dev_targ_map_size; +lock_t intr_dev_targ_map_lock; + +/* Print out the device - target cpu mapping. + * This routine is used only in the idbg command + * "intrmap" + */ +void +intr_dev_targ_map_print(cnodeid_t cnodeid) +{ + int i,j,size = 0; + int print_flag = 0,verbose = 0; + char node_name[10]; + + if (cnodeid != CNODEID_NONE) { + nodepda_t *npda; + + npda = NODEPDA(cnodeid); + for (j=0; jintr_dispatch0.info[i].ii_flags); + qprintf("\n INT_PEND1: "); + for(i = 0 ; i < N_INTPEND_BITS ; i++) + qprintf("%d",SNPDA(npda,j)->intr_dispatch1.info[i].ii_flags); + } + verbose = 1; + } + qprintf("\n Device - Target Map [Interrupts: %s Node%s]\n\n", + (verbose ? "All" : "Non-hardwired"), + (cnodeid == CNODEID_NONE) ? "s: All" : node_name); + + qprintf("Device\tCpu\tCnode\tIntr_bit\tIntr_name\n"); + for (i = 0 ; i < intr_dev_targ_map_size ; i++) { + + print_flag = 0; + if (verbose) { + if (cnodeid != CNODEID_NONE) { + if (cnodeid == intr_dev_targ_map[i].cnodeid) + print_flag = 1; + } else { + print_flag = 1; + } + } else { + if (intr_dev_targ_map[i].dev != 0) { + if (cnodeid != CNODEID_NONE) { + if (cnodeid == + intr_dev_targ_map[i].cnodeid) + print_flag = 1; + } else { + print_flag = 1; + } + } + } + if (print_flag) { + size++; + qprintf("%d\t%d\t%d\t%d\t%s\n", + intr_dev_targ_map[i].dev, + intr_dev_targ_map[i].cpuid, + intr_dev_targ_map[i].cnodeid, + intr_dev_targ_map[i].bit, + intr_dev_targ_map[i].intr_name); + } + + } + qprintf("\nTotal : %d\n",size); +} +#endif /* DEBUG */ + +/* + * The spinlocks have already been initialized. Now initialize the interrupt + * vectors. One processor on each hub does the work. + */ +void +intr_init_vecblk(nodepda_t *npda, cnodeid_t node, int sn) +{ + int i, ip=0; + intr_vecblk_t *vecblk; + subnode_pda_t *snpda; + + + snpda = SNPDA(npda,sn); + do { + if (ip == 0) { + vecblk = &snpda->intr_dispatch0; + } else { + vecblk = &snpda->intr_dispatch1; + } + + /* Initialize this vector. */ + for (i = 0; i < N_INTPEND_BITS; i++) { + vecblk->vectors[i].iv_func = intr_stray; + vecblk->vectors[i].iv_prefunc = NULL; + vecblk->vectors[i].iv_arg = (void *)(__psint_t)(ip * N_INTPEND_BITS + i); + + vecblk->info[i].ii_owner_dev = 0; + strcpy(vecblk->info[i].ii_name, "Unused"); + vecblk->info[i].ii_flags = 0; /* No flags */ + vecblk->vectors[i].iv_mustruncpu = -1; /* No CPU yet. */ + + } + + spinlock_init(&vecblk->vector_lock, "ivecb"); + + vecblk->vector_count = 0; + for (i = 0; i < CPUS_PER_SUBNODE; i++) + vecblk->cpu_count[i] = 0; + + vecblk->vector_state = VECTOR_UNINITED; + + } while (++ip < 2); + +} + + +/* + * do_intr_reserve_level(cpuid_t cpu, int bit, int resflags, int reserve, + * devfs_handle_t owner_dev, char *name) + * Internal work routine to reserve or unreserve an interrupt level. + * cpu is the CPU to which the interrupt will be sent. + * bit is the level bit to reserve. -1 means any level + * resflags should include II_ERRORINT if this is an + * error interrupt, II_THREADED if the interrupt handler + * will be threaded, or 0 otherwise. + * reserve should be set to II_RESERVE or II_UNRESERVE + * to get or clear a reservation. + * owner_dev is the device that "owns" this interrupt, if supplied + * name is a human-readable name for this interrupt, if supplied + * intr_reserve_level returns the bit reserved or -1 to indicate an error + */ +static int +do_intr_reserve_level(cpuid_t cpu, int bit, int resflags, int reserve, + devfs_handle_t owner_dev, char *name) +{ + intr_vecblk_t *vecblk; + hub_intmasks_t *hub_intmasks; + int s; + int rv = 0; + int ip; + synergy_da_t *sda; + int which_synergy; + cnodeid_t cnode; + + ASSERT(bit < N_INTPEND_BITS * 2); + + cnode = cpuid_to_cnodeid(cpu); + which_synergy = cpuid_to_synergy(cpu); + sda = Synergy_da_indr[(cnode * 2) + which_synergy]; + hub_intmasks = &sda->s_intmasks; + // hub_intmasks = &pdaindr[cpu].pda->p_intmasks; + + // if (pdaindr[cpu].pda == NULL) return -1; + if ((bit < N_INTPEND_BITS) && !(resflags & II_ERRORINT)) { + vecblk = hub_intmasks->dispatch0; + ip = 0; + } else { + ASSERT((bit >= N_INTPEND_BITS) || (bit == -1)); + bit -= N_INTPEND_BITS; /* Get position relative to INT_PEND1 reg. */ + vecblk = hub_intmasks->dispatch1; + ip = 1; + } + + INTR_LOCK(vecblk); + + if (bit <= -1) { + // bit = 0; + bit = 7; /* First available on SNIA */ + ASSERT(reserve == II_RESERVE); + /* Choose any available level */ + for (; bit < N_INTPEND_BITS; bit++) { + if (!(vecblk->info[bit].ii_flags & II_RESERVE)) { + rv = bit; + break; + } + } + + /* Return -1 if all interrupt levels int this register are taken. */ + if (bit == N_INTPEND_BITS) + rv = -1; + + } else { + /* Reserve a particular level if it's available. */ + if ((vecblk->info[bit].ii_flags & II_RESERVE) == reserve) { + /* Can't (un)reserve a level that's already (un)reserved. */ + rv = -1; + } else { + rv = bit; + } + } + + /* Reserve the level and bump the count. */ + if (rv != -1) { + if (reserve) { + int maxlen = sizeof(vecblk->info[bit].ii_name) - 1; + int namelen; + vecblk->info[bit].ii_flags |= (II_RESERVE | resflags); + vecblk->info[bit].ii_owner_dev = owner_dev; + /* Copy in the name. */ + namelen = name ? strlen(name) : 0; + strncpy(vecblk->info[bit].ii_name, name, MIN(namelen, maxlen)); + vecblk->info[bit].ii_name[maxlen] = '\0'; + vecblk->vector_count++; + } else { + vecblk->info[bit].ii_flags = 0; /* Clear all the flags */ + vecblk->info[bit].ii_owner_dev = 0; + /* Clear the name. */ + vecblk->info[bit].ii_name[0] = '\0'; + vecblk->vector_count--; + } + } + + INTR_UNLOCK(vecblk); + +#if defined(DEBUG) + if (rv >= 0) { + int namelen = name ? strlen(name) : 0; + /* Gather this device - target cpu mapping information + * in a table which can be used later by the idbg "intrmap" + * command + */ + s = mutex_spinlock(&intr_dev_targ_map_lock); + if (intr_dev_targ_map_size < MAX_DEVICES) { + intr_dev_targ_map_t *p; + + p = &intr_dev_targ_map[intr_dev_targ_map_size]; + p->dev = owner_dev; + p->cpuid = cpu; + p->cnodeid = cputocnode(cpu); + p->bit = ip * N_INTPEND_BITS + rv; + strncpy(p->intr_name, + name, + MIN(MAX_NAME,namelen)); + intr_dev_targ_map_size++; + } + mutex_spinunlock(&intr_dev_targ_map_lock,s); + } +#endif /* DEBUG */ + + return (((rv == -1) ? rv : (ip * N_INTPEND_BITS) + rv)) ; +} + + +/* + * WARNING: This routine should only be called from within ml/SN. + * Reserve an interrupt level. + */ +int +intr_reserve_level(cpuid_t cpu, int bit, int resflags, devfs_handle_t owner_dev, char *name) +{ + return(do_intr_reserve_level(cpu, bit, resflags, II_RESERVE, owner_dev, name)); +} + + +/* + * WARNING: This routine should only be called from within ml/SN. + * Unreserve an interrupt level. + */ +void +intr_unreserve_level(cpuid_t cpu, int bit) +{ + (void)do_intr_reserve_level(cpu, bit, 0, II_UNRESERVE, 0, NULL); +} + +/* + * Get values that vary depending on which CPU and bit we're operating on + */ +static hub_intmasks_t * +intr_get_ptrs(cpuid_t cpu, int bit, + int *new_bit, /* Bit relative to the register */ + hubreg_t **intpend_masks, /* Masks for this register */ + intr_vecblk_t **vecblk, /* Vecblock for this interrupt */ + int *ip) /* Which intpend register */ +{ + hub_intmasks_t *hub_intmasks; + synergy_da_t *sda; + int which_synergy; + cnodeid_t cnode; + + ASSERT(bit < N_INTPEND_BITS * 2); + + cnode = cpuid_to_cnodeid(cpu); + which_synergy = cpuid_to_synergy(cpu); + sda = Synergy_da_indr[(cnode * 2) + which_synergy]; + hub_intmasks = &sda->s_intmasks; + + // hub_intmasks = &pdaindr[cpu].pda->p_intmasks; + + if (bit < N_INTPEND_BITS) { + *intpend_masks = hub_intmasks->intpend0_masks; + *vecblk = hub_intmasks->dispatch0; + *ip = 0; + *new_bit = bit; + } else { + *intpend_masks = hub_intmasks->intpend1_masks; + *vecblk = hub_intmasks->dispatch1; + *ip = 1; + *new_bit = bit - N_INTPEND_BITS; + } + + return hub_intmasks; +} + + +/* + * intr_connect_level(cpuid_t cpu, int bit, ilvl_t intr_swlevel, + * intr_func_t intr_func, void *intr_arg); + * This is the lowest-level interface to the interrupt code. It shouldn't + * be called from outside the ml/SN directory. + * intr_connect_level hooks up an interrupt to a particular bit in + * the INT_PEND0/1 masks. Returns 0 on success. + * cpu is the CPU to which the interrupt will be sent. + * bit is the level bit to connect to + * intr_swlevel tells which software level to use + * intr_func is the interrupt handler + * intr_arg is an arbitrary argument interpreted by the handler + * intr_prefunc is a prologue function, to be called + * with interrupts disabled, to disable + * the interrupt at source. It is called + * with the same argument. Should be NULL for + * typical interrupts, which can be masked + * by the infrastructure at the level bit. + * intr_connect_level returns 0 on success or nonzero on an error + */ +/* ARGSUSED */ +int +intr_connect_level(cpuid_t cpu, int bit, ilvl_t intr_swlevel, + intr_func_t intr_func, void *intr_arg, + intr_func_t intr_prefunc) +{ + intr_vecblk_t *vecblk; + hubreg_t *intpend_masks; + int s; + int rv = 0; + int ip; + + ASSERT(bit < N_INTPEND_BITS * 2); + + (void)intr_get_ptrs(cpu, bit, &bit, &intpend_masks, + &vecblk, &ip); + + INTR_LOCK(vecblk); + + if ((vecblk->info[bit].ii_flags & II_INUSE) || + (!(vecblk->info[bit].ii_flags & II_RESERVE))) { + /* Can't assign to a level that's in use or isn't reserved. */ + rv = -1; + } else { + /* Stuff parameters into vector and info */ + vecblk->vectors[bit].iv_func = intr_func; + vecblk->vectors[bit].iv_prefunc = intr_prefunc; + vecblk->vectors[bit].iv_arg = intr_arg; + vecblk->info[bit].ii_flags |= II_INUSE; + } + + /* Now stuff the masks if everything's okay. */ + if (!rv) { + int lslice; + volatile hubreg_t *mask_reg; + nasid_t nasid = COMPACT_TO_NASID_NODEID(cputocnode(cpu)); + int subnode = cputosubnode(cpu); + + /* Make sure it's not already pending when we connect it. */ + REMOTE_HUB_PI_CLR_INTR(nasid, subnode, bit + ip * N_INTPEND_BITS); + + intpend_masks[0] |= (1ULL << (uint64_t)bit); + + lslice = cputolocalslice(cpu); + vecblk->cpu_count[lslice]++; +#if SN1 + /* + * On SN1, there are 8 interrupt mask registers per node: + * PI_0 MASK_0 A + * PI_0 MASK_1 A + * PI_0 MASK_0 B + * PI_0 MASK_1 B + * PI_1 MASK_0 A + * PI_1 MASK_1 A + * PI_1 MASK_0 B + * PI_1 MASK_1 B + */ +#endif + if (ip == 0) { + mask_reg = REMOTE_HUB_PI_ADDR(nasid, cputosubnode(cpu), + PI_INT_MASK0_A + PI_INT_MASK_OFFSET * lslice); + } else { + mask_reg = REMOTE_HUB_PI_ADDR(nasid, cputosubnode(cpu), + PI_INT_MASK1_A + PI_INT_MASK_OFFSET * lslice); + } + + HUB_S(mask_reg, intpend_masks[0]); + } + + INTR_UNLOCK(vecblk); + + return rv; +} + + +/* + * intr_disconnect_level(cpuid_t cpu, int bit) + * + * This is the lowest-level interface to the interrupt code. It should + * not be called from outside the ml/SN directory. + * intr_disconnect_level removes a particular bit from an interrupt in + * the INT_PEND0/1 masks. Returns 0 on success or nonzero on failure. + */ +int +intr_disconnect_level(cpuid_t cpu, int bit) +{ + intr_vecblk_t *vecblk; + hubreg_t *intpend_masks; + int s; + int rv = 0; + int ip; + + (void)intr_get_ptrs(cpu, bit, &bit, &intpend_masks, + &vecblk, &ip); + + INTR_LOCK(vecblk); + + if ((vecblk->info[bit].ii_flags & (II_RESERVE | II_INUSE)) != + ((II_RESERVE | II_INUSE))) { + /* Can't remove a level that's not in use or isn't reserved. */ + rv = -1; + } else { + /* Stuff parameters into vector and info */ + vecblk->vectors[bit].iv_func = (intr_func_t)NULL; + vecblk->vectors[bit].iv_prefunc = (intr_func_t)NULL; + vecblk->vectors[bit].iv_arg = 0; + vecblk->info[bit].ii_flags &= ~II_INUSE; +#ifdef BASE_ITHRTEAD + vecblk->vectors[bit].iv_mustruncpu = -1; /* No mustrun CPU any more. */ +#endif + } + + /* Now clear the masks if everything's okay. */ + if (!rv) { + int lslice; + volatile hubreg_t *mask_reg; + + intpend_masks[0] &= ~(1ULL << (uint64_t)bit); + lslice = cputolocalslice(cpu); + vecblk->cpu_count[lslice]--; + mask_reg = REMOTE_HUB_PI_ADDR(COMPACT_TO_NASID_NODEID(cputocnode(cpu)), + cputosubnode(cpu), + ip == 0 ? PI_INT_MASK0_A : PI_INT_MASK1_A); + mask_reg = (volatile hubreg_t *)((__psunsigned_t)mask_reg + + (PI_INT_MASK_OFFSET * lslice)); + *mask_reg = intpend_masks[0]; + } + + INTR_UNLOCK(vecblk); + + return rv; +} + +/* + * Actually block or unblock an interrupt + */ +void +do_intr_block_bit(cpuid_t cpu, int bit, int block) +{ + intr_vecblk_t *vecblk; + int s; + int ip; + hubreg_t *intpend_masks; + volatile hubreg_t mask_value; + volatile hubreg_t *mask_reg; + + intr_get_ptrs(cpu, bit, &bit, &intpend_masks, &vecblk, &ip); + + INTR_LOCK(vecblk); + + if (block) + /* Block */ + intpend_masks[0] &= ~(1ULL << (uint64_t)bit); + else + /* Unblock */ + intpend_masks[0] |= (1ULL << (uint64_t)bit); + + if (ip == 0) { + mask_reg = REMOTE_HUB_PI_ADDR(COMPACT_TO_NASID_NODEID(cputocnode(cpu)), + cputosubnode(cpu), PI_INT_MASK0_A); + } else { + mask_reg = REMOTE_HUB_PI_ADDR(COMPACT_TO_NASID_NODEID(cputocnode(cpu)), + cputosubnode(cpu), PI_INT_MASK1_A); + } + + HUB_S(mask_reg, intpend_masks[0]); + + /* + * Wait for it to take effect. (One read should suffice.) + * This is only necessary when blocking an interrupt + */ + if (block) + while ((mask_value = HUB_L(mask_reg)) != intpend_masks[0]) + ; + + INTR_UNLOCK(vecblk); +} + + +/* + * Block a particular interrupt (cpu/bit pair). + */ +/* ARGSUSED */ +void +intr_block_bit(cpuid_t cpu, int bit) +{ + do_intr_block_bit(cpu, bit, 1); +} + + +/* + * Unblock a particular interrupt (cpu/bit pair). + */ +/* ARGSUSED */ +void +intr_unblock_bit(cpuid_t cpu, int bit) +{ + do_intr_block_bit(cpu, bit, 0); +} + + +/* verifies that the specified CPUID is on the specified SUBNODE (if any) */ +#define cpu_on_subnode(cpuid, which_subnode) \ + (((which_subnode) == SUBNODE_ANY) || (cputosubnode(cpuid) == (which_subnode))) + + +/* + * Choose one of the CPUs on a specified node or subnode to receive + * interrupts. Don't pick a cpu which has been specified as a NOINTR cpu. + * + * Among all acceptable CPUs, the CPU that has the fewest total number + * of interrupts targetted towards it is chosen. Note that we never + * consider how frequent each of these interrupts might occur, so a rare + * hardware error interrupt is weighted equally with a disk interrupt. + */ +static cpuid_t +do_intr_cpu_choose(cnodeid_t cnode, int which_subnode) +{ + cpuid_t cpu, best_cpu = CPU_NONE; + int slice, min_count=1000; + + min_count = 1000; + for (slice=0; slice < CPUS_PER_NODE; slice++) { + intr_vecblk_t *vecblk0, *vecblk1; + int total_intrs_to_slice; + subnode_pda_t *snpda; + int local_cpu_num; + + cpu = cnode_slice_to_cpuid(cnode, slice); + if (cpu == CPU_NONE) + continue; + + /* If this cpu isn't enabled for interrupts, skip it */ + if (!cpu_enabled(cpu) || !cpu_allows_intr(cpu)) + continue; + + /* If this isn't the right subnode, skip it */ + if (!cpu_on_subnode(cpu, which_subnode)) + continue; + + /* OK, this one's a potential CPU for interrupts */ + snpda = SUBNODEPDA(cnode,SUBNODE(slice)); + vecblk0 = &snpda->intr_dispatch0; + vecblk1 = &snpda->intr_dispatch1; + local_cpu_num = LOCALCPU(slice); + total_intrs_to_slice = vecblk0->cpu_count[local_cpu_num] + + vecblk1->cpu_count[local_cpu_num]; + + if (min_count > total_intrs_to_slice) { + min_count = total_intrs_to_slice; + best_cpu = cpu; + } + } + return best_cpu; +} + +/* + * Choose an appropriate interrupt target CPU on a specified node. + * If which_subnode is SUBNODE_ANY, then subnode is not considered. + * Otherwise, the chosen CPU must be on the specified subnode. + */ +static cpuid_t +intr_cpu_choose_from_node(cnodeid_t cnode, int which_subnode) +{ + return(do_intr_cpu_choose(cnode, which_subnode)); +} + + +#ifndef CONFIG_IA64_SGI_IO +/* + * Convert a subnode vertex into a (cnodeid, which_subnode) pair. + * Return 0 on success, non-zero on failure. + */ +static int +subnodevertex_to_subnode(devfs_handle_t vhdl, cnodeid_t *cnodeidp, int *which_subnodep) +{ + arbitrary_info_t which_subnode; + cnodeid_t cnodeid; + + /* Try to grab subnode information */ + if (hwgraph_info_get_LBL(vhdl, INFO_LBL_CPUBUS, &which_subnode) != GRAPH_SUCCESS) + return(-1); + + /* On which node? */ + cnodeid = master_node_get(vhdl); + if (cnodeid == CNODEID_NONE) + return(-1); + + *which_subnodep = (int)which_subnode; + *cnodeidp = cnodeid; + return(0); /* success */ +} + +#endif /* CONFIG_IA64_SGI_IO */ + +/* Make it easy to identify subnode vertices in the hwgraph */ +void +mark_subnodevertex_as_subnode(devfs_handle_t vhdl, int which_subnode) +{ + graph_error_t rv; + + ASSERT(0 <= which_subnode); + ASSERT(which_subnode < NUM_SUBNODES); + + rv = hwgraph_info_add_LBL(vhdl, INFO_LBL_CPUBUS, (arbitrary_info_t)which_subnode); + ASSERT_ALWAYS(rv == GRAPH_SUCCESS); + + rv = hwgraph_info_export_LBL(vhdl, INFO_LBL_CPUBUS, sizeof(arbitrary_info_t)); + ASSERT_ALWAYS(rv == GRAPH_SUCCESS); +} + + +#ifndef CONFIG_IA64_SGI_IO +/* + * Given a device descriptor, extract interrupt target information and + * choose an appropriate CPU. Return CPU_NONE if we can't make sense + * out of the target information. + * TBD: Should this be considered platform-independent code? + */ +static cpuid_t +intr_target_from_desc(device_desc_t dev_desc, int favor_subnode) +{ + cpuid_t cpuid = CPU_NONE; + cnodeid_t cnodeid; + int which_subnode; + devfs_handle_t intr_target_dev; + + if ((intr_target_dev = device_desc_intr_target_get(dev_desc)) != GRAPH_VERTEX_NONE) { + /* + * A valid device was specified. If it's a particular + * CPU, then use that CPU as target. + */ + cpuid = cpuvertex_to_cpuid(intr_target_dev); + if (cpuid != CPU_NONE) + goto cpuchosen; + + /* If a subnode vertex was specified, pick a CPU on that subnode. */ + if (subnodevertex_to_subnode(intr_target_dev, &cnodeid, &which_subnode) == 0) { + cpuid = intr_cpu_choose_from_node(cnodeid, which_subnode); + goto cpuchosen; + } + + /* + * Otherwise, pick a CPU on the node that owns the + * specified target. Favor "favor_subnode", if specified. + */ + cnodeid = master_node_get(intr_target_dev); + if (cnodeid != CNODEID_NONE) { + cpuid = intr_cpu_choose_from_node(cnodeid, favor_subnode); + goto cpuchosen; + } + } + +cpuchosen: + return(cpuid); +} +#endif /* CONFIG_IA64_SGI_IO */ + + +#ifndef CONFIG_IA64_SGI_IO +/* + * Check if we had already visited this candidate cnode + */ +static void * +intr_cnode_seen(cnodeid_t candidate, + void *arg1, + void *arg2) +{ + int i; + cnodeid_t *visited_cnodes = (cnodeid_t *)arg1; + int *num_visited_cnodes = (int *)arg2; + + ASSERT(visited_cnodes); + ASSERT(*num_visited_cnodes <= numnodes); + for(i = 0 ; i < *num_visited_cnodes; i++) { + if (candidate == visited_cnodes[i]) + return(NULL); + } + return(visited_cnodes); +} + +#endif /* CONFIG_IA64_SGI_IO */ + + + +/* + * intr_bit_reserve_test(cpuid,which_subnode,cnode,req_bit,intr_resflags, + * owner_dev,intr_name,*resp_bit) + * Either cpuid is not CPU_NONE or cnodeid not CNODE_NONE but + * not both. + * 1. If cpuid is specified, this routine tests if this cpu can be a valid + * interrupt target candidate. + * 2. If cnodeid is specified, this routine tests if there is a cpu on + * this node which can be a valid interrupt target candidate. + * 3. If a valid interrupt target cpu candidate is found then an attempt at + * reserving an interrupt bit on the corresponding cnode is made. + * + * If steps 1 & 2 both fail or step 3 fails then we are not able to get a valid + * interrupt target cpu then routine returns CPU_NONE (failure) + * Otherwise routine returns cpuid of interrupt target (success) + */ +static cpuid_t +intr_bit_reserve_test(cpuid_t cpuid, + int favor_subnode, + cnodeid_t cnodeid, + int req_bit, + int intr_resflags, + devfs_handle_t owner_dev, + char *intr_name, + int *resp_bit) +{ + + ASSERT((cpuid==CPU_NONE) || (cnodeid==CNODEID_NONE)); + + if (cnodeid != CNODEID_NONE) { + /* Try to choose a interrupt cpu candidate */ + cpuid = intr_cpu_choose_from_node(cnodeid, favor_subnode); + } + + if (cpuid != CPU_NONE) { + /* Try to reserve an interrupt bit on the hub + * corresponding to the canidate cnode. If we + * are successful then we got a cpu which can + * act as an interrupt target for the io device. + * Otherwise we need to continue the search + * further. + */ + *resp_bit = do_intr_reserve_level(cpuid, + req_bit, + intr_resflags, + II_RESERVE, + owner_dev, + intr_name); + + if (*resp_bit >= 0) + /* The interrupt target specified was fine */ + return(cpuid); + } + return(CPU_NONE); +} +/* + * intr_heuristic(dev_t dev,device_desc_t dev_desc, + * int req_bit,int intr_resflags,dev_t owner_dev, + * char *intr_name,int *resp_bit) + * + * Choose an interrupt destination for an interrupt. + * dev is the device for which the interrupt is being set up + * dev_desc is a description of hardware and policy that could + * help determine where this interrupt should go + * req_bit is the interrupt bit requested + * (can be INTRCONNECT_ANY_BIT in which the first available + * interrupt bit is used) + * intr_resflags indicates whether we want to (un)reserve bit + * owner_dev is the owner device + * intr_name is the readable interrupt name + * resp_bit indicates whether we succeeded in getting the required + * action { (un)reservation} done + * negative value indicates failure + * + */ +/* ARGSUSED */ +cpuid_t +intr_heuristic(devfs_handle_t dev, + device_desc_t dev_desc, + int req_bit, + int intr_resflags, + devfs_handle_t owner_dev, + char *intr_name, + int *resp_bit) +{ + cpuid_t cpuid; /* possible intr targ*/ + cnodeid_t candidate; /* possible canidate */ +#ifndef BRINGUP + cnodeid_t visited_cnodes[MAX_NASIDS], /* nodes seen so far */ + center, /* node we are on */ + candidate; /* possible canidate */ + int num_visited_cnodes = 0; /* # nodes seen */ + + int radius = 1, /* start looking at the + * current node + */ + maxradius = physmem_maxradius(); + void *rv; +#endif /* BRINGUP */ + int which_subnode = SUBNODE_ANY; + +#if CONFIG_IA64_SGI_IO /* SN1 + pcibr Addressing Limitation */ + { + devfs_handle_t pconn_vhdl; + pcibr_soft_t pcibr_soft; + + /* + * This combination of SN1 and Bridge hardware has an odd "limitation". + * Due to the choice of addresses for PI0 and PI1 registers on SN1 + * and historical limitations in Bridge, Bridge is unable to + * send interrupts to both PI0 CPUs and PI1 CPUs -- we have + * to choose one set or the other. That choice is implicitly + * made when Bridge first attaches its error interrupt. After + * that point, all subsequent interrupts are restricted to the + * same PI number (though it's possible to send interrupts to + * the same PI number on a different node). + * + * Since neither SN1 nor Bridge designers are willing to admit a + * bug, we can't really call this a "workaround". It's a permanent + * solution for an SN1-specific and Bridge-specific hardware + * limitation that won't ever be lifted. + */ + if ((hwgraph_edge_get(dev, EDGE_LBL_PCI, &pconn_vhdl) == GRAPH_SUCCESS) && + ((pcibr_soft = pcibr_soft_get(pconn_vhdl)) != NULL)) { + /* + * We "know" that the error interrupt is the first + * interrupt set up by pcibr_attach. Send all interrupts + * on this bridge to the same subnode number. + */ + if (pcibr_soft->bsi_err_intr) { + which_subnode = cputosubnode(((hub_intr_t) pcibr_soft->bsi_err_intr)->i_cpuid); + } + } + } +#endif /* CONFIG_IA64_SGI_IO */ + +#ifndef CONFIG_IA64_SGI_IO + /* + * If an interrupt target was specified for this + * interrupt allocation, try to use it. + */ + if (dev_desc) { + + /* Try to see if the interrupt target specified in the + * device descriptor is a legal candidate. + */ + cpuid = intr_bit_reserve_test(intr_target_from_desc(dev_desc, which_subnode), + which_subnode, + CNODEID_NONE, + req_bit, + intr_resflags, + owner_dev, + intr_name, + resp_bit); + + if (cpuid != CPU_NONE) { + if (cpu_on_subnode(cpuid, which_subnode)) + return(cpuid); /* got a valid interrupt target */ + + printk("Override explicit interrupt targetting: %v (0x%x)\n", + owner_dev, owner_dev); + + intr_unreserve_level(cpuid, *resp_bit); + } + + /* Fall through on to the next step in the search for + * the interrupt candidate. + */ + + } +#endif /* CONFIG_IA64_SGI_IO */ + + /* Check if we can find a valid interrupt target candidate on + * the master node for the device. + */ + cpuid = intr_bit_reserve_test(CPU_NONE, + which_subnode, + master_node_get(dev), + req_bit, + intr_resflags, + owner_dev, + intr_name, + resp_bit); + +printk("SHIT: cpuid = %d, bit = %d\n",cpuid, *resp_bit); + if (cpuid != CPU_NONE) { + if (cpu_on_subnode(cpuid, which_subnode)) + return(cpuid); /* got a valid interrupt target */ + else + intr_unreserve_level(cpuid, *resp_bit); + } + + printk("Cannot target interrupts to closest node: %ld (0x%lx)\n", + (long) owner_dev, (unsigned long)owner_dev); + + /* Fall through into the default algorithm + * (exhaustive-search-for-the-nearest-possible-interrupt-target) + * for finding the interrupt target + */ + +#ifndef BRINGUP + // Use of this algorithm is deferred until the supporting + // code has been implemented. + /* + * No valid interrupt specification exists. + * Try to find a node which is closest to the current node + * which can process interrupts from a device + */ + + center = cpuid_to_cnodeid(smp_processor_id()); + while (radius <= maxradius) { + + /* Try to find a node at the given radius and which + * we haven't seen already. + */ + rv = physmem_select_neighbor_node(center,radius,&candidate, + intr_cnode_seen, + (void *)visited_cnodes, + (void *)&num_visited_cnodes); + if (!rv) { + /* We have seen all the nodes at this particular radius + * Go on to the next radius level. + */ + radius++; + continue; + } + /* We are seeing this candidate cnode for the first time + */ + visited_cnodes[num_visited_cnodes++] = candidate; + + cpuid = intr_bit_reserve_test(CPU_NONE, + which_subnode, + candidate, + req_bit, + intr_resflags, + owner_dev, + intr_name, + resp_bit); + + if (cpuid != CPU_NONE) { + if (cpu_on_subnode(cpuid, which_subnode)) + return(cpuid); /* got a valid interrupt target */ + else + intr_unreserve_level(cpuid, *resp_bit); + } + } +#else /* BRINGUP */ + { + // Do a stupid round-robin assignment of the node. + static cnodeid_t last_node = 0; + + if (last_node > numnodes) last_node = 0; + for (candidate = last_node; candidate <= numnodes; candidate++) { + cpuid = intr_bit_reserve_test(CPU_NONE, + which_subnode, + candidate, + req_bit, + intr_resflags, + owner_dev, + intr_name, + resp_bit); + + if (cpuid != CPU_NONE) { + if (cpu_on_subnode(cpuid, which_subnode)) { + last_node++; + return(cpuid); /* got a valid interrupt target */ + } + else + intr_unreserve_level(cpuid, *resp_bit); + } + last_node++; + } + } +#endif + + printk("Cannot target interrupts to any close node: %ld (0x%lx)\n", + (long)owner_dev, (unsigned long)owner_dev); + + /* In the worst case try to allocate interrupt bits on the + * master processor's node. We may get here during error interrupt + * allocation phase when the topology matrix is not yet setup + * and hence cannot do an exhaustive search. + */ + ASSERT(cpu_allows_intr(master_procid)); + cpuid = intr_bit_reserve_test(master_procid, + which_subnode, + CNODEID_NONE, + req_bit, + intr_resflags, + owner_dev, + intr_name, + resp_bit); + + if (cpuid != CPU_NONE) { + if (cpu_on_subnode(cpuid, which_subnode)) + return(cpuid); + else + intr_unreserve_level(cpuid, *resp_bit); + } + + printk("Cannot target interrupts: %ld (0x%lx)\n", + (long)owner_dev, (unsigned long)owner_dev); + + return(CPU_NONE); /* Should never get here */ +} + + + + +#ifndef BRINGUP +/* + * Should never receive an exception while running on the idle + * stack. It IS possible to handle *interrupts* while on the + * idle stack, but a non-interrupt *exception* is a problem. + */ +void +idle_err(inst_t *epc, uint cause, void *fep, void *sp) +{ + eframe_t *ep = (eframe_t *)fep; + + if ((cause & CAUSE_EXCMASK) == EXC_IBE || + (cause & CAUSE_EXCMASK) == EXC_DBE) { + (void)dobuserre((eframe_t *)ep, epc, 0); + } + + /* XXX - This will have to change to deal with various SN errors. */ + panic( "exception on IDLE stack " + "ep:0x%x epc:0x%x cause:0x%w32x sp:0x%x badvaddr:0x%x", + ep, epc, cause, sp, getbadvaddr()); + /* NOTREACHED */ +} + + +/* + * earlynofault - handle very early global faults - usually just while + * sizing memory + * Returns: 1 if should do nofault + * 0 if not + */ +/* ARGSUSED */ +int +earlynofault(eframe_t *ep, uint code) +{ + switch(code) { + case EXC_DBE: + return(1); + default: + return(0); + } +} + + + +/* ARGSUSED */ +static void +cpuintr(void *arg1, void *arg2) +{ +#if RTE + static int rte_intrdebug = 1; +#endif + /* + * Frame Scheduler + */ + LOG_TSTAMP_EVENT(RTMON_INTR, TSTAMP_EV_CPUINTR, NULL, NULL, + NULL, NULL); + + /* + * Hardware clears the IO interrupts, but we need to clear software- + * generated interrupts. + */ + LOCAL_HUB_CLR_INTR(CPU_ACTION_A + cputolocalslice(cpuid())); + +#if 0 + /* XXX - Handle error interrupts. */ + if (error_intr_reason) + error_intr(); +#endif /* 0 */ + + /* + * If we're headed for panicspin and it is due to a NMI, save the + * eframe in the NMI area + */ + if (private.p_va_panicspin && nmied) { + caddr_t nmi_save_area; + + nmi_save_area = (caddr_t) (TO_UNCAC(TO_NODE( + cputonasid(cpuid()), IP27_NMI_EFRAME_OFFSET)) + + cputoslice(cpuid()) * IP27_NMI_EFRAME_SIZE); + bcopy((caddr_t) arg2, nmi_save_area, sizeof(eframe_t)); + } + + doacvec(); +#if RTE + if (private.p_flags & PDAF_ISOLATED && !rte_intrdebug) + goto end_cpuintr; +#endif + doactions(); +#if RTE +end_cpuintr: +#endif + LOG_TSTAMP_EVENT(RTMON_INTR, TSTAMP_EV_INTREXIT, TSTAMP_EV_CPUINTR, NULL, NULL, NULL); +} + +void +install_cpuintr(cpuid_t cpu) +{ + int intr_bit = CPU_ACTION_A + cputolocalslice(cpu); + + if (intr_connect_level(cpu, intr_bit, INTPEND0_MAXMASK, + (intr_func_t) cpuintr, NULL, NULL)) + panic("install_cpuintr: Can't connect interrupt."); +} +#endif /* BRINGUP */ + +#ifdef DEBUG_INTR_TSTAMP +/* We allocate an array, but only use element number 64. This guarantees that + * the entry is in a cacheline by itself. + */ +#define DINTR_CNTIDX 32 +#define DINTR_TSTAMP1 48 +#define DINTR_TSTAMP2 64 +volatile long long dintr_tstamp_cnt[128]; +int dintr_debug_output=0; +extern void idbg_tstamp_debug(void); +#ifdef SPLDEBUG +extern void idbg_splx_log(int); +#endif +#if DEBUG_INTR_TSTAMP_DEBUG +int dintr_enter_symmon=1000; /* 1000 microseconds is 1 millisecond */ +#endif + +#ifndef BRINGUP +/* ARGSUSED */ +static void +cpulatintr(void *arg) +{ + /* + * Hardware only clears IO interrupts so we have to clear our level + * here. + */ + LOCAL_HUB_CLR_INTR(CPU_INTRLAT_A + cputolocalslice(cpuid())); + +#if DEBUG_INTR_TSTAMP_DEBUG + dintr_tstamp_cnt[DINTR_TSTAMP2] = GET_LOCAL_RTC; + if ((dintr_tstamp_cnt[DINTR_TSTAMP2] - dintr_tstamp_cnt[DINTR_TSTAMP1]) + > dintr_enter_symmon) { +#ifdef SPLDEBUG + extern int spldebug_log_off; + + spldebug_log_off = 1; +#endif /* SPLDEBUG */ + debug("ring"); +#ifdef SPLDEBUG + spldebug_log_off = 0; +#endif /* SPLDEBUG */ + } +#endif + dintr_tstamp_cnt[DINTR_CNTIDX]++; + + return; +} + +static int install_cpulat_first=0; + +void +install_cpulatintr(cpuid_t cpu) +{ + int intr_bit; + devfs_handle_t cpuv = cpuid_to_vertex(cpu); + + intr_bit = CPU_INTRLAT_A + cputolocalslice(cpu); + if (intr_bit != intr_reserve_level(cpu, intr_bit, II_THREADED, + cpuv, "intrlat")) + panic( "install_cpulatintr: Can't reserve interrupt."); + + if (intr_connect_level(cpu, intr_bit, INTPEND0_MAXMASK, + cpulatintr, NULL, NULL)) + panic( "install_cpulatintr: Can't connect interrupt."); + + if (!install_cpulat_first) { + install_cpulat_first++; + idbg_addfunc("tstamp_debug", (void (*)())idbg_tstamp_debug); +#if defined(SPLDEBUG) || defined(SPLDEBUG_CPU_EVENTS) + idbg_addfunc("splx_log", (void (*)())idbg_splx_log); +#endif /* SPLDEBUG || SPLDEBUG_CPU_EVENTS */ + } +} +#endif /* BRINGUP */ + +#endif /* DEBUG_INTR_TSTAMP */ + +#ifndef BRINGUP +/* ARGSUSED */ +static void +dbgintr(void *arg) +{ + /* + * Hardware only clears IO interrupts so we have to clear our level + * here. + */ + LOCAL_HUB_CLR_INTR(N_INTPEND_BITS + DEBUG_INTR_A + cputolocalslice(cpuid())); + + debug("zing"); + return; +} + + +void +install_dbgintr(cpuid_t cpu) +{ + int intr_bit; + devfs_handle_t cpuv = cpuid_to_vertex(cpu); + + intr_bit = N_INTPEND_BITS + DEBUG_INTR_A + cputolocalslice(cpu); + if (intr_bit != intr_reserve_level(cpu, intr_bit, 1, cpuv, "DEBUG")) + panic("install_dbgintr: Can't reserve interrupt. " + " intr_bit %d" ,intr_bit); + + if (intr_connect_level(cpu, intr_bit, INTPEND1_MAXMASK, + dbgintr, NULL, NULL)) + panic("install_dbgintr: Can't connect interrupt."); + +#ifdef DEBUG_INTR_TSTAMP + /* Set up my interrupt latency test interrupt */ + install_cpulatintr(cpu); +#endif +} + +/* ARGSUSED */ +static void +tlbintr(void *arg) +{ + extern void tlbflush_rand(void); + + /* + * Hardware only clears IO interrupts so we have to clear our level + * here. + */ + LOCAL_HUB_CLR_INTR(N_INTPEND_BITS + TLB_INTR_A + cputolocalslice(cpuid())); + + tlbflush_rand(); + return; +} + + +void +install_tlbintr(cpuid_t cpu) +{ + int intr_bit; + devfs_handle_t cpuv = cpuid_to_vertex(cpu); + + intr_bit = N_INTPEND_BITS + TLB_INTR_A + cputolocalslice(cpu); + if (intr_bit != intr_reserve_level(cpu, intr_bit, 1, cpuv, "DEBUG")) + panic("install_tlbintr: Can't reserve interrupt. " + " intr_bit %d" ,intr_bit); + + if (intr_connect_level(cpu, intr_bit, INTPEND1_MAXMASK, + tlbintr, NULL, NULL)) + panic("install_tlbintr: Can't connect interrupt."); + +} + + +/* + * Send an interrupt to all nodes. Don't panic if we get an error. + * Returns 1 if any exceptions occurred. + */ +int +protected_broadcast(hubreg_t intrbit) +{ + nodepda_t *npdap = private.p_nodepda; + int byte, bit, sn; + int error = 0; + + extern int _wbadaddr_val(volatile void *, int, volatile int *); + + /* Send rather than clear an interrupt. */ + intrbit |= 0x100; + + for (byte = 0; byte < NASID_MASK_BYTES; byte++) { + for (bit = 0; bit < 8; bit++) { + if (npdap->nasid_mask[byte] & (1 << bit)) { + nasid_t nasid = byte * 8 + bit; + for (sn=0; snii_name, + vector->iv_func, vector->iv_arg, vector->iv_prefunc); + pf(" vertex 0x%x %s%s", + info->ii_owner_dev, + ((info->ii_flags) & II_RESERVE) ? "R" : "U", + ((info->ii_flags) & II_INUSE) ? "C" : "-"); + pf("%s%s%s%s", + ip & value ? "P" : "-", + ima & value ? "A" : "-", + imb & value ? "B" : "-", + ((info->ii_flags) & II_ERRORINT) ? "E" : "-"); + pf("\n"); +} + + +/* + * Dump information about interrupt vector assignment. + */ +void +intr_dumpvec(cnodeid_t cnode, void (*pf)(char *, ...)) +{ + nodepda_t *npda; + int ip, sn, bit; + intr_vecblk_t *dispatch; + hubreg_t ipr, ima, imb; + nasid_t nasid; + + if ((cnode < 0) || (cnode >= numnodes)) { + pf("intr_dumpvec: cnodeid out of range: %d\n", cnode); + return ; + } + + nasid = COMPACT_TO_NASID_NODEID(cnode); + + if (nasid == INVALID_NASID) { + pf("intr_dumpvec: Bad cnodeid: %d\n", cnode); + return ; + } + + + npda = NODEPDA(cnode); + + for (sn = 0; sn < NUM_SUBNODES; sn++) { + for (ip = 0; ip < 2; ip++) { + dispatch = ip ? &(SNPDA(npda,sn)->intr_dispatch1) : &(SNPDA(npda,sn)->intr_dispatch0); + ipr = REMOTE_HUB_PI_L(nasid, sn, ip ? PI_INT_PEND1 : PI_INT_PEND0); + ima = REMOTE_HUB_PI_L(nasid, sn, ip ? PI_INT_MASK1_A : PI_INT_MASK0_A); + imb = REMOTE_HUB_PI_L(nasid, sn, ip ? PI_INT_MASK1_B : PI_INT_MASK0_B); + + pf("Node %d INT_PEND%d:\n", cnode, ip); + + if (dispatch->ithreads_enabled) + pf(" Ithreads enabled\n"); + else + pf(" Ithreads disabled\n"); + pf(" vector_count = %d, vector_state = %d\n", + dispatch->vector_count, + dispatch->vector_state); + pf(" CPU A count %d, CPU B count %d\n", + dispatch->cpu_count[0], + dispatch->cpu_count[1]); + pf(" &vector_lock = 0x%x\n", + &(dispatch->vector_lock)); + for (bit = 0; bit < N_INTPEND_BITS; bit++) { + if ((dispatch->info[bit].ii_flags & II_RESERVE) || + (ipr & (1L << bit))) { + dump_vector(&(dispatch->info[bit]), + &(dispatch->vectors[bit]), + bit, ipr, ima, imb, pf); + } + } + pf("\n"); + } + } +} + diff -urN linux-2.4.0-test10/arch/ia64/sn/io/ml_iograph.c linux-2.4.0-test10-lia/arch/ia64/sn/io/ml_iograph.c --- linux-2.4.0-test10/arch/ia64/sn/io/ml_iograph.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/ml_iograph.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,1579 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int maxnodes; + +/* #define PROBE_TEST */ + +/* At most 2 hubs can be connected to an xswitch */ +#define NUM_XSWITCH_VOLUNTEER 2 + +/* + * Track which hubs have volunteered to manage devices hanging off of + * a Crosstalk Switch (e.g. xbow). This structure is allocated, + * initialized, and hung off the xswitch vertex early on when the + * xswitch vertex is created. + */ +typedef struct xswitch_vol_s { + struct semaphore xswitch_volunteer_mutex; + int xswitch_volunteer_count; + devfs_handle_t xswitch_volunteer[NUM_XSWITCH_VOLUNTEER]; +} *xswitch_vol_t; + +void +xswitch_vertex_init(devfs_handle_t xswitch) +{ + xswitch_vol_t xvolinfo; + int rc; + + xvolinfo = kmalloc(sizeof(struct xswitch_vol_s), GFP_KERNEL); + init_MUTEX(&xvolinfo->xswitch_volunteer_mutex); + xvolinfo->xswitch_volunteer_count = 0; + rc = hwgraph_info_add_LBL(xswitch, + INFO_LBL_XSWITCH_VOL, + (arbitrary_info_t)xvolinfo); + ASSERT(rc == GRAPH_SUCCESS); rc = rc; +} + + +/* + * When assignment of hubs to widgets is complete, we no longer need the + * xswitch volunteer structure hanging around. Destroy it. + */ +static void +xswitch_volunteer_delete(devfs_handle_t xswitch) +{ + xswitch_vol_t xvolinfo; + int rc; + + rc = hwgraph_info_remove_LBL(xswitch, + INFO_LBL_XSWITCH_VOL, + (arbitrary_info_t *)&xvolinfo); +#ifndef CONFIG_IA64_SGI_IO + ASSERT(rc == GRAPH_SUCCESS); rc = rc; +#endif + + kfree(xvolinfo); +} +/* + * A Crosstalk master volunteers to manage xwidgets on the specified xswitch. + */ +/* ARGSUSED */ +static void +volunteer_for_widgets(devfs_handle_t xswitch, devfs_handle_t master) +{ + xswitch_vol_t xvolinfo = NULL; + + (void)hwgraph_info_get_LBL(xswitch, + INFO_LBL_XSWITCH_VOL, + (arbitrary_info_t *)&xvolinfo); + if (xvolinfo == NULL) { +#ifndef CONFIG_IA64_SGI_IO + if (!is_headless_node_vertex(master)) + cmn_err(CE_WARN, + "volunteer for widgets: vertex %v has no info label", + xswitch); +#endif + return; + } + +#ifndef CONFIG_IA64_SGI_IO + mutex_lock(&xvolinfo->xswitch_volunteer_mutex, PZERO); +#endif + ASSERT(xvolinfo->xswitch_volunteer_count < NUM_XSWITCH_VOLUNTEER); + xvolinfo->xswitch_volunteer[xvolinfo->xswitch_volunteer_count] = master; + xvolinfo->xswitch_volunteer_count++; +#ifndef CONFIG_IA64_SGI_IO + mutex_unlock(&xvolinfo->xswitch_volunteer_mutex); +#endif +} + +#ifndef BRINGUP +/* + * The "ideal fixed assignment" of 12 IO slots to 4 node slots. + * At index N is the node slot number of the node board that should + * ideally control the widget in IO slot N. Note that if there is + * only one node board on a given xbow, it will control all of the + * devices on that xbow regardless of these defaults. + * + * N1 controls IO slots IO1, IO3, IO5 (upper left) + * N3 controls IO slots IO2, IO4, IO6 (upper right) + * N2 controls IO slots IO7, IO9, IO11 (lower left) + * N4 controls IO slots IO8, IO10, IO12 (lower right) + * + * This makes assignments predictable and easily controllable. + * TBD: Allow administrator to override these defaults. + */ +static slotid_t ideal_assignment[] = { + -1, /* IO0 -->non-existent */ + 1, /* IO1 -->N1 */ + 3, /* IO2 -->N3 */ + 1, /* IO3 -->N1 */ + 3, /* IO4 -->N3 */ + 1, /* IO5 -->N1 */ + 3, /* IO6 -->N3 */ + 2, /* IO7 -->N2 */ + 4, /* IO8 -->N4 */ + 2, /* IO9 -->N2 */ + 4, /* IO10-->N4 */ + 2, /* IO11-->N2 */ + 4 /* IO12-->N4 */ +}; + +static int +is_ideal_assignment(slotid_t hubslot, slotid_t ioslot) +{ + return(ideal_assignment[ioslot] == hubslot); +} +#endif /* ifndef BRINGUP */ + +extern int xbow_port_io_enabled(nasid_t nasid, int widgetnum); + +/* + * Assign all the xwidgets hanging off the specified xswitch to the + * Crosstalk masters that have volunteered for xswitch duty. + */ +/* ARGSUSED */ +static void +assign_widgets_to_volunteers(devfs_handle_t xswitch, devfs_handle_t hubv) +{ + xswitch_info_t xswitch_info; + xswitch_vol_t xvolinfo = NULL; + xwidgetnum_t widgetnum; + int curr_volunteer, num_volunteer; + nasid_t nasid; + hubinfo_t hubinfo; +#ifndef BRINGUP + int xbownum; +#endif + + hubinfo_get(hubv, &hubinfo); + nasid = hubinfo->h_nasid; + + xswitch_info = xswitch_info_get(xswitch); + ASSERT(xswitch_info != NULL); + + (void)hwgraph_info_get_LBL(xswitch, + INFO_LBL_XSWITCH_VOL, + (arbitrary_info_t *)&xvolinfo); + if (xvolinfo == NULL) { +#ifndef CONFIG_IA64_SGI_IO + if (!is_headless_node_vertex(hubv)) + cmn_err(CE_WARN, + "assign_widgets_to_volunteers:vertex %v has " + " no info label", + xswitch); +#endif + return; + } + + num_volunteer = xvolinfo->xswitch_volunteer_count; + ASSERT(num_volunteer > 0); + curr_volunteer = 0; + + /* Assign master hub for xswitch itself. */ + if (HUB_WIDGET_ID_MIN > 0) { + hubv = xvolinfo->xswitch_volunteer[0]; + xswitch_info_master_assignment_set(xswitch_info, (xwidgetnum_t)0, hubv); + } + +#ifndef BRINGUP + xbownum = get_node_crossbow(nasid); +#endif /* ifndef BRINGUP */ + + /* + * TBD: Use administrative information to alter assignment of + * widgets to hubs. + */ + for (widgetnum=HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) { + +#ifndef BRINGUP + int i; +#endif + /* + * Ignore disabled/empty ports. + */ + if (!xbow_port_io_enabled(nasid, widgetnum)) + continue; + + /* + * If this is the master IO board, assign it to the same + * hub that owned it in the prom. + */ + if (is_master_nasid_widget(nasid, widgetnum)) { + int i; + + for (i=0; ixswitch_volunteer[i]; + hubinfo_get(hubv, &hubinfo); + nasid = hubinfo->h_nasid; + if (nasid == get_console_nasid()) + goto do_assignment; + } +#ifndef CONFIG_IA64_SGI_IO + cmn_err(CE_PANIC, + "Nasid == %d, console nasid == %d", + nasid, get_console_nasid()); +#endif + } + +#ifndef BRINGUP + /* + * Try to do the "ideal" assignment if IO slots to nodes. + */ + for (i=0; ixswitch_volunteer[i]; + hubinfo_get(hubv, &hubinfo); + nasid = hubinfo->h_nasid; + if (is_ideal_assignment(SLOTNUM_GETSLOT(get_node_slotid(nasid)), + SLOTNUM_GETSLOT(get_widget_slotnum(xbownum, widgetnum)))) { + + goto do_assignment; + + } + } +#endif /* ifndef BRINGUP */ + + /* + * Do a round-robin assignment among the volunteer nodes. + */ + hubv = xvolinfo->xswitch_volunteer[curr_volunteer]; + curr_volunteer = (curr_volunteer + 1) % num_volunteer; + /* fall through */ + +do_assignment: + /* + * At this point, we want to make hubv the master of widgetnum. + */ + xswitch_info_master_assignment_set(xswitch_info, widgetnum, hubv); + } + + xswitch_volunteer_delete(xswitch); +} + +/* + * Early iograph initialization. Called by master CPU in mlreset(). + * Useful for including iograph.o in kernel.o. + */ +void +iograph_early_init(void) +{ +/* + * Need new way to get this information .. + */ + cnodeid_t cnode; + nasid_t nasid; + lboard_t *board; + + /* + * Init. the board-to-hwgraph link early, so FRU analyzer + * doesn't trip on leftover values if we panic early on. + */ + for(cnode = 0; cnode < numnodes; cnode++) { + nasid = COMPACT_TO_NASID_NODEID(cnode); + board = (lboard_t *)KL_CONFIG_INFO(nasid); + printk("iograph_early_init: Found board 0x%p\n", board); + + /* Check out all the board info stored on a node */ + while(board) { + board->brd_graph_link = GRAPH_VERTEX_NONE; + board = KLCF_NEXT(board); + printk("iograph_early_init: Found board 0x%p\n", board); + + + } + } + + hubio_init(); +} + +#ifndef CONFIG_IA64_SGI_IO +/* There is an identical definition of this in os/scheduler/runq.c */ +#define INIT_COOKIE(cookie) cookie.must_run = 0; cookie.cpu = PDA_RUNANYWHERE +/* + * These functions absolutely doesn't belong here. It's here, though, + * until the scheduler provides a platform-independent version + * that works the way it should. The interface will definitely change, + * too. Currently used only in this file and by io/cdl.c in order to + * bind various I/O threads to a CPU on the proper node. + */ +cpu_cookie_t +setnoderun(cnodeid_t cnodeid) +{ + int i; + cpuid_t cpunum; + cpu_cookie_t cookie; + + INIT_COOKIE(cookie); + if (cnodeid == CNODEID_NONE) + return(cookie); + + /* + * Do a setmustrun to one of the CPUs on the specified + * node. + */ + if ((cpunum = CNODE_TO_CPU_BASE(cnodeid)) == CPU_NONE) { + return(cookie); + } + + cpunum += CNODE_NUM_CPUS(cnodeid) - 1; + + for (i = 0; i < CNODE_NUM_CPUS(cnodeid); i++, cpunum--) { + + if (cpu_enabled(cpunum)) { + cookie = setmustrun(cpunum); + break; + } + } + + return(cookie); +} + +void +restorenoderun(cpu_cookie_t cookie) +{ + restoremustrun(cookie); +} +static sema_t io_init_sema; + +#endif /* !CONFIG_IA64_SGI_IO */ + +struct semaphore io_init_sema; + + +/* + * Let boot processor know that we're done initializing our node's IO + * and then exit. + */ +/* ARGSUSED */ +static void +io_init_done(cnodeid_t cnodeid,cpu_cookie_t c) +{ +#ifndef CONFIG_IA64_SGI_IO + /* Let boot processor know that we're done. */ + up(&io_init_sema); + /* This is for the setnoderun done when the io_init thread + * started + */ + restorenoderun(c); + sthread_exit(); +#endif +} + +/* + * Probe to see if this hub's xtalk link is active. If so, + * return the Crosstalk Identification of the widget that we talk to. + * This is called before any of the Crosstalk infrastructure for + * this hub is set up. It's usually called on the node that we're + * probing, but not always. + * + * TBD: Prom code should actually do this work, and pass through + * hwid for our use. + */ +static void +early_probe_for_widget(devfs_handle_t hubv, xwidget_hwid_t hwid) +{ + hubreg_t llp_csr_reg; + nasid_t nasid; + hubinfo_t hubinfo; + + hubinfo_get(hubv, &hubinfo); + nasid = hubinfo->h_nasid; + + llp_csr_reg = REMOTE_HUB_L(nasid, IIO_LLP_CSR); + /* + * If link is up, read the widget's part number. + * A direct connect widget must respond to widgetnum=0. + */ + if (llp_csr_reg & IIO_LLP_CSR_IS_UP) { + /* TBD: Put hub into "indirect" mode */ + /* + * We're able to read from a widget because our hub's + * WIDGET_ID was set up earlier. + */ +#ifdef BRINGUP + widgetreg_t widget_id = *(volatile widgetreg_t *) + (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID); + + printk("early_probe_for_widget: Hub Vertex 0x%p is UP widget_id = 0x%x Register 0x%p\n", hubv, widget_id, + (volatile widgetreg_t *)(RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID) ); + +#else /* !BRINGUP */ + widgetreg_t widget_id = XWIDGET_ID_READ(nasid, 0); +#endif /* BRINGUP */ + + hwid->part_num = XWIDGET_PART_NUM(widget_id); + hwid->rev_num = XWIDGET_REV_NUM(widget_id); + hwid->mfg_num = XWIDGET_MFG_NUM(widget_id); + + /* TBD: link reset */ + } else { + + panic("\n\n**** early_probe_for_widget: Hub Vertex 0x%p is DOWN llp_csr_reg 0x%x ****\n\n", hubv, llp_csr_reg); + + hwid->part_num = XWIDGET_PART_NUM_NONE; + hwid->rev_num = XWIDGET_REV_NUM_NONE; + hwid->mfg_num = XWIDGET_MFG_NUM_NONE; + } + +} + +/* Add inventory information to the widget vertex + * Right now (module,slot,revision) is being + * added as inventory information. + */ +static void +xwidget_inventory_add(devfs_handle_t widgetv, + lboard_t *board, + struct xwidget_hwid_s hwid) +{ + if (!board) + return; + /* Donot add inventory information for the baseio + * on a speedo with an xbox. It has already been + * taken care of in SN00_vmc. + * Speedo with xbox's baseio comes in at slot io1 (widget 9) + */ + device_inventory_add(widgetv,INV_IOBD,board->brd_type, + board->brd_module, + SLOTNUM_GETSLOT(board->brd_slot), + hwid.rev_num); +} + +/* + * io_xswitch_widget_init + * + */ + +/* defined in include/linux/ctype.h */ +/* #define toupper(c) (islower(c) ? (c) - 'a' + 'A' : (c)) */ + +void +io_xswitch_widget_init(devfs_handle_t xswitchv, + devfs_handle_t hubv, + xwidgetnum_t widgetnum, + async_attach_t aa) +{ + xswitch_info_t xswitch_info; + xwidgetnum_t hub_widgetid; + devfs_handle_t widgetv; + cnodeid_t cnode; + widgetreg_t widget_id; + nasid_t nasid, peer_nasid; + struct xwidget_hwid_s hwid; + hubinfo_t hubinfo; + /*REFERENCED*/ + int rc; + char slotname[SLOTNUM_MAXLENGTH]; + char pathname[128]; + char new_name[64]; + moduleid_t module; + slotid_t slot; + lboard_t *board = NULL; + + printk("\nio_xswitch_widget_init: hubv 0x%p, xswitchv 0x%p, widgetnum 0x%x\n", hubv, xswitchv, widgetnum); + /* + * Verify that xswitchv is indeed an attached xswitch. + */ + xswitch_info = xswitch_info_get(xswitchv); + ASSERT(xswitch_info != NULL); + + hubinfo_get(hubv, &hubinfo); + nasid = hubinfo->h_nasid; + cnode = NASID_TO_COMPACT_NODEID(nasid); + hub_widgetid = hubinfo->h_widgetid; + + + /* Who's the other guy on out crossbow (if anyone) */ + peer_nasid = NODEPDA(cnode)->xbow_peer; + if (peer_nasid == INVALID_NASID) + /* If I don't have a peer, use myself. */ + peer_nasid = nasid; + + + /* Check my xbow structure and my peer's */ + if (!xbow_port_io_enabled(nasid, widgetnum) && + !xbow_port_io_enabled(peer_nasid, widgetnum)) { + return; + } + + if (xswitch_info_link_ok(xswitch_info, widgetnum)) { + char name[4]; + /* + * If the current hub is not supposed to be the master + * for this widgetnum, then skip this widget. + */ + if (xswitch_info_master_assignment_get(xswitch_info, + widgetnum) != hubv) { + return; + } + + module = NODEPDA(cnode)->module_id; +#ifdef XBRIDGE_REGS_SIM + /* hardwire for now...could do this with something like: + * xbow_soft_t soft = hwgraph_fastinfo_get(vhdl); + * xbow_t xbow = soft->base; + * xbowreg_t xwidget_id = xbow->xb_wid_id; + * but I don't feel like figuring out vhdl right now.. + * and I know for a fact the answer is 0x2d000049 + */ + printk("io_xswitch_widget_init: XBRIDGE_REGS_SIM FIXME: reading xwidget id: hardwired to xbridge (0x2d000049).\n"); + printk("XWIDGET_PART_NUM(0x2d000049)= 0x%x\n", XWIDGET_PART_NUM(0x2d000049)); + if (XWIDGET_PART_NUM(0x2d000049)==XXBOW_WIDGET_PART_NUM) { +#else + if (nasid_has_xbridge(nasid)) { +#endif /* XBRIDGE_REGS_SIM */ + board = find_lboard_module_class( + (lboard_t *)KL_CONFIG_INFO(nasid), + module, + KLTYPE_IOBRICK); + + if (board) + printk("io_xswitch_widget_init: Found KLTYPE_IOBRICK Board 0x%p brd_type 0x%x\n", board, board->brd_type); + + /* + * BRINGUP + * Make sure we really want to say xbrick, pbrick, + * etc. rather than XIO, graphics, etc. + */ + +#ifdef SUPPORT_PRINTING_M_FORMAT + sprintf(pathname, EDGE_LBL_MODULE "/%M/" +#else + sprintf(pathname, EDGE_LBL_MODULE "/%x/" +#endif + "%cbrick" "/%s/%d", + NODEPDA(cnode)->module_id, +#ifdef BRINGUP + + (board->brd_type == KLTYPE_IBRICK) ? 'I' : + (board->brd_type == KLTYPE_PBRICK) ? 'P' : + (board->brd_type == KLTYPE_XBRICK) ? 'X' : '?', +#else + toupper(MODULE_GET_BTCHAR(NODEPDA(cnode)->module_id)), +#endif /* BRINGUP */ + EDGE_LBL_XTALK, widgetnum); + } + + printk("io_xswitch_widget_init: path= %s\n", pathname); + rc = hwgraph_path_add(hwgraph_root, pathname, &widgetv); + + ASSERT(rc == GRAPH_SUCCESS); + + /* This is needed to let the user programs to map the + * module,slot numbers to the corresponding widget numbers + * on the crossbow. + */ + rc = device_master_set(hwgraph_connectpt_get(widgetv), hubv); + + /* If we are looking at the global master io6 + * then add information about the version of + * the io6prom as a part of "detailed inventory" + * information. + */ + if (is_master_baseio(nasid, + NODEPDA(cnode)->module_id, +#ifdef BRINGUP + get_widget_slotnum(0,widgetnum))) { +#else + <<< BOMB! >>> Need a new way to get slot numbers on IP35/IP37 +#endif + extern void klhwg_baseio_inventory_add(devfs_handle_t, + cnodeid_t); + module = NODEPDA(cnode)->module_id; + +#ifdef XBRIDGE_REGS_SIM + printk("io_xswitch_widget_init: XBRIDGE_REGS_SIM FIXME: reading xwidget id: hardwired to xbridge (0x2d000049).\n"); + if (XWIDGET_PART_NUM(0x2d000049)==XXBOW_WIDGET_PART_NUM) { +#else + if (nasid_has_xbridge(nasid)) { +#endif /* XBRIDGE_REGS_SIM */ + board = find_lboard_module( + (lboard_t *)KL_CONFIG_INFO(nasid), + module); + /* + * BRINGUP + * Change iobrick to correct i/o brick + */ +#ifdef SUPPORT_PRINTING_M_FORMAT + sprintf(pathname, EDGE_LBL_MODULE "/%M/" +#else + sprintf(pathname, EDGE_LBL_MODULE "/%x/" +#endif + "iobrick" "/%s/%d", + NODEPDA(cnode)->module_id, + EDGE_LBL_XTALK, widgetnum); + } else { + board = get_board_name(nasid, module, slot, + new_name); + /* + * Create the vertex for the widget, + * using the decimal + * widgetnum as the name of the primary edge. + */ +#ifdef SUPPORT_PRINTING_M_FORMAT + sprintf(pathname, EDGE_LBL_MODULE "/%M/" +#else + sprintf(pathname, EDGE_LBL_MODULE "/%x/" +#endif + EDGE_LBL_SLOT "/%s/%s", + NODEPDA(cnode)->module_id, + slotname, new_name); + } + + rc = hwgraph_path_add(hwgraph_root, pathname, &widgetv); + printk("io_xswitch_widget_init: (2) path= %s\n", pathname); + /* + * This is a weird ass code needed for error injection + * purposes. + */ + rc = device_master_set(hwgraph_connectpt_get(widgetv), hubv); + + klhwg_baseio_inventory_add(widgetv,cnode); + } + sprintf(name, "%d", widgetnum); + printk("io_xswitch_widget_init: FIXME hwgraph_edge_add %s xswitchv 0x%p, widgetv 0x%p\n", name, xswitchv, widgetv); + rc = hwgraph_edge_add(xswitchv, widgetv, name); + + /* + * crosstalk switch code tracks which + * widget is attached to each link. + */ + xswitch_info_vhdl_set(xswitch_info, widgetnum, widgetv); + + /* + * Peek at the widget to get its crosstalk part and + * mfgr numbers, then present it to the generic xtalk + * bus provider to have its driver attach routine + * called (or not). + */ +#ifdef XBRIDGE_REGS_SIM + widget_id = 0x2d000049; + printk("io_xswitch_widget_init: XBRIDGE_REGS_SIM FIXME: id hardwired to widget_id\n"); +#else + widget_id = XWIDGET_ID_READ(nasid, widgetnum); +#endif /* XBRIDGE_REGS_SIM */ + hwid.part_num = XWIDGET_PART_NUM(widget_id); + hwid.rev_num = XWIDGET_REV_NUM(widget_id); + hwid.mfg_num = XWIDGET_MFG_NUM(widget_id); + /* Store some inventory information about + * the xwidget in the hardware graph. + */ + xwidget_inventory_add(widgetv,board,hwid); + + (void)xwidget_register(&hwid, widgetv, widgetnum, + hubv, hub_widgetid, + aa); + +#ifdef SN0_USE_BTE + bte_bpush_war(cnode, (void *)board); +#endif + } + +} + + +static void +io_init_xswitch_widgets(devfs_handle_t xswitchv, cnodeid_t cnode) +{ + xwidgetnum_t widgetnum; + async_attach_t aa; + + aa = async_attach_new(); + + printk("io_init_xswitch_widgets: xswitchv 0x%p for cnode %d\n", xswitchv, cnode); + + for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; + widgetnum++) { +#ifdef BRINGUP + if (widgetnum != 0xe) + io_xswitch_widget_init(xswitchv, + cnodeid_to_vertex(cnode), + widgetnum, aa); + +#else + io_xswitch_widget_init(xswitchv, + cnodeid_to_vertex(cnode), + widgetnum, aa); +#endif /* BRINGUP */ + } + /* + * Wait for parallel attach threads, if any, to complete. + */ + async_attach_waitall(aa); + async_attach_free(aa); +} + +/* + * For each PCI bridge connected to the xswitch, add a link from the + * board's klconfig info to the bridge's hwgraph vertex. This lets + * the FRU analyzer find the bridge without traversing the hardware + * graph and risking hangs. + */ +static void +io_link_xswitch_widgets(devfs_handle_t xswitchv, cnodeid_t cnodeid) +{ + xwidgetnum_t widgetnum; + char pathname[128]; + devfs_handle_t vhdl; + nasid_t nasid, peer_nasid; + lboard_t *board; + + + + /* And its connected hub's nasids */ + nasid = COMPACT_TO_NASID_NODEID(cnodeid); + peer_nasid = NODEPDA(cnodeid)->xbow_peer; + + /* + * Look for paths matching "/pci" under xswitchv. + * For every widget, init. its lboard's hwgraph link. If the + * board has a PCI bridge, point the link to it. + */ + for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; + widgetnum++) { + sprintf(pathname, "%d", widgetnum); + if (hwgraph_traverse(xswitchv, pathname, &vhdl) != + GRAPH_SUCCESS) + continue; + +#if defined (CONFIG_SGI_IP35) || defined (CONFIG_IA64_SGI_SN1) || defined (CONFIG_IA64_GENERIC) + board = find_lboard_module((lboard_t *)KL_CONFIG_INFO(nasid), + NODEPDA(cnodeid)->module_id); +#else + { + slotid_t slot; + slot = get_widget_slotnum(xbow_num, widgetnum); + board = find_lboard_modslot((lboard_t *)KL_CONFIG_INFO(nasid), + NODEPDA(cnodeid)->module_id, slot); + } +#endif /* CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 */ + if (board == NULL && peer_nasid != INVALID_NASID) { + /* + * Try to find the board on our peer + */ +#if defined (CONFIG_SGI_IP35) || defined (CONFIG_IA64_SGI_SN1) || defined (CONFIG_IA64_GENERIC) + board = find_lboard_module( + (lboard_t *)KL_CONFIG_INFO(peer_nasid), + NODEPDA(cnodeid)->module_id); + +#else + board = find_lboard_modslot((lboard_t *)KL_CONFIG_INFO(peer_nasid), + NODEPDA(cnodeid)->module_id, slot); + +#endif /* CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 */ + } + if (board == NULL) { +#ifndef CONFIG_IA64_SGI_IO + cmn_err(CE_WARN, + "Could not find PROM info for vertex %v, " + "FRU analyzer may fail", + vhdl); +#endif + return; + } + + sprintf(pathname, "%d/"EDGE_LBL_PCI, widgetnum); + if (hwgraph_traverse(xswitchv, pathname, &vhdl) == + GRAPH_SUCCESS) + board->brd_graph_link = vhdl; + else + board->brd_graph_link = GRAPH_VERTEX_NONE; + } +} + +/* + * Initialize all I/O on the specified node. + */ +static void +io_init_node(cnodeid_t cnodeid) +{ + /*REFERENCED*/ + devfs_handle_t hubv, switchv, widgetv; + struct xwidget_hwid_s hwid; + hubinfo_t hubinfo; + int is_xswitch; + nodepda_t *npdap; +#ifndef CONFIG_IA64_SGI_IO + sema_t *peer_sema = 0; +#else + struct semaphore *peer_sema = 0; +#endif + uint32_t widget_partnum; + nodepda_router_info_t *npda_rip; + cpu_cookie_t c = 0; + +#ifndef CONFIG_IA64_SGI_IO + /* Try to execute on the node that we're initializing. */ + c = setnoderun(cnodeid); +#endif + npdap = NODEPDA(cnodeid); + + /* + * Get the "top" vertex for this node's hardware + * graph; it will carry the per-hub hub-specific + * data, and act as the crosstalk provider master. + * It's canonical path is probably something of the + * form /hw/module/%M/slot/%d/node + */ + hubv = cnodeid_to_vertex(cnodeid); + printk("io_init_node: Initialize IO for cnode %d hubv(node) 0x%p npdap 0x%p\n", cnodeid, hubv, npdap); + + ASSERT(hubv != GRAPH_VERTEX_NONE); + +#if CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 || CONFIG_IA64_GENERIC + hubdev_docallouts(hubv); +#endif + + /* + * Set up the dependent routers if we have any. + */ + npda_rip = npdap->npda_rip_first; + + while(npda_rip) { + /* If the router info has not been initialized + * then we need to do the router initialization + */ + if (!npda_rip->router_infop) { + router_init(cnodeid,0,npda_rip); + } + npda_rip = npda_rip->router_next; + } + + /* + * Read mfg info on this hub + */ +#ifndef CONFIG_IA64_SGI_IO + printk("io_init_node: FIXME need to implement HUB_VERTEX_MFG_INFO\n"); + HUB_VERTEX_MFG_INFO(hubv); +#endif /* CONFIG_IA64_SGI_IO */ + + /* + * If nothing connected to this hub's xtalk port, we're done. + */ + early_probe_for_widget(hubv, &hwid); + if (hwid.part_num == XWIDGET_PART_NUM_NONE) { +#ifdef PROBE_TEST + if ((cnodeid == 1) || (cnodeid == 2)) { + int index; + + for (index = 0; index < 600; index++) + printk("Interfering with device probing!!!\n"); + } +#endif + /* io_init_done takes cpu cookie as 2nd argument + * to do a restorenoderun for the setnoderun done + * at the start of this thread + */ + + printk("**** io_init_node: Node's 0x%p hub widget has XWIDGET_PART_NUM_NONE ****\n", hubv); + io_init_done(cnodeid,c); + /* NOTREACHED */ + } + + /* + * attach our hub_provider information to hubv, + * so we can use it as a crosstalk provider "master" + * vertex. + */ + xtalk_provider_register(hubv, &hub_provider); + xtalk_provider_startup(hubv); + + /* + * Create a vertex to represent the crosstalk bus + * attached to this hub, and a vertex to be used + * as the connect point for whatever is out there + * on the other side of our crosstalk connection. + * + * Crosstalk Switch drivers "climb up" from their + * connection point to try and take over the switch + * point. + * + * Of course, the edges and verticies may already + * exist, in which case our net effect is just to + * associate the "xtalk_" driver with the connection + * point for the device. + */ + + (void)hwgraph_path_add(hubv, EDGE_LBL_XTALK, &switchv); + + printk("io_init_node: Created 'xtalk' entry to '../node/' xtalk vertex 0x%p\n", switchv); + + ASSERT(switchv != GRAPH_VERTEX_NONE); + + (void)hwgraph_edge_add(hubv, switchv, EDGE_LBL_IO); + + printk("io_init_node: Created symlink 'io' from ../node/io to ../node/xtalk \n"); + + /* + * We need to find the widget id and update the basew_id field + * accordingly. In particular, SN00 has direct connected bridge, + * and hence widget id is Not 0. + */ + + widget_partnum = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + WIDGET_ID))) & WIDGET_PART_NUM) >> WIDGET_PART_NUM_SHFT; + + if (widget_partnum == BRIDGE_WIDGET_PART_NUM || + widget_partnum == XBRIDGE_WIDGET_PART_NUM){ + npdap->basew_id = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + BRIDGE_WID_CONTROL))) & WIDGET_WIDGET_ID); + + printk("io_init_node: Found XBRIDGE widget_partnum= 0x%x\n", widget_partnum); + + } else if (widget_partnum == XBOW_WIDGET_PART_NUM || + widget_partnum == XXBOW_WIDGET_PART_NUM) { + /* + * Xbow control register does not have the widget ID field. + * So, hard code the widget ID to be zero. + */ + printk("io_init_node: Found XBOW widget_partnum= 0x%x\n", widget_partnum); + npdap->basew_id = 0; + +#if defined(BRINGUP) + } else if (widget_partnum == XG_WIDGET_PART_NUM) { + /* + * OK, WTF do we do here if we have an XG direct connected to a HUB/Bedrock??? + * So, hard code the widget ID to be zero? + */ + npdap->basew_id = 0; + npdap->basew_id = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + BRIDGE_WID_CONTROL))) & WIDGET_WIDGET_ID); +#endif + } else { + npdap->basew_id = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + BRIDGE_WID_CONTROL))) & WIDGET_WIDGET_ID); + + panic(" ****io_init_node: Unknown Widget Part Number 0x%x Widgt ID 0x%x attached to Hubv 0x%p ****\n", widget_partnum, npdap->basew_id, hubv); + + /*NOTREACHED*/ + } + { + char widname[10]; + sprintf(widname, "%x", npdap->basew_id); + (void)hwgraph_path_add(switchv, widname, &widgetv); + printk("io_init_node: Created '%s' to '..node/xtalk/' vertex 0x%p\n", widname, widgetv); + ASSERT(widgetv != GRAPH_VERTEX_NONE); + } + + nodepda->basew_xc = widgetv; + + is_xswitch = xwidget_hwid_is_xswitch(&hwid); + + /* + * Try to become the master of the widget. If this is an xswitch + * with multiple hubs connected, only one will succeed. Mastership + * of an xswitch is used only when touching registers on that xswitch. + * The slave xwidgets connected to the xswitch can be owned by various + * masters. + */ + if (device_master_set(widgetv, hubv) == 0) { + + /* Only one hub (thread) per Crosstalk device or switch makes + * it to here. + */ + + /* + * Initialize whatever xwidget is hanging off our hub. + * Whatever it is, it's accessible through widgetnum 0. + */ + hubinfo_get(hubv, &hubinfo); + + (void)xwidget_register(&hwid, widgetv, npdap->basew_id, hubv, hubinfo->h_widgetid, NULL); + + if (!is_xswitch) { + /* io_init_done takes cpu cookie as 2nd argument + * to do a restorenoderun for the setnoderun done + * at the start of this thread + */ + io_init_done(cnodeid,c); + /* NOTREACHED */ + } + + /* + * Special handling for Crosstalk Switches (e.g. xbow). + * We need to do things in roughly the following order: + * 1) Initialize xswitch hardware (done above) + * 2) Determine which hubs are available to be widget masters + * 3) Discover which links are active from the xswitch + * 4) Assign xwidgets hanging off the xswitch to hubs + * 5) Initialize all xwidgets on the xswitch + */ + + volunteer_for_widgets(switchv, hubv); + + /* If there's someone else on this crossbow, recognize him */ + if (npdap->xbow_peer != INVALID_NASID) { + nodepda_t *peer_npdap = NODEPDA(NASID_TO_COMPACT_NODEID(npdap->xbow_peer)); + peer_sema = &peer_npdap->xbow_sema; + volunteer_for_widgets(switchv, peer_npdap->node_vertex); + } + + assign_widgets_to_volunteers(switchv, hubv); + + /* Signal that we're done */ + if (peer_sema) { + up(peer_sema); + } + + } + else { + /* Wait 'til master is done assigning widgets. */ + down(&npdap->xbow_sema); + } + +#ifdef PROBE_TEST + if ((cnodeid == 1) || (cnodeid == 2)) { + int index; + + for (index = 0; index < 500; index++) + printk("Interfering with device probing!!!\n"); + } +#endif + /* Now both nodes can safely inititialize widgets */ + io_init_xswitch_widgets(switchv, cnodeid); + io_link_xswitch_widgets(switchv, cnodeid); + + /* io_init_done takes cpu cookie as 2nd argument + * to do a restorenoderun for the setnoderun done + * at the start of this thread + */ + io_init_done(cnodeid,c); + + printk("\nio_init_node: DONE INITIALIZED ALL I/O FOR CNODEID %d\n\n", cnodeid); +} + + +#define IOINIT_STKSZ (16 * 1024) + +#ifndef CONFIG_IA64_SGI_IO +#include +#endif +#define __DEVSTR1 "/../.master/" +#define __DEVSTR2 "/target/" +#define __DEVSTR3 "/lun/0/disk/partition/" +#define __DEVSTR4 "/../ef" + +#if CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 || CONFIG_IA64_GENERIC +/* + * Currently, we need to allow for 5 IBrick slots with 1 FC each + * plus an internal 1394. + * + * ioconfig starts numbering SCSI's at NUM_BASE_IO_SCSI_CTLR. + */ +#define NUM_BASE_IO_SCSI_CTLR 6 +#endif +/* + * This tells ioconfig where it can start numbering scsi controllers. + * Below this base number, platform-specific handles the numbering. + * XXX Irix legacy..controller numbering should be part of devfsd's job + */ +int num_base_io_scsi_ctlr = 2; /* used by syssgi */ +devfs_handle_t base_io_scsi_ctlr_vhdl[NUM_BASE_IO_SCSI_CTLR]; +static devfs_handle_t baseio_enet_vhdl,baseio_console_vhdl; + +/* + * Put the logical controller number information in the + * scsi controller vertices for each scsi controller that + * is in a "fixed position". + */ +static void +scsi_ctlr_nums_add(devfs_handle_t pci_vhdl) +{ + { + int i; + + num_base_io_scsi_ctlr = NUM_BASE_IO_SCSI_CTLR; + + /* Initialize base_io_scsi_ctlr_vhdl array */ + for (i=0; i +#else +#include +#endif +extern devfs_handle_t ioc3_console_vhdl_get(void); +devfs_handle_t sys_critical_graph_root = GRAPH_VERTEX_NONE; + +/* #ifdef LATER */ +/* Define the system critical vertices and connect them through + * a canonical parent-child relationships for easy traversal + * during io error handling. + */ +static void +sys_critical_graph_init(void) +{ + devfs_handle_t bridge_vhdl,master_node_vhdl; + devfs_handle_t xbow_vhdl = GRAPH_VERTEX_NONE; + extern devfs_handle_t hwgraph_root; + devfs_handle_t pci_slot_conn; + int slot; + devfs_handle_t baseio_console_conn; + + printk("sys_critical_graph_init: FIXME.\n"); + baseio_console_conn = hwgraph_connectpt_get(baseio_console_vhdl); + + if (baseio_console_conn == NULL) { + return; + } + + /* Get the vertex handle for the baseio bridge */ + bridge_vhdl = device_master_get(baseio_console_conn); + + /* Get the master node of the baseio card */ + master_node_vhdl = cnodeid_to_vertex( + master_node_get(baseio_console_vhdl)); + + /* Add the "root->node" part of the system critical graph */ + + sys_critical_graph_vertex_add(hwgraph_root,master_node_vhdl); + + /* Check if we have a crossbow */ + if (hwgraph_traverse(master_node_vhdl, + EDGE_LBL_XTALK"/0", + &xbow_vhdl) == GRAPH_SUCCESS) { + /* We have a crossbow.Add "node->xbow" part of the system + * critical graph. + */ + sys_critical_graph_vertex_add(master_node_vhdl,xbow_vhdl); + + /* Add "xbow->baseio bridge" of the system critical graph */ + sys_critical_graph_vertex_add(xbow_vhdl,bridge_vhdl); + + hwgraph_vertex_unref(xbow_vhdl); + } else + /* We donot have a crossbow. Add "node->baseio_bridge" + * part of the system critical graph. + */ + sys_critical_graph_vertex_add(master_node_vhdl,bridge_vhdl); + + /* Add all the populated PCI slot vertices to the system critical + * graph with the bridge vertex as the parent. + */ + for (slot = 0 ; slot < 8; slot++) { + char slot_edge[10]; + + sprintf(slot_edge,"%d",slot); + if (hwgraph_traverse(bridge_vhdl,slot_edge, &pci_slot_conn) + != GRAPH_SUCCESS) + continue; + sys_critical_graph_vertex_add(bridge_vhdl,pci_slot_conn); + hwgraph_vertex_unref(pci_slot_conn); + } + + hwgraph_vertex_unref(bridge_vhdl); + + /* Add the "ioc3 pci connection point -> console ioc3" part + * of the system critical graph + */ + + if (hwgraph_traverse(baseio_console_vhdl,"..",&pci_slot_conn) == + GRAPH_SUCCESS) { + sys_critical_graph_vertex_add(pci_slot_conn, + baseio_console_vhdl); + hwgraph_vertex_unref(pci_slot_conn); + } + + /* Add the "ethernet pci connection point -> base ethernet" part of + * the system critical graph + */ + if (hwgraph_traverse(baseio_enet_vhdl,"..",&pci_slot_conn) == + GRAPH_SUCCESS) { + sys_critical_graph_vertex_add(pci_slot_conn, + baseio_enet_vhdl); + hwgraph_vertex_unref(pci_slot_conn); + } + + /* Add the "scsi controller pci connection point -> base scsi + * controller" part of the system critical graph + */ + if (hwgraph_traverse(base_io_scsi_ctlr_vhdl[0], + "../..",&pci_slot_conn) == GRAPH_SUCCESS) { + sys_critical_graph_vertex_add(pci_slot_conn, + base_io_scsi_ctlr_vhdl[0]); + hwgraph_vertex_unref(pci_slot_conn); + } + if (hwgraph_traverse(base_io_scsi_ctlr_vhdl[1], + "../..",&pci_slot_conn) == GRAPH_SUCCESS) { + sys_critical_graph_vertex_add(pci_slot_conn, + base_io_scsi_ctlr_vhdl[1]); + hwgraph_vertex_unref(pci_slot_conn); + } + hwgraph_vertex_unref(baseio_console_conn); + +} + +static void +baseio_ctlr_num_set(void) +{ + char name[MAXDEVNAME]; + devfs_handle_t console_vhdl, pci_vhdl, enet_vhdl; + + + printk("baseio_ctlr_num_set; FIXME\n"); + console_vhdl = ioc3_console_vhdl_get(); + if (console_vhdl == GRAPH_VERTEX_NONE) + return; + /* Useful for setting up the system critical graph */ + baseio_console_vhdl = console_vhdl; + + vertex_to_name(console_vhdl,name,MAXDEVNAME); + + strcat(name,__DEVSTR1); + pci_vhdl = hwgraph_path_to_vertex(name); + scsi_ctlr_nums_add(pci_vhdl); + /* Unref the pci_vhdl due to the reference by hwgraph_path_to_vertex + */ + hwgraph_vertex_unref(pci_vhdl); + + vertex_to_name(console_vhdl, name, MAXDEVNAME); + strcat(name, __DEVSTR4); + enet_vhdl = hwgraph_path_to_vertex(name); + + /* Useful for setting up the system critical graph */ + baseio_enet_vhdl = enet_vhdl; + + device_controller_num_set(enet_vhdl, 0); + /* Unref the enet_vhdl due to the reference by hwgraph_path_to_vertex + */ + hwgraph_vertex_unref(enet_vhdl); +} +/* #endif */ + +void +sn00_rrb_alloc(devfs_handle_t vhdl, int *vendor_list) +{ + /* REFERENCED */ + int rtn_val; + + /* + ** sn00 population: errb orrb + ** 0- ql 3+? + ** 1- ql 2 + ** 2- ioc3 ethernet 2+? + ** 3- ioc3 secondary 1 + ** 4- 0 + ** 5- PCI slot + ** 6- PCI slot + ** 7- PCI slot + */ + + /* The following code implements this heuristic for getting + * maximum usage out of the rrbs + * + * constraints: + * 8 bit ql1 needs 1+1 + * ql0 or ql5,6,7 wants 1+2 + * ethernet wants 2 or more + * + * rules for even rrbs: + * if nothing in slot 6 + * 4 rrbs to 0 and 2 (0xc8889999) + * else + * 3 2 3 to slots 0 2 6 (0xc8899bbb) + * + * rules for odd rrbs + * if nothing in slot 5 or 7 (0xc8889999) + * 4 rrbs to 1 and 3 + * else if 1 thing in 5 or 7 (0xc8899aaa) or (0xc8899bbb) + * 3 2 3 to slots 1 3 5|7 + * else + * 2 1 3 2 to slots 1 3 5 7 (note: if there's a ql card in 7 this + * (0xc89aaabb) may short what it wants therefore the + * rule should be to plug pci slots in order) + */ + + + if (vendor_list[6] != PCIIO_VENDOR_ID_NONE) { + /* something in slot 6 */ + rtn_val = pcibr_alloc_all_rrbs(vhdl, 0, 3,1, 2,0, 0,0, 3,0); + } + else { + rtn_val = pcibr_alloc_all_rrbs(vhdl, 0, 4,1, 4,0, 0,0, 0,0); + } +#ifndef CONFIG_IA64_SGI_IO + if (rtn_val) + cmn_err(CE_WARN, "sn00_rrb_alloc: pcibr_alloc_all_rrbs failed"); +#endif + + if ((vendor_list[5] != PCIIO_VENDOR_ID_NONE) && + (vendor_list[7] != PCIIO_VENDOR_ID_NONE)) { + /* soemthing in slot 5 and 7 */ + rtn_val = pcibr_alloc_all_rrbs(vhdl, 1, 2,1, 1,0, 3,0, 2,0); + } + else if (vendor_list[5] != PCIIO_VENDOR_ID_NONE) { + /* soemthing in slot 5 but not 7 */ + rtn_val = pcibr_alloc_all_rrbs(vhdl, 1, 3,1, 2,0, 3,0, 0,0); + } + else if (vendor_list[7] != PCIIO_VENDOR_ID_NONE) { + /* soemthing in slot 7 but not 5 */ + rtn_val = pcibr_alloc_all_rrbs(vhdl, 1, 3,1, 2,0, 0,0, 3,0); + } + else { + /* nothing in slot 5 or 7 */ + rtn_val = pcibr_alloc_all_rrbs(vhdl, 1, 4,1, 4,0, 0,0, 0,0); + } +#ifndef CONFIG_IA64_SGI_IO + if (rtn_val) + cmn_err(CE_WARN, "sn00_rrb_alloc: pcibr_alloc_all_rrbs failed"); +#endif +} + + +/* + * Initialize all I/O devices. Starting closest to nodes, probe and + * initialize outward. + */ +void +init_all_devices(void) +{ + /* Governor on init threads..bump up when safe + * (beware many devfs races) + */ +#ifndef CONFIG_IA64_SGI_IO + int io_init_node_threads = 2; +#endif + cnodeid_t cnodeid, active; + + init_MUTEX(&io_init_sema); + + + active = 0; + for (cnodeid = 0; cnodeid < maxnodes; cnodeid++) { +#ifndef CONFIG_IA64_SGI_IO + char thread_name[16]; + extern int io_init_pri; + + /* + * Spawn a service thread for each node to initialize all + * I/O on that node. Each thread attempts to bind itself + * to the node whose I/O it's initializing. + */ + sprintf(thread_name, "IO_init[%d]", cnodeid); + + (void)sthread_create(thread_name, 0, IOINIT_STKSZ, 0, + io_init_pri, KT_PS, (st_func_t *)io_init_node, + (void *)(long)cnodeid, 0, 0, 0); +#else + printk("init_all_devices: Calling io_init_node() for cnode %d\n", cnodeid); + io_init_node(cnodeid); + + printk("init_all_devices: Done io_init_node() for cnode %d\n", cnodeid); + +#endif /* !CONFIG_IA64_SGI_IO */ + + + /* Limit how many nodes go at once, to not overload hwgraph */ + /* TBD: Should timeout */ +#ifdef AA_DEBUG + printk("started thread for cnode %d\n", cnodeid); +#endif +#ifdef LATER + active++; + if (io_init_node_threads && + active >= io_init_node_threads) { + down(&io_init_sema); + active--; + } +#endif /* LATER */ + } + +#ifdef LATER + /* Wait until all IO_init threads are done */ + + while (active > 0) { +#ifdef AA_DEBUG + printk("waiting, %d still active\n", active); +#endif + sema(&io_init_sema); + active--; + } + +#endif /* LATER */ + + for (cnodeid = 0; cnodeid < maxnodes; cnodeid++) + /* + * Update information generated by IO init. + */ + update_node_information(cnodeid); + + baseio_ctlr_num_set(); + /* Setup the system critical graph (which is a subgraph of the + * main hwgraph). This information is useful during io error + * handling. + */ + sys_critical_graph_init(); + +#if HWG_PRINT + hwgraph_print(); +#endif + +} + +#define toint(x) ((int)(x) - (int)('0')) + +void +devnamefromarcs(char *devnm) +{ + int val; + char tmpnm[MAXDEVNAME]; + char *tmp1, *tmp2; + + val = strncmp(devnm, "dks", 3); + if (val != 0) + return; + tmp1 = devnm + 3; + if (!isdigit(*tmp1)) + return; + + val = 0; + while (isdigit(*tmp1)) { + val = 10*val+toint(*tmp1); + tmp1++; + } + + if(*tmp1 != 'd') + return; + else + tmp1++; + + if ((val < 0) || (val >= NUM_BASE_IO_SCSI_CTLR)) { + int i; + int viable_found = 0; + + printk("Only controller numbers 0..%d are supported for\n", NUM_BASE_IO_SCSI_CTLR-1); + printk("prom \"root\" variables of the form dksXdXsX.\n"); + printk("To use another disk you must use the full hardware graph path\n\n"); + printk("Possible controller numbers for use in 'dksXdXsX' on this system: "); + for (i=0; i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define LDEBUG 1 + +#define DPRINTF if (LDEBUG) printk +#define printf printk + +module_t *modules[MODULE_MAX]; +int nummodules; + +#define SN00_SERIAL_FUDGE 0x3b1af409d513c2 +#define SN0_SERIAL_FUDGE 0x6e + +void +encode_int_serial(uint64_t src,uint64_t *dest) +{ + uint64_t val; + int i; + + val = src + SN00_SERIAL_FUDGE; + + + for (i = 0; i < sizeof(long long); i++) { + ((char*)dest)[i] = + ((char*)&val)[sizeof(long long)/2 + + ((i%2) ? ((i/2 * -1) - 1) : (i/2))]; + } +} + + +void +decode_int_serial(uint64_t src, uint64_t *dest) +{ + uint64_t val; + int i; + + for (i = 0; i < sizeof(long long); i++) { + ((char*)&val)[sizeof(long long)/2 + + ((i%2) ? ((i/2 * -1) - 1) : (i/2))] = + ((char*)&src)[i]; + } + + *dest = val - SN00_SERIAL_FUDGE; +} + + +void +encode_str_serial(const char *src, char *dest) +{ + int i; + + for (i = 0; i < MAX_SERIAL_NUM_SIZE; i++) { + + dest[i] = src[MAX_SERIAL_NUM_SIZE/2 + + ((i%2) ? ((i/2 * -1) - 1) : (i/2))] + + SN0_SERIAL_FUDGE; + } +} + +void +decode_str_serial(const char *src, char *dest) +{ + int i; + + for (i = 0; i < MAX_SERIAL_NUM_SIZE; i++) { + dest[MAX_SERIAL_NUM_SIZE/2 + + ((i%2) ? ((i/2 * -1) - 1) : (i/2))] = src[i] - + SN0_SERIAL_FUDGE; + } +} + + +module_t *module_lookup(moduleid_t id) +{ + int i; + + DPRINTF("module_lookup: id=%d\n", id); + + for (i = 0; i < nummodules; i++) + if (modules[i]->id == id) { + DPRINTF("module_lookup: found m=0x%p\n", modules[i]); + return modules[i]; + } + + return NULL; +} + +/* + * module_add_node + * + * The first time a new module number is seen, a module structure is + * inserted into the module list in order sorted by module number + * and the structure is initialized. + * + * The node number is added to the list of nodes in the module. + */ + +module_t *module_add_node(moduleid_t id, cnodeid_t n) +{ + module_t *m; + int i; + + DPRINTF("module_add_node: id=%x node=%d\n", id, n); + + if ((m = module_lookup(id)) == 0) { +#ifndef CONFIG_IA64_SGI_IO + m = kmem_zalloc_node(sizeof (module_t), KM_NOSLEEP, n); +#else + m = kmalloc(sizeof (module_t), GFP_KERNEL); + memset(m, 0 , sizeof(module_t)); + printk("Module nodecnt = %d\n", m->nodecnt); +#endif + ASSERT_ALWAYS(m); + + DPRINTF("module_add_node: m=0x%p\n", m); + + m->id = id; + spin_lock_init(&m->lock); + + init_MUTEX_LOCKED(&m->thdcnt); +#ifndef CONFIG_IA64_SGI_IO + /* + * I do not believe this driver is used in SN1 - colin + */ + elsc_init(&m->elsc, COMPACT_TO_NASID_NODEID(n)); +#endif + spin_lock_init(&m->elsclock); + + /* Insert in sorted order by module number */ + + for (i = nummodules; i > 0 && modules[i - 1]->id > id; i--) + modules[i] = modules[i - 1]; + + modules[i] = m; + nummodules++; + } + + m->nodes[m->nodecnt++] = n; + + DPRINTF("module_add_node: module %x now has %d nodes\n", id, m->nodecnt); + + return m; +} + +int module_probe_snum(module_t *m, nasid_t nasid) +{ + lboard_t *board; + klmod_serial_num_t *comp; + + board = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid), + KLTYPE_MIDPLANE8); + + if (! board || KL_CONFIG_DUPLICATE_BOARD(board)) + return 0; + + comp = GET_SNUM_COMP(board); + + if (comp) { +#if defined (CONFIG_SGI_IP27) /* CONFIG_SGI_IP27 specific */ + if (private.p_sn00) { + DPRINTF("********found sn00 module with " + "id %d and serial 0x%llx\n", + m->id, comp->snum.snum_int); + + if (comp->snum.snum_int != 0) { + m->snum.snum_int = comp->snum.snum_int; + m->snum_valid = 1; + } + + } + else +#endif /* CONFIG_SGI_IP27 */ + { +#if LDEBUG + int i; + + printf("********found module with id %x and string", m->id); + + for (i = 0; i < MAX_SERIAL_NUM_SIZE; i++) + printf(" %x ", comp->snum.snum_str[i]); + + printf("\n"); /* Fudged string is not ASCII */ +#endif + + if (comp->snum.snum_str[0] != '\0') { + bcopy(comp->snum.snum_str, + m->snum.snum_str, + MAX_SERIAL_NUM_SIZE); + m->snum_valid = 1; + } + } + } + + if (m->snum_valid) + return 1; + else { +#ifndef CONFIG_IA64_SGI_IO + cmn_err(CE_WARN | CE_MAINTENANCE, + "Invalid serial number for module %d, " + "possible missing or invalid NIC.", m->id); +#else + printk("Invalid serial number for module %d, " + "possible missing or invalid NIC.", m->id); +#endif + return 0; + } +} + +void +io_module_init(void) +{ + cnodeid_t node; + lboard_t *board; + nasid_t nasid; + int nserial; + module_t *m; + + DPRINTF("*******module_init\n"); + + nserial = 0; + + for (node = 0; node < numnodes; node++) { + nasid = COMPACT_TO_NASID_NODEID(node); + + board = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid), + KLTYPE_IP27); + ASSERT(board); + + m = module_add_node(board->brd_module, node); + + if (! m->snum_valid && module_probe_snum(m, nasid)) + nserial++; + } + + DPRINTF("********found total of %d serial numbers in the system\n", + nserial); + + if (nserial == 0) + cmn_err(CE_WARN, "No serial number found."); +} + +#ifndef CONFIG_IA64_SGI_IO +elsc_t *get_elsc(void) +{ + return &NODEPDA(cnodeid())->module->elsc; +} +#endif + +int +get_kmod_info(cmoduleid_t cmod, module_info_t *mod_info) +{ + int i; + + if (cmod < 0 || cmod >= nummodules) + return EINVAL; + + if (! modules[cmod]->snum_valid) + return ENXIO; + + mod_info->mod_num = modules[cmod]->id; + +#if defined (CONFIG_SGI_IP27) /* CONFIG_SGI_IP27 specific */ + if (private.p_sn00) { + int i; + uint64_t snum64; + uint32_t snum32; + char *cur; + + decode_int_serial(modules[cmod]->snum.snum_int, + &snum64); + + /* if this is an invalid serial number return an error */ + if ((snum64 == 0) || (snum64 > 0x8ffffffffff)) + return ENXIO; + + /* this chops off the top two bytes */ + snum32 = snum64; + + mod_info->serial_num = snum32; + + /* convert to 8 hex characters */ + mod_info->serial_str[8] = '\0'; + cur = mod_info->serial_str + 7; + + for (i = 0; i < 8; i++) { + *cur-- = "0123456789ABCDEF"[snum32%16]; + snum32 /= 16; + } + + DPRINTF("********int get info, 0x%llx decoded to 0x%llx, " + "string is %s\n", + modules[cmod]->snum.snum_int, + mod_info->serial_num, mod_info->serial_str); + } + else +#endif /* CONFIG_SGI_IP27 specific */ + { + char temp[MAX_SERIAL_NUM_SIZE]; + + decode_str_serial(modules[cmod]->snum.snum_str, temp); + + /* if this is an invalid serial number return an error */ + if (temp[0] != 'K') + return ENXIO; + + mod_info->serial_num = 0; + + for (i = 0; i < MAX_SERIAL_NUM_SIZE && temp[i] != '\0'; i++) { + mod_info->serial_num <<= 4; + mod_info->serial_num |= (temp[i] & 0xf); + + mod_info->serial_str[i] = temp[i]; + } + + mod_info->serial_str[i] = '\0'; + } + + return 0; +} + diff -urN linux-2.4.0-test10/arch/ia64/sn/io/pci.c linux-2.4.0-test10-lia/arch/ia64/sn/io/pci.c --- linux-2.4.0-test10/arch/ia64/sn/io/pci.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/pci.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,311 @@ +/* + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * SNI64 specific PCI support for SNI IO. + * + * Copyright (C) 1997, 1998, 2000 Colin Ngam + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef DEBUG_CONFIG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + + + +#ifdef CONFIG_PCI + +extern devfs_handle_t pci_bus_to_vertex(unsigned char); +extern devfs_handle_t devfn_to_vertex(unsigned char bus, unsigned char devfn); + +/* + * snia64_read_config_byte - Read a byte from the config area of the device. + */ +static int snia64_read_config_byte (struct pci_dev *dev, + int where, unsigned char *val) +{ + unsigned long res = 0; + unsigned size = 1; + devfs_handle_t device_vertex; + + if ( (dev == (struct pci_dev *)0) || (val == (unsigned char *)0) ) { + return PCIBIOS_DEVICE_NOT_FOUND; + } + device_vertex = devfn_to_vertex(dev->bus->number, dev->devfn); + if (!device_vertex) { + DBG("%s : nonexistent device: bus= 0x%x slot= 0x%x func= 0x%x\n", + __FUNCTION__, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + return(-1); + } + res = pciio_config_get(device_vertex, (unsigned) where, size); + *val = (unsigned char) res; + return PCIBIOS_SUCCESSFUL; +} + +/* + * snia64_read_config_word - Read 2 bytes from the config area of the device. + */ +static int snia64_read_config_word (struct pci_dev *dev, + int where, unsigned short *val) +{ + unsigned long res = 0; + unsigned size = 2; /* 2 bytes */ + devfs_handle_t device_vertex; + + if ( (dev == (struct pci_dev *)0) || (val == (unsigned short *)0) ) { + return PCIBIOS_DEVICE_NOT_FOUND; + } + device_vertex = devfn_to_vertex(dev->bus->number, dev->devfn); + if (!device_vertex) { + DBG("%s : nonexistent device: bus= 0x%x slot= 0x%x func= 0x%x\n", + __FUNCTION__, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + return(-1); + } + res = pciio_config_get(device_vertex, (unsigned) where, size); + *val = (unsigned short) res; + return PCIBIOS_SUCCESSFUL; +} + +/* + * snia64_read_config_dword - Read 4 bytes from the config area of the device. + */ +static int snia64_read_config_dword (struct pci_dev *dev, + int where, unsigned int *val) +{ + unsigned long res = 0; + unsigned size = 4; /* 4 bytes */ + devfs_handle_t device_vertex; + + if (where & 3) { + return PCIBIOS_BAD_REGISTER_NUMBER; + } + if ( (dev == (struct pci_dev *)0) || (val == (unsigned int *)0) ) { + return PCIBIOS_DEVICE_NOT_FOUND; + } + + device_vertex = devfn_to_vertex(dev->bus->number, dev->devfn); + if (!device_vertex) { + DBG("%s : nonexistent device: bus= 0x%x slot= 0x%x func= 0x%x\n", + __FUNCTION__, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + return(-1); + } + res = pciio_config_get(device_vertex, (unsigned) where, size); + *val = (unsigned int) res; + return PCIBIOS_SUCCESSFUL; +} + +/* + * snia64_write_config_byte - Writes 1 byte to the config area of the device. + */ +static int snia64_write_config_byte (struct pci_dev *dev, + int where, unsigned char val) +{ + devfs_handle_t device_vertex; + + if ( dev == (struct pci_dev *)0 ) { + return PCIBIOS_DEVICE_NOT_FOUND; + } + /* + * if it's an IOC3 then we bail out, we special + * case them with pci_fixup_ioc3 + */ + if (dev->vendor == PCI_VENDOR_ID_SGI && + dev->device == PCI_DEVICE_ID_SGI_IOC3 ) + return PCIBIOS_SUCCESSFUL; + + device_vertex = devfn_to_vertex(dev->bus->number, dev->devfn); + if (!device_vertex) { + DBG("%s : nonexistent device: bus= 0x%x slot= 0x%x func= 0x%x\n", + __FUNCTION__, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + return(-1); + } + pciio_config_set( device_vertex, (unsigned)where, 1, (uint64_t) val); + + return PCIBIOS_SUCCESSFUL; +} + +/* + * snia64_write_config_word - Writes 2 bytes to the config area of the device. + */ +static int snia64_write_config_word (struct pci_dev *dev, + int where, unsigned short val) +{ + devfs_handle_t device_vertex = NULL; + + if (where & 1) { + return PCIBIOS_BAD_REGISTER_NUMBER; + } + if ( dev == (struct pci_dev *)0 ) { + return PCIBIOS_DEVICE_NOT_FOUND; + } + /* + * if it's an IOC3 then we bail out, we special + * case them with pci_fixup_ioc3 + */ + if (dev->vendor == PCI_VENDOR_ID_SGI && + dev->device == PCI_DEVICE_ID_SGI_IOC3) + return PCIBIOS_SUCCESSFUL; + + device_vertex = devfn_to_vertex(dev->bus->number, dev->devfn); + if (!device_vertex) { + DBG("%s : nonexistent device: bus= 0x%x slot= 0x%x func= 0x%x\n", + __FUNCTION__, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + return(-1); + } + pciio_config_set( device_vertex, (unsigned)where, 2, (uint64_t) val); + + return PCIBIOS_SUCCESSFUL; +} + +/* + * snia64_write_config_dword - Writes 4 bytes to the config area of the device. + */ +static int snia64_write_config_dword (struct pci_dev *dev, + int where, unsigned int val) +{ + devfs_handle_t device_vertex; + + if (where & 3) { + return PCIBIOS_BAD_REGISTER_NUMBER; + } + if ( dev == (struct pci_dev *)0 ) { + return PCIBIOS_DEVICE_NOT_FOUND; + } + /* + * if it's an IOC3 then we bail out, we special + * case them with pci_fixup_ioc3 + */ + if (dev->vendor == PCI_VENDOR_ID_SGI && + dev->device == PCI_DEVICE_ID_SGI_IOC3) + return PCIBIOS_SUCCESSFUL; + + device_vertex = devfn_to_vertex(dev->bus->number, dev->devfn); + if (!device_vertex) { + DBG("%s : nonexistent device: bus= 0x%x slot= 0x%x func= 0x%x\n", + __FUNCTION__, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + return(-1); + } + pciio_config_set( device_vertex, (unsigned)where, 4, (uint64_t) val); + + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops snia64_pci_ops = { + snia64_read_config_byte, + snia64_read_config_word, + snia64_read_config_dword, + snia64_write_config_byte, + snia64_write_config_word, + snia64_write_config_dword +}; + +/* + * snia64_pci_find_bios - SNIA64 pci_find_bios() platform specific code. + */ +struct pci_ops * +sn1_pci_find_bios(void) +{ + /* + * Go initialize our IO Infrastructure .. + */ + extern void sgi_master_io_infr_init(void); + extern struct pci_ops *ia64_pci_find_bios(void); + + sgi_master_io_infr_init(); + +#ifdef BRINGUP + if ( IS_RUNNING_ON_SIMULATOR() ) + return ia64_pci_find_bios(); +#endif + /* sn1_io_infrastructure_init(); */ + return &snia64_pci_ops; +} + +static void +pci_fixup_ioc3(struct pci_dev *d) +{ + int i; + int slot; + unsigned long res = 0; + unsigned int val, size; + int ret; + u_short command; + + devfs_handle_t device_vertex; + devfs_handle_t bridge_vhdl = pci_bus_to_vertex(d->bus->number); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) hwgraph_fastinfo_get(bridge_vhdl); + devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn; + bridge_t *bridge = pcibr_soft->bs_base; + bridgereg_t devreg; + + /* IOC3 only decodes 0x20 bytes of the config space, reading + * beyond that is relatively benign but writing beyond that + * (especially the base address registers) will shut down the + * pci bus...so avoid doing so. + * NOTE: this means we can't program the intr_pin into the device, + * currently we hack this with special code in + * sgi_pci_intr_support() + */ + printk("pci_fixup_ioc3: Fixing base addresses for ioc3 device %s\n", d->slot_name); + + /* I happen to know from the spec that the ioc3 needs only 0xfffff + * The standard pci trick of writing ~0 to the baddr and seeing + * what comes back doesn't work with the ioc3 + */ + size = 0xfffff; + d->resource[0].end = (unsigned long) d->resource[0].start + (unsigned long) size; + + /* + * Zero out the resource structure .. because we did not go through + * the normal PCI Infrastructure Init, garbbage are left in these + * fileds. + */ + for (i = 1; i <= PCI_ROM_RESOURCE; i++) { + d->resource[i].start = 0UL; + d->resource[i].end = 0UL; + d->resource[i].flags = 0UL; + } + + /* + * Hardcode Device 4 register(IOC3 is in Slot 4) to set the + * DEV_DIRECT bit. This will not work if IOC3 is not on Slot + * 4. + */ + *(volatile u32 *)0xc0000a000f000220 |= 0x90000; + + d->subsystem_vendor = 0; + d->subsystem_device = 0; + +} + +struct pci_fixup pcibios_fixups[] = { + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, + pci_fixup_ioc3 }, + { 0 } +}; + +#endif /* CONFIG_PCI */ diff -urN linux-2.4.0-test10/arch/ia64/sn/io/pci_bus_cvlink.c linux-2.4.0-test10-lia/arch/ia64/sn/io/pci_bus_cvlink.c --- linux-2.4.0-test10/arch/ia64/sn/io/pci_bus_cvlink.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/pci_bus_cvlink.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,544 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +#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 +extern int bridge_rev_b_data_check_disable; +#include + +#define MAX_PCI_XWIDGET 256 +devfs_handle_t busnum_to_xwidget[MAX_PCI_XWIDGET]; +nasid_t busnum_to_nid[MAX_PCI_XWIDGET]; +unsigned char num_bridges; +static int done_probing = 0; + +static int pci_bus_map_create(devfs_handle_t xtalk); +devfs_handle_t devfn_to_vertex(unsigned char busnum, unsigned int devfn); + +/* + * pci_bus_cvlink_init() - To be called once during initialization before + * SGI IO Infrastructure init is called. + */ +void +pci_bus_cvlink_init(void) +{ + + memset(busnum_to_xwidget, 0x0, sizeof(devfs_handle_t) * MAX_PCI_XWIDGET); + memset(busnum_to_nid, 0x0, sizeof(nasid_t) * MAX_PCI_XWIDGET); + num_bridges = 0; +} + +/* + * pci_bus_to_vertex() - Given a logical Linux Bus Number returns the associated + * pci bus vertex from the SGI IO Infrastructure. + */ +devfs_handle_t +pci_bus_to_vertex(unsigned char busnum) +{ + + devfs_handle_t xwidget; + devfs_handle_t pci_bus = NULL; + + + /* + * First get the xwidget vertex. + */ + xwidget = busnum_to_xwidget[busnum]; + if (!xwidget) + return (NULL); + + /* + * Use devfs to get the pci vertex from xwidget. + */ + if (hwgraph_traverse(xwidget, EDGE_LBL_PCI, &pci_bus) != GRAPH_SUCCESS) { + if (!pci_bus) { + printk("pci_bus_to_vertex: Cannot find pci bus for given bus number %d\n", busnum); + return (NULL); + } + } + + return(pci_bus); +} + +/* + * devfn_to_vertex() - returns the vertex of the device given the bus, slot, + * and function numbers. + */ +devfs_handle_t +devfn_to_vertex(unsigned char busnum, unsigned int devfn) +{ + + int slot = 0; + int func = 0; + char name[16]; + devfs_handle_t pci_bus = NULL; + devfs_handle_t device_vertex = NULL; + + /* + * Go get the pci bus vertex. + */ + pci_bus = pci_bus_to_vertex(busnum); + if (!pci_bus) { + /* + * During probing, the Linux pci code invents non existant + * bus numbers and pci_dev structures and tries to access + * them to determine existance. Don't crib during probing. + */ + if (done_probing) + printk("devfn_to_vertex: Invalid bus number %d + given.\n", busnum); + return(NULL); + } + + + /* + * Go get the slot&function vertex. + * Should call pciio_slot_func_to_name() when ready. + */ + slot = PCI_SLOT(devfn); + func = PCI_FUNC(devfn); + + if (func == 0) + sprintf(name, "%d", slot); + else + sprintf(name, "%d%c", slot, 'a'+func); + + if (hwgraph_traverse(pci_bus, name, &device_vertex) != GRAPH_SUCCESS) { + if (!device_vertex) { + printk("devfn_to_vertex: Unable to get slot&func %s from pci vertex 0x%p\n", name, pci_bus); + return(NULL); + } + } + + return(device_vertex); +} + +/* + * sn1_pci_fixup() - This routine is called when platform_pci_fixup() is + * invoked at the end of pcibios_init() to link the Linux pci + * infrastructure to SGI IO Infrasturcture - ia64/kernel/pci.c + * + * Other platform specific fixup can also be done here. + */ +void +sn1_pci_fixup(void) +{ + struct list_head *ln; + struct pci_bus *pci_bus = NULL; + struct pci_dev *device_dev = NULL; + + +unsigned long res; + + +{ + devfs_handle_t bridge_vhdl = pci_bus_to_vertex(0); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) hwgraph_fastinfo_get(bridge_vhdl); + devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn; + bridge_t *bridge = pcibr_soft->bs_base; + +printk("Before Changing PIO Map Address:\n"); + printk("pci_fixup_ioc3: Before devreg fixup\n"); + printk("pci_fixup_ioc3: Devreg 0 0x%x\n", bridge->b_device[0].reg); + printk("pci_fixup_ioc3: Devreg 1 0x%x\n", bridge->b_device[1].reg); + printk("pci_fixup_ioc3: Devreg 2 0x%x\n", bridge->b_device[2].reg); + printk("pci_fixup_ioc3: Devreg 3 0x%x\n", bridge->b_device[3].reg); + printk("pci_fixup_ioc3: Devreg 4 0x%x\n", bridge->b_device[4].reg); + printk("pci_fixup_ioc3: Devreg 5 0x%x\n", bridge->b_device[5].reg); + printk("pci_fixup_ioc3: Devreg 6 0x%x\n", bridge->b_device[6].reg); + printk("pci_fixup_ioc3: Devreg 7 0x%x\n", bridge->b_device[7].reg); + + +} + done_probing = 1; + + if ( IS_RUNNING_ON_SIMULATOR() ) { + printk("sn1_pci_fixup not supported on simulator.\n"); + return; + } + +#ifdef REAL_HARDWARE + + /* + * Initialize the pci bus vertex in the pci_bus struct. + */ + for( ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) { + pci_bus = pci_bus_b(ln); + pci_bus->sysdata = (void *)pci_bus_to_vertex(pci_bus->number); + } + + /* + * set the root start and end so that drivers calling check_region() + * won't see a conflict + */ + ioport_resource.start |= IO_SWIZ_BASE; + ioport_resource.end |= (HSPEC_SWIZ_BASE-1); + /* + * Initialize the device vertex in the pci_dev struct. + */ + pci_for_each_dev(device_dev) { + unsigned int irq; + int idx; + u16 cmd; + devfs_handle_t vhdl; + unsigned long size; + + /* Set the device vertex */ + + device_dev->sysdata = (void *) devfn_to_vertex(device_dev->bus->number, device_dev->devfn); + + pci_read_config_word(device_dev, PCI_COMMAND, &cmd); + + /* + * Set the resources address correctly. The assumption here + * is that the addresses in the resource structure has been + * read from the card and it was set in the card by our + * Infrastructure .. + */ + vhdl = (devfs_handle_t) device_dev->sysdata; + for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { + size = 0; + size = device_dev->resource[idx].end - + device_dev->resource[idx].start; + if (size) { +res = 0; +res = pciio_config_get(vhdl, (unsigned) PCI_BASE_ADDRESS_0 + idx, 4); +printk("Before pciio_pio_addr Base address %d = 0x%lx\n", idx, res); + + printk(" Changing device %d:%d resource start address from 0x%lx", + PCI_SLOT(device_dev->devfn),PCI_FUNC(device_dev->devfn), + device_dev->resource[idx].start); + device_dev->resource[idx].start = + (unsigned long)pciio_pio_addr(vhdl, 0, + PCIIO_SPACE_WIN(idx), 0, size, 0, PCIIO_BYTE_STREAM); + } + else + continue; + + device_dev->resource[idx].end = + device_dev->resource[idx].start + size; + + /* + * Adjust the addresses to go to the SWIZZLE .. + */ + device_dev->resource[idx].start = + device_dev->resource[idx].start & 0xfffff7ffffffffff; + device_dev->resource[idx].end = + device_dev->resource[idx].end & 0xfffff7ffffffffff; + printk(" to 0x%lx\n", device_dev->resource[idx].start); +res = 0; +res = pciio_config_get(vhdl, (unsigned) PCI_BASE_ADDRESS_0 + idx, 4); +printk("After pciio_pio_addr Base address %d = 0x%lx\n", idx, res); + + if (device_dev->resource[idx].flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + else if (device_dev->resource[idx].flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + /* + * Now handle the ROM resource .. + */ + size = device_dev->resource[PCI_ROM_RESOURCE].end - + device_dev->resource[PCI_ROM_RESOURCE].start; + printk(" Changing device %d:%d ROM resource start address from 0x%lx", + PCI_SLOT(device_dev->devfn),PCI_FUNC(device_dev->devfn), + device_dev->resource[PCI_ROM_RESOURCE].start); + device_dev->resource[PCI_ROM_RESOURCE].start = + (unsigned long) pciio_pio_addr(vhdl, 0, PCIIO_SPACE_ROM, 0, + size, 0, PCIIO_BYTE_STREAM); + device_dev->resource[PCI_ROM_RESOURCE].end = + device_dev->resource[PCI_ROM_RESOURCE].start + size; + + /* + * go through synergy swizzled space + */ + device_dev->resource[PCI_ROM_RESOURCE].start &= 0xfffff7ffffffffffUL; + device_dev->resource[PCI_ROM_RESOURCE].end &= 0xfffff7ffffffffffUL; + + /* + * Update the Command Word on the Card. + */ + cmd |= PCI_COMMAND_MASTER; /* If the device doesn't support */ + /* bit gets dropped .. no harm */ + pci_write_config_word(device_dev, PCI_COMMAND, cmd); + + printk(" to 0x%lx\n", device_dev->resource[PCI_ROM_RESOURCE].start); + + /* + * Set the irq correctly. + * Bits 7:3 = slot + * Bits 2:0 = function + * + * In the IRQ we will have: + * Bits 24:16 = bus number + * Bits 15:8 = slot|func number + */ + irq = 0; + irq = (irq | (device_dev->devfn << 8)); + irq = (irq | ( (device_dev->bus->number & 0xff) << 16) ); + device_dev->irq = irq; +printk("sn1_pci_fixup: slot= %d fn= %d vendor= 0x%x device= 0x%x irq= 0x%x\n", +PCI_SLOT(device_dev->devfn),PCI_FUNC(device_dev->devfn),device_dev->vendor, +device_dev->device, device_dev->irq); + + } +#endif /* REAL_HARDWARE */ +{ + devfs_handle_t bridge_vhdl = pci_bus_to_vertex(0); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) hwgraph_fastinfo_get(bridge_vhdl); + devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn; + bridge_t *bridge = pcibr_soft->bs_base; + +printk("After Changing PIO Map Address:\n"); + printk("pci_fixup_ioc3: Before devreg fixup\n"); + printk("pci_fixup_ioc3: Devreg 0 0x%x\n", bridge->b_device[0].reg); + printk("pci_fixup_ioc3: Devreg 1 0x%x\n", bridge->b_device[1].reg); + printk("pci_fixup_ioc3: Devreg 2 0x%x\n", bridge->b_device[2].reg); + printk("pci_fixup_ioc3: Devreg 3 0x%x\n", bridge->b_device[3].reg); + printk("pci_fixup_ioc3: Devreg 4 0x%x\n", bridge->b_device[4].reg); + printk("pci_fixup_ioc3: Devreg 5 0x%x\n", bridge->b_device[5].reg); + printk("pci_fixup_ioc3: Devreg 6 0x%x\n", bridge->b_device[6].reg); + printk("pci_fixup_ioc3: Devreg 7 0x%x\n", bridge->b_device[7].reg); + + +} + + +} + +/* + * pci_bus_map_create() - Called by pci_bus_to_hcl_cvlink() to finish the job. + */ +static int +pci_bus_map_create(devfs_handle_t xtalk) +{ + + devfs_handle_t master_node_vertex = NULL; + devfs_handle_t xwidget = NULL; + devfs_handle_t pci_bus = NULL; + hubinfo_t hubinfo = NULL; + xwidgetnum_t widgetnum; + char pathname[128]; + graph_error_t rv; + + /* + * Loop throught this vertex and get the Xwidgets .. + */ + for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) { + sprintf(pathname, "%d", widgetnum); + xwidget = NULL; + + rv = hwgraph_traverse(xtalk, pathname, &xwidget); + if ( (rv != GRAPH_SUCCESS) ) { + if (!xwidget) + continue; + } + + sprintf(pathname, "%d/"EDGE_LBL_PCI, widgetnum); + pci_bus = NULL; + if (hwgraph_traverse(xtalk, pathname, &pci_bus) != GRAPH_SUCCESS) + if (!pci_bus) + continue; + + /* + * Assign the correct bus number and also the nasid of this + * pci Xwidget. + * + * Should not be any race here ... + */ + num_bridges++; + busnum_to_xwidget[num_bridges - 1] = xwidget; + + /* + * Get the master node and from there get the NASID. + */ + master_node_vertex = device_master_get(xwidget); + if (!master_node_vertex) { + printk(" **** pci_bus_map_create: Unable to get .master for vertex 0x%p **** \n", xwidget); + } + + hubinfo_get(master_node_vertex, &hubinfo); + if (!hubinfo) { + printk(" **** pci_bus_map_create: Unable to get hubinfo for master node vertex 0x%p ****\n", master_node_vertex); + return(1); + } else { + busnum_to_nid[num_bridges - 1] = hubinfo->h_nasid; + } + + printk("pci_bus_map_create: Found Hub nasid %d PCI Xwidget 0x%p widgetnum= %d\n", hubinfo->h_nasid, xwidget, widgetnum); + } + + return(0); +} + +/* + * pci_bus_to_hcl_cvlink() - This routine is called after SGI IO Infrastructure + * initialization has completed to set up the mappings between Xbridge + * and logical pci bus numbers. We also set up the NASID for each of these + * xbridges. + * + * Must be called before pci_init() is invoked. + */ +int +pci_bus_to_hcl_cvlink(void) +{ + + devfs_handle_t devfs_hdl = NULL; + devfs_handle_t module_comp = NULL; + devfs_handle_t node = NULL; + devfs_handle_t xtalk = NULL; + graph_vertex_place_t placeptr = EDGE_PLACE_WANT_REAL_EDGES; + int rv = 0; + char name[256]; + + /* + * Iterate throught each xtalk links in the system .. + * /hw/module/001c01/node/xtalk/ 8|9|10|11|12|13|14|15 + * + * /hw/module/001c01/node/xtalk/15 -> /hw/module/001c01/Ibrick/xtalk/15 + * + * What if it is not pci? + */ + devfs_hdl = hwgraph_path_to_vertex("/dev/hw/module"); + + /* + * Loop throught this directory "/devfs/hw/module/" and get each + * of it's entry. + */ + while (1) { + + /* Get vertex of component /dev/hw/ */ + memset((char *)name, '0', 256); + module_comp = NULL; + rv = hwgraph_edge_get_next(devfs_hdl, (char *)name, &module_comp, (uint *)&placeptr); + if ((rv == 0) && (module_comp)) { + /* Found a valid entry */ + node = NULL; + rv = hwgraph_edge_get(module_comp, "node", &node); + + } else { + printk("pci_bus_to_hcl_cvlink: No more Module Component.\n"); + return(0); + } + + if ( (rv != 0) || (!node) ){ + printk("pci_bus_to_hcl_cvlink: Module Component does not have node vertex.\n"); + continue; + } else { + xtalk = NULL; + rv = hwgraph_edge_get(node, "xtalk", &xtalk); + if ( (rv != 0) || (xtalk == NULL) ){ + printk("pci_bus_to_hcl_cvlink: Node has no xtalk vertex.\n"); + continue; + } + } + + printk("pci_bus_to_hcl_cvlink: Found Module %s node vertex = 0x%p xtalk vertex = 0x%p\n", name, node, xtalk); + /* + * Call routine to get the existing PCI Xwidget and create + * the convenience link from "/devfs/hw/pci_bus/.." + */ + pci_bus_map_create(xtalk); + } + + return(0); +} + +/* + * sgi_pci_intr_support - + */ +int +sgi_pci_intr_support (unsigned int requested_irq, device_desc_t *dev_desc, + devfs_handle_t *bus_vertex, pciio_intr_line_t *lines, + devfs_handle_t *device_vertex) + +{ + + unsigned int bus; + unsigned int devfn; + struct pci_dev *pci_dev; + unsigned char intr_pin = 0; + + printk("sgi_pci_intr_support: Called with requested_irq 0x%x\n", requested_irq); + + if (!dev_desc || !bus_vertex || !device_vertex) { + printk("sgi_pci_intr_support: Invalid parameter dev_desc 0x%p, bus_vertex 0x%p, device_vertex 0x%p\n", dev_desc, bus_vertex, device_vertex); + return(-1); + } + + devfn = (requested_irq >> 8) & 0xff; + bus = (requested_irq >> 16) & 0xffff; + pci_dev = pci_find_slot(bus, devfn); + *bus_vertex = pci_dev->bus->sysdata; + *device_vertex = pci_dev->sysdata; +#if 0 + { + int pos; + char dname[256]; + pos = devfs_generate_path(*device_vertex, dname, 256); + printk("%s : path= %s pos %d\n", __FUNCTION__, &dname[pos], pos); + } +#endif /* BRINGUP */ + + + /* + * Get the Interrupt PIN. + */ + pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &intr_pin); + *lines = (pciio_intr_line_t)intr_pin; + +#ifdef BRINGUP + /* + * ioc3 can't decode the PCI_INTERRUPT_PIN field of its config + * space so we have to set it here + */ + if (pci_dev->vendor == PCI_VENDOR_ID_SGI && + pci_dev->device == PCI_DEVICE_ID_SGI_IOC3 ) { + *lines = 1; + printk("%s : IOC3 HACK: lines= %d\n", __FUNCTION__, *lines); + } +#endif /* BRINGUP */ + + /* Not supported currently */ + *dev_desc = NULL; + + printk("sgi_pci_intr_support: Device Descriptor 0x%p, Bus Vertex 0x%p, Interrupt Pins 0x%x, Device Vertex 0x%p\n", *dev_desc, *bus_vertex, *lines, *device_vertex); + + return(0); + +} diff -urN linux-2.4.0-test10/arch/ia64/sn/io/pci_dma.c linux-2.4.0-test10-lia/arch/ia64/sn/io/pci_dma.c --- linux-2.4.0-test10/arch/ia64/sn/io/pci_dma.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/pci_dma.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,76 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Leo Dagum + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef BRINGUP +#ifndef BRIDGE_DIRECT_MAP_DMA +#define BRIDGE_DIRECT_MAP_DMA 0xb180000000000000ull +#endif +#endif + +/* + * sn1 platform specific pci_alloc_consistent() + * + * this interface is meant for "command" streams, i.e. called only + * once for initializing a device, so we don't want prefetching or + * write gathering turned on, hence the PCIIO_DMA_CMD flag + */ +void * +sn1_pci_alloc_consistent (struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle) +{ + void *ret; + int gfp = GFP_ATOMIC; + devfs_handle_t vhdl; + unsigned char slot; + + /* + * get vertex for the device + */ + vhdl = (devfs_handle_t) hwdev->sysdata; + slot = PCI_SLOT(hwdev->devfn); + + /* + * any device that can't dma into a 32 bit address space + * really has no business in this system, but we'll do + * what we can.. + */ + if (!hwdev || hwdev->dma_mask != 0xffffffff) + gfp |= GFP_DMA; + ret = (void *)__get_free_pages(gfp, get_order(size)); + +#ifdef BRINGUP + printk("%s : FIXME: not doing busaddr\n", __FUNCTION__); + if (ret) { + memset(ret, 0, size); + *dma_handle = __pa(ret) | BRIDGE_DIRECT_MAP_DMA; + } +#else + if (ret) { + memset(ret, 0, size); + + *dma_handle = pciio_dmatrans_addr(vhdl, NULL, (paddr_t)ret, size, + PCIIO_DMA_CMD); + } +#endif /* BRINGUP */ + return ret; +} + diff -urN linux-2.4.0-test10/arch/ia64/sn/io/pcibr.c linux-2.4.0-test10-lia/arch/ia64/sn/io/pcibr.c --- linux-2.4.0-test10/arch/ia64/sn/io/pcibr.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/pcibr.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,9574 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +#ifdef BRINGUP +int NeedXbridgeSwap = 0; +#endif + +#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_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) +#include +#include +#endif + +#if defined(BRINGUP) +#if 0 +#define DEBUG 1 /* To avoid lots of bad printk() formats leave off */ +#endif +#define PCI_DEBUG 1 +#define ATTACH_DEBUG 1 +#define PCIBR_SOFT_LIST 1 +#endif + +#ifndef LOCAL +#define LOCAL static +#endif + +#define PCIBR_LLP_CONTROL_WAR +#if defined (PCIBR_LLP_CONTROL_WAR) +int pcibr_llp_control_war_cnt; +#endif /* PCIBR_LLP_CONTROL_WAR */ + +#define NEWAf(ptr,n,f) (ptr = kmem_zalloc((n)*sizeof (*(ptr)), (f&PCIIO_NOSLEEP)?KM_NOSLEEP:KM_SLEEP)) +#define NEWA(ptr,n) (ptr = kmem_zalloc((n)*sizeof (*(ptr)), KM_SLEEP)) +#define DELA(ptr,n) (kfree(ptr)) + +#define NEWf(ptr,f) NEWAf(ptr,1,f) +#define NEW(ptr) NEWA(ptr,1) +#define DEL(ptr) DELA(ptr,1) + +int pcibr_devflag = D_MP; + +#define F(s,n) { 1l<<(s),-(s), n } + +struct reg_desc bridge_int_status_desc[] = +{ + F(31, "MULTI_ERR"), + F(30, "PMU_ESIZE_EFAULT"), + F(29, "UNEXPECTED_RESP"), + F(28, "BAD_XRESP_PACKET"), + F(27, "BAD_XREQ_PACKET"), + F(26, "RESP_XTALK_ERROR"), + F(25, "REQ_XTALK_ERROR"), + F(24, "INVALID_ADDRESS"), + F(23, "UNSUPPORTED_XOP"), + F(22, "XREQ_FIFO_OFLOW"), + F(21, "LLP_REC_SNERROR"), + F(20, "LLP_REC_CBERROR"), + F(19, "LLP_RCTY"), + F(18, "LLP_TX_RETRY"), + F(17, "LLP_TCTY"), + F(16, "SSRAM_PERR"), + F(15, "PCI_ABORT"), + F(14, "PCI_PARITY"), + F(13, "PCI_SERR"), + F(12, "PCI_PERR"), + F(11, "PCI_MASTER_TOUT"), + F(10, "PCI_RETRY_CNT"), + F(9, "XREAD_REQ_TOUT"), + F(8, "GIO_BENABLE_ERR"), + F(7, "INT7"), + F(6, "INT6"), + F(5, "INT5"), + F(4, "INT4"), + F(3, "INT3"), + F(2, "INT2"), + F(1, "INT1"), + F(0, "INT0"), + {0} +}; + +struct reg_values space_v[] = +{ + {PCIIO_SPACE_NONE, "none"}, + {PCIIO_SPACE_ROM, "ROM"}, + {PCIIO_SPACE_IO, "I/O"}, + {PCIIO_SPACE_MEM, "MEM"}, + {PCIIO_SPACE_MEM32, "MEM(32)"}, + {PCIIO_SPACE_MEM64, "MEM(64)"}, + {PCIIO_SPACE_CFG, "CFG"}, + {PCIIO_SPACE_WIN(0), "WIN(0)"}, + {PCIIO_SPACE_WIN(1), "WIN(1)"}, + {PCIIO_SPACE_WIN(2), "WIN(2)"}, + {PCIIO_SPACE_WIN(3), "WIN(3)"}, + {PCIIO_SPACE_WIN(4), "WIN(4)"}, + {PCIIO_SPACE_WIN(5), "WIN(5)"}, + {PCIIO_SPACE_BAD, "BAD"}, + {0} +}; + +struct reg_desc space_desc[] = +{ + {0xFF, 0, "space", 0, space_v}, + {0} +}; + +#if DEBUG +#define device_desc device_bits +LOCAL struct reg_desc device_bits[] = +{ + {BRIDGE_DEV_ERR_LOCK_EN, 0, "ERR_LOCK_EN"}, + {BRIDGE_DEV_PAGE_CHK_DIS, 0, "PAGE_CHK_DIS"}, + {BRIDGE_DEV_FORCE_PCI_PAR, 0, "FORCE_PCI_PAR"}, + {BRIDGE_DEV_VIRTUAL_EN, 0, "VIRTUAL_EN"}, + {BRIDGE_DEV_PMU_WRGA_EN, 0, "PMU_WRGA_EN"}, + {BRIDGE_DEV_DIR_WRGA_EN, 0, "DIR_WRGA_EN"}, + {BRIDGE_DEV_DEV_SIZE, 0, "DEV_SIZE"}, + {BRIDGE_DEV_RT, 0, "RT"}, + {BRIDGE_DEV_SWAP_PMU, 0, "SWAP_PMU"}, + {BRIDGE_DEV_SWAP_DIR, 0, "SWAP_DIR"}, + {BRIDGE_DEV_PREF, 0, "PREF"}, + {BRIDGE_DEV_PRECISE, 0, "PRECISE"}, + {BRIDGE_DEV_COH, 0, "COH"}, + {BRIDGE_DEV_BARRIER, 0, "BARRIER"}, + {BRIDGE_DEV_GBR, 0, "GBR"}, + {BRIDGE_DEV_DEV_SWAP, 0, "DEV_SWAP"}, + {BRIDGE_DEV_DEV_IO_MEM, 0, "DEV_IO_MEM"}, + {BRIDGE_DEV_OFF_MASK, BRIDGE_DEV_OFF_ADDR_SHFT, "DEV_OFF", "%x"}, + {0} +}; +#endif /* DEBUG */ + +#ifdef SUPPORT_PRINTING_R_FORMAT +LOCAL struct reg_values xio_cmd_pactyp[] = +{ + {0x0, "RdReq"}, + {0x1, "RdResp"}, + {0x2, "WrReqWithResp"}, + {0x3, "WrResp"}, + {0x4, "WrReqNoResp"}, + {0x5, "Reserved(5)"}, + {0x6, "FetchAndOp"}, + {0x7, "Reserved(7)"}, + {0x8, "StoreAndOp"}, + {0x9, "Reserved(9)"}, + {0xa, "Reserved(a)"}, + {0xb, "Reserved(b)"}, + {0xc, "Reserved(c)"}, + {0xd, "Reserved(d)"}, + {0xe, "SpecialReq"}, + {0xf, "SpecialResp"}, + {0} +}; + +LOCAL struct reg_desc xio_cmd_bits[] = +{ + {WIDGET_DIDN, -28, "DIDN", "%x"}, + {WIDGET_SIDN, -24, "SIDN", "%x"}, + {WIDGET_PACTYP, -20, "PACTYP", 0, xio_cmd_pactyp}, + {WIDGET_TNUM, -15, "TNUM", "%x"}, + {WIDGET_COHERENT, 0, "COHERENT"}, + {WIDGET_DS, 0, "DS"}, + {WIDGET_GBR, 0, "GBR"}, + {WIDGET_VBPM, 0, "VBPM"}, + {WIDGET_ERROR, 0, "ERROR"}, + {WIDGET_BARRIER, 0, "BARRIER"}, + {0} +}; +#endif /* SUPPORT_PRINTING_R_FORMAT */ + +#if PCIBR_FREEZE_TIME || PCIBR_ATE_DEBUG +LOCAL struct reg_desc ate_bits[] = +{ + {0xFFFF000000000000ull, -48, "RMF", "%x"}, + {~(IOPGSIZE - 1) & /* may trim off some low bits */ + 0x0000FFFFFFFFF000ull, 0, "XIO", "%x"}, + {0x0000000000000F00ull, -8, "port", "%x"}, + {0x0000000000000010ull, 0, "Barrier"}, + {0x0000000000000008ull, 0, "Prefetch"}, + {0x0000000000000004ull, 0, "Precise"}, + {0x0000000000000002ull, 0, "Coherent"}, + {0x0000000000000001ull, 0, "Valid"}, + {0} +}; +#endif + +#if PCIBR_ATE_DEBUG +LOCAL struct reg_values ssram_sizes[] = +{ + {BRIDGE_CTRL_SSRAM_512K, "512k"}, + {BRIDGE_CTRL_SSRAM_128K, "128k"}, + {BRIDGE_CTRL_SSRAM_64K, "64k"}, + {BRIDGE_CTRL_SSRAM_1K, "1k"}, + {0} +}; + +LOCAL struct reg_desc control_bits[] = +{ + {BRIDGE_CTRL_FLASH_WR_EN, 0, "FLASH_WR_EN"}, + {BRIDGE_CTRL_EN_CLK50, 0, "EN_CLK50"}, + {BRIDGE_CTRL_EN_CLK40, 0, "EN_CLK40"}, + {BRIDGE_CTRL_EN_CLK33, 0, "EN_CLK33"}, + {BRIDGE_CTRL_RST_MASK, -24, "RST", "%x"}, + {BRIDGE_CTRL_IO_SWAP, 0, "IO_SWAP"}, + {BRIDGE_CTRL_MEM_SWAP, 0, "MEM_SWAP"}, + {BRIDGE_CTRL_PAGE_SIZE, 0, "PAGE_SIZE"}, + {BRIDGE_CTRL_SS_PAR_BAD, 0, "SS_PAR_BAD"}, + {BRIDGE_CTRL_SS_PAR_EN, 0, "SS_PAR_EN"}, + {BRIDGE_CTRL_SSRAM_SIZE_MASK, 0, "SSRAM_SIZE", 0, ssram_sizes}, + {BRIDGE_CTRL_F_BAD_PKT, 0, "F_BAD_PKT"}, + {BRIDGE_CTRL_LLP_XBAR_CRD_MASK, -12, "LLP_XBAR_CRD", "%d"}, + {BRIDGE_CTRL_CLR_RLLP_CNT, 0, "CLR_RLLP_CNT"}, + {BRIDGE_CTRL_CLR_TLLP_CNT, 0, "CLR_TLLP_CNT"}, + {BRIDGE_CTRL_SYS_END, 0, "SYS_END"}, + {BRIDGE_CTRL_MAX_TRANS_MASK, -4, "MAX_TRANS", "%d"}, + {BRIDGE_CTRL_WIDGET_ID_MASK, 0, "WIDGET_ID", "%x"}, + {0} +}; +#endif + +/* kbrick widgetnum-to-bus layout */ +int p_busnum[MAX_PORT_NUM] = { /* widget# */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x0 - 0x7 */ + 2, /* 0x8 */ + 1, /* 0x9 */ + 0, 0, /* 0xa - 0xb */ + 5, /* 0xc */ + 6, /* 0xd */ + 4, /* 0xe */ + 3, /* 0xf */ +}; + +/* + * Additional PIO spaces per slot are + * recorded in this structure. + */ +struct pciio_piospace_s { + pciio_piospace_t next; /* another space for this device */ + char free; /* 1 if free, 0 if in use */ + pciio_space_t space; /* Which space is in use */ + iopaddr_t start; /* Starting address of the PIO space */ + size_t count; /* size of PIO space */ +}; + +/* Use io spin locks. This ensures that all the PIO writes from a particular + * CPU to a particular IO device are synched before the start of the next + * set of PIO operations to the same device. + */ +#define pcibr_lock(pcibr_soft) io_splock(pcibr_soft->bs_lock) +#define pcibr_unlock(pcibr_soft, s) io_spunlock(pcibr_soft->bs_lock,s) + +#if PCIBR_SOFT_LIST +typedef struct pcibr_list_s *pcibr_list_p; +struct pcibr_list_s { + pcibr_list_p bl_next; + pcibr_soft_t bl_soft; + devfs_handle_t bl_vhdl; +}; +pcibr_list_p pcibr_list = 0; +#endif + +typedef volatile unsigned *cfg_p; +typedef volatile bridgereg_t *reg_p; + +#define INFO_LBL_PCIBR_ASIC_REV "_pcibr_asic_rev" + +#define PCIBR_D64_BASE_UNSET (0xFFFFFFFFFFFFFFFF) +#define PCIBR_D32_BASE_UNSET (0xFFFFFFFF) + +#define PCIBR_VALID_SLOT(s) (s < 8) + +#ifdef SN_XXX +extern int hub_device_flags_set(devfs_handle_t widget_dev, + hub_widget_flags_t flags); +#endif + +extern devfs_handle_t hwgraph_root; +extern graph_error_t hwgraph_vertex_unref(devfs_handle_t vhdl); +extern int cap_able(uint64_t x); +extern uint64_t rmalloc(struct map *mp, size_t size); +extern void rmfree(struct map *mp, size_t size, uint64_t a); +extern int hwgraph_vertex_name_get(devfs_handle_t vhdl, char *buf, uint buflen); +extern long atoi(register char *p); +extern void *swap_ptr(void **loc, void *new); +extern char *dev_to_name(devfs_handle_t dev, char *buf, uint buflen); +extern cnodeid_t nodevertex_to_cnodeid(devfs_handle_t vhdl); +extern graph_error_t hwgraph_edge_remove(devfs_handle_t from, char *name, devfs_handle_t *toptr); +extern struct map *rmallocmap(uint64_t mapsiz); +extern void rmfreemap(struct map *mp); +extern int compare_and_swap_ptr(void **location, void *old_ptr, void *new_ptr); +extern void cmn_err_tag(int seqnumber, register int level, char *fmt, ...); + + + +/* ===================================================================== + * Function Table of Contents + * + * The order of functions in this file has stopped + * making much sense. We might want to take a look + * at it some time and bring back some sanity, or + * perhaps bust this file into smaller chunks. + */ + +LOCAL void do_pcibr_rrb_clear(bridge_t *, int); +LOCAL void do_pcibr_rrb_flush(bridge_t *, int); +LOCAL int do_pcibr_rrb_count_valid(bridge_t *, pciio_slot_t); +LOCAL int do_pcibr_rrb_count_avail(bridge_t *, pciio_slot_t); +LOCAL int do_pcibr_rrb_alloc(bridge_t *, pciio_slot_t, int); +LOCAL int do_pcibr_rrb_free(bridge_t *, pciio_slot_t, int); + +LOCAL void do_pcibr_rrb_autoalloc(pcibr_soft_t, int, int); + +int pcibr_wrb_flush(devfs_handle_t); +int pcibr_rrb_alloc(devfs_handle_t, int *, int *); +int pcibr_rrb_check(devfs_handle_t, int *, int *, int *, int *); +int pcibr_alloc_all_rrbs(devfs_handle_t, int, int, int, int, int, int, int, int, int); +void pcibr_rrb_flush(devfs_handle_t); + +LOCAL int pcibr_try_set_device(pcibr_soft_t, pciio_slot_t, unsigned, bridgereg_t); +void pcibr_release_device(pcibr_soft_t, pciio_slot_t, bridgereg_t); + +LOCAL void pcibr_clearwidint(bridge_t *); +LOCAL void pcibr_setwidint(xtalk_intr_t); +LOCAL int pcibr_probe_slot(bridge_t *, cfg_p, unsigned *); + +void pcibr_init(void); +int pcibr_attach(devfs_handle_t); +int pcibr_detach(devfs_handle_t); +int pcibr_open(devfs_handle_t *, int, int, cred_t *); +int pcibr_close(devfs_handle_t, int, int, cred_t *); +int pcibr_map(devfs_handle_t, vhandl_t *, off_t, size_t, uint); +int pcibr_unmap(devfs_handle_t, vhandl_t *); +int pcibr_ioctl(devfs_handle_t, int, void *, int, struct cred *, int *); + +void pcibr_freeblock_sub(iopaddr_t *, iopaddr_t *, iopaddr_t, size_t); + +#ifndef BRINGUP +LOCAL int pcibr_init_ext_ate_ram(bridge_t *); +#endif +LOCAL int pcibr_ate_alloc(pcibr_soft_t, int); +LOCAL void pcibr_ate_free(pcibr_soft_t, int, int); + +LOCAL pcibr_info_t pcibr_info_get(devfs_handle_t); +LOCAL pcibr_info_t pcibr_device_info_new(pcibr_soft_t, pciio_slot_t, pciio_function_t, pciio_vendor_id_t, pciio_device_id_t); +LOCAL void pcibr_device_info_free(devfs_handle_t, pciio_slot_t); +LOCAL int pcibr_device_attach(devfs_handle_t,pciio_slot_t); +LOCAL int pcibr_device_detach(devfs_handle_t,pciio_slot_t); +LOCAL iopaddr_t pcibr_addr_pci_to_xio(devfs_handle_t, pciio_slot_t, pciio_space_t, iopaddr_t, size_t, unsigned); + +pcibr_piomap_t pcibr_piomap_alloc(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, size_t, unsigned); +void pcibr_piomap_free(pcibr_piomap_t); +caddr_t pcibr_piomap_addr(pcibr_piomap_t, iopaddr_t, size_t); +void pcibr_piomap_done(pcibr_piomap_t); +caddr_t pcibr_piotrans_addr(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, unsigned); +iopaddr_t pcibr_piospace_alloc(devfs_handle_t, device_desc_t, pciio_space_t, size_t, size_t); +void pcibr_piospace_free(devfs_handle_t, pciio_space_t, iopaddr_t, size_t); + +LOCAL iopaddr_t pcibr_flags_to_d64(unsigned, pcibr_soft_t); +LOCAL bridge_ate_t pcibr_flags_to_ate(unsigned); + +pcibr_dmamap_t pcibr_dmamap_alloc(devfs_handle_t, device_desc_t, size_t, unsigned); +void pcibr_dmamap_free(pcibr_dmamap_t); +LOCAL bridge_ate_p pcibr_ate_addr(pcibr_soft_t, int); +LOCAL iopaddr_t pcibr_addr_xio_to_pci(pcibr_soft_t, iopaddr_t, size_t); +iopaddr_t pcibr_dmamap_addr(pcibr_dmamap_t, paddr_t, size_t); +alenlist_t pcibr_dmamap_list(pcibr_dmamap_t, alenlist_t, unsigned); +void pcibr_dmamap_done(pcibr_dmamap_t); +cnodeid_t pcibr_get_dmatrans_node(devfs_handle_t); +iopaddr_t pcibr_dmatrans_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, unsigned); +alenlist_t pcibr_dmatrans_list(devfs_handle_t, device_desc_t, alenlist_t, unsigned); +void pcibr_dmamap_drain(pcibr_dmamap_t); +void pcibr_dmaaddr_drain(devfs_handle_t, paddr_t, size_t); +void pcibr_dmalist_drain(devfs_handle_t, alenlist_t); +iopaddr_t pcibr_dmamap_pciaddr_get(pcibr_dmamap_t); + +static unsigned pcibr_intr_bits(pciio_info_t info, pciio_intr_line_t lines); +pcibr_intr_t pcibr_intr_alloc(devfs_handle_t, device_desc_t, pciio_intr_line_t, devfs_handle_t); +void pcibr_intr_free(pcibr_intr_t); +LOCAL void pcibr_setpciint(xtalk_intr_t); +int pcibr_intr_connect(pcibr_intr_t, intr_func_t, intr_arg_t, void *); +void pcibr_intr_disconnect(pcibr_intr_t); + +devfs_handle_t pcibr_intr_cpu_get(pcibr_intr_t); +void pcibr_xintr_preset(void *, int, xwidgetnum_t, iopaddr_t, xtalk_intr_vector_t); +void pcibr_intr_list_func(intr_arg_t); + +LOCAL void print_bridge_errcmd(uint32_t, char *); + +void pcibr_error_dump(pcibr_soft_t); +uint32_t pcibr_errintr_group(uint32_t); +LOCAL void pcibr_pioerr_check(pcibr_soft_t); +LOCAL void pcibr_error_intr_handler(intr_arg_t); + +LOCAL int pcibr_addr_toslot(pcibr_soft_t, iopaddr_t, pciio_space_t *, iopaddr_t *, pciio_function_t *); +LOCAL void pcibr_error_cleanup(pcibr_soft_t, int); +void pcibr_device_disable(pcibr_soft_t, int); +LOCAL int pcibr_pioerror(pcibr_soft_t, int, ioerror_mode_t, ioerror_t *); +int pcibr_dmard_error(pcibr_soft_t, int, ioerror_mode_t, ioerror_t *); +int pcibr_dmawr_error(pcibr_soft_t, int, ioerror_mode_t, ioerror_t *); +LOCAL int pcibr_error_handler(error_handler_arg_t, int, ioerror_mode_t, ioerror_t *); +int pcibr_error_devenable(devfs_handle_t, int); + +void pcibr_provider_startup(devfs_handle_t); +void pcibr_provider_shutdown(devfs_handle_t); + +int pcibr_reset(devfs_handle_t); +pciio_endian_t pcibr_endian_set(devfs_handle_t, pciio_endian_t, pciio_endian_t); +int pcibr_priority_bits_set(pcibr_soft_t, pciio_slot_t, pciio_priority_t); +pciio_priority_t pcibr_priority_set(devfs_handle_t, pciio_priority_t); +int pcibr_device_flags_set(devfs_handle_t, pcibr_device_flags_t); + +LOCAL cfg_p pcibr_config_addr(devfs_handle_t, unsigned); +uint64_t pcibr_config_get(devfs_handle_t, unsigned, unsigned); +LOCAL uint64_t do_pcibr_config_get(cfg_p, unsigned, unsigned); +void pcibr_config_set(devfs_handle_t, unsigned, unsigned, uint64_t); +LOCAL void do_pcibr_config_set(cfg_p, unsigned, unsigned, uint64_t); + +LOCAL pcibr_hints_t pcibr_hints_get(devfs_handle_t, int); +void pcibr_hints_fix_rrbs(devfs_handle_t); +void pcibr_hints_dualslot(devfs_handle_t, pciio_slot_t, pciio_slot_t); +void pcibr_hints_intr_bits(devfs_handle_t, pcibr_intr_bits_f *); +void pcibr_set_rrb_callback(devfs_handle_t, rrb_alloc_funct_t); +void pcibr_hints_handsoff(devfs_handle_t); +void pcibr_hints_subdevs(devfs_handle_t, pciio_slot_t, uint64_t); + +LOCAL int pcibr_slot_reset(devfs_handle_t,pciio_slot_t); +LOCAL int pcibr_slot_info_init(devfs_handle_t,pciio_slot_t); +LOCAL int pcibr_slot_info_free(devfs_handle_t,pciio_slot_t); +LOCAL int pcibr_slot_addr_space_init(devfs_handle_t,pciio_slot_t); +LOCAL int pcibr_slot_device_init(devfs_handle_t, pciio_slot_t); +LOCAL int pcibr_slot_guest_info_init(devfs_handle_t,pciio_slot_t); +LOCAL int pcibr_slot_initial_rrb_alloc(devfs_handle_t,pciio_slot_t); +LOCAL int pcibr_slot_call_device_attach(devfs_handle_t,pciio_slot_t); +LOCAL int pcibr_slot_call_device_detach(devfs_handle_t,pciio_slot_t); + +int pcibr_slot_powerup(devfs_handle_t,pciio_slot_t); +int pcibr_slot_shutdown(devfs_handle_t,pciio_slot_t); +int pcibr_slot_inquiry(devfs_handle_t,pciio_slot_t); + +/* ===================================================================== + * RRB management + */ + +#define LSBIT(word) ((word) &~ ((word)-1)) + +#define PCIBR_RRB_SLOT_VIRTUAL 8 + +LOCAL void +do_pcibr_rrb_clear(bridge_t *bridge, int rrb) +{ + bridgereg_t status; + + /* bridge_lock must be held; + * this RRB must be disabled. + */ + + /* wait until RRB has no outstanduing XIO packets. */ + while ((status = bridge->b_resp_status) & BRIDGE_RRB_INUSE(rrb)) { + ; /* XXX- beats on bridge. bad idea? */ + } + + /* if the RRB has data, drain it. */ + if (status & BRIDGE_RRB_VALID(rrb)) { + bridge->b_resp_clear = BRIDGE_RRB_CLEAR(rrb); + + /* wait until RRB is no longer valid. */ + while ((status = bridge->b_resp_status) & BRIDGE_RRB_VALID(rrb)) { + ; /* XXX- beats on bridge. bad idea? */ + } + } +} + +LOCAL void +do_pcibr_rrb_flush(bridge_t *bridge, int rrbn) +{ + reg_p rrbp = &bridge->b_rrb_map[rrbn & 1].reg; + bridgereg_t rrbv; + int shft = 4 * (rrbn >> 1); + unsigned ebit = BRIDGE_RRB_EN << shft; + + rrbv = *rrbp; + if (rrbv & ebit) + *rrbp = rrbv & ~ebit; + + do_pcibr_rrb_clear(bridge, rrbn); + + if (rrbv & ebit) + *rrbp = rrbv; +} + +/* + * pcibr_rrb_count_valid: count how many RRBs are + * marked valid for the specified PCI slot on this + * bridge. + * + * NOTE: The "slot" parameter for all pcibr_rrb + * management routines must include the "virtual" + * bit; when manageing both the normal and the + * virtual channel, separate calls to these + * routines must be made. To denote the virtual + * channel, add PCIBR_RRB_SLOT_VIRTUAL to the slot + * number. + * + * IMPL NOTE: The obvious algorithm is to iterate + * through the RRB fields, incrementing a count if + * the RRB is valid and matches the slot. However, + * it is much simpler to use an algorithm derived + * from the "partitioned add" idea. First, XOR in a + * pattern such that the fields that match this + * slot come up "all ones" and all other fields + * have zeros in the mismatching bits. Then AND + * together the bits in the field, so we end up + * with one bit turned on for each field that + * matched. Now we need to count these bits. This + * can be done either with a series of shift/add + * instructions or by using "tmp % 15"; I expect + * that the cascaded shift/add will be faster. + */ + +LOCAL int +do_pcibr_rrb_count_valid(bridge_t *bridge, + pciio_slot_t slot) +{ + bridgereg_t tmp; + + tmp = bridge->b_rrb_map[slot & 1].reg; + tmp ^= 0x11111111 * (7 - slot / 2); + tmp &= (0xCCCCCCCC & tmp) >> 2; + tmp &= (0x22222222 & tmp) >> 1; + tmp += tmp >> 4; + tmp += tmp >> 8; + tmp += tmp >> 16; + return tmp & 15; +} + +/* + * do_pcibr_rrb_count_avail: count how many RRBs are + * available to be allocated for the specified slot. + * + * IMPL NOTE: similar to the above, except we are + * just counting how many fields have the valid bit + * turned off. + */ +LOCAL int +do_pcibr_rrb_count_avail(bridge_t *bridge, + pciio_slot_t slot) +{ + bridgereg_t tmp; + + tmp = bridge->b_rrb_map[slot & 1].reg; + tmp = (0x88888888 & ~tmp) >> 3; + tmp += tmp >> 4; + tmp += tmp >> 8; + tmp += tmp >> 16; + return tmp & 15; +} + +/* + * do_pcibr_rrb_alloc: allocate some additional RRBs + * for the specified slot. Returns -1 if there were + * insufficient free RRBs to satisfy the request, + * or 0 if the request was fulfilled. + * + * Note that if a request can be partially filled, + * it will be, even if we return failure. + * + * IMPL NOTE: again we avoid iterating across all + * the RRBs; instead, we form up a word containing + * one bit for each free RRB, then peel the bits + * off from the low end. + */ +LOCAL int +do_pcibr_rrb_alloc(bridge_t *bridge, + pciio_slot_t slot, + int more) +{ + int rv = 0; + bridgereg_t reg, tmp, bit; + + reg = bridge->b_rrb_map[slot & 1].reg; + tmp = (0x88888888 & ~reg) >> 3; + while (more-- > 0) { + bit = LSBIT(tmp); + if (!bit) { + rv = -1; + break; + } + tmp &= ~bit; + reg = ((reg & ~(bit * 15)) | (bit * (8 + slot / 2))); + } + bridge->b_rrb_map[slot & 1].reg = reg; + return rv; +} + +/* + * do_pcibr_rrb_free: release some of the RRBs that + * have been allocated for the specified + * slot. Returns zero for success, or negative if + * it was unable to free that many RRBs. + * + * IMPL NOTE: We form up a bit for each RRB + * allocated to the slot, aligned with the VALID + * bitfield this time; then we peel bits off one at + * a time, releasing the corresponding RRB. + */ +LOCAL int +do_pcibr_rrb_free(bridge_t *bridge, + pciio_slot_t slot, + int less) +{ + int rv = 0; + bridgereg_t reg, tmp, clr, bit; + int i; + + clr = 0; + reg = bridge->b_rrb_map[slot & 1].reg; + + /* This needs to be done otherwise the rrb's on the virtual channel + * for this slot won't be freed !! + */ + tmp = reg & 0xbbbbbbbb; + + tmp ^= (0x11111111 * (7 - slot / 2)); + tmp &= (0x33333333 & tmp) << 2; + tmp &= (0x44444444 & tmp) << 1; + while (less-- > 0) { + bit = LSBIT(tmp); + if (!bit) { + rv = -1; + break; + } + tmp &= ~bit; + reg &= ~bit; + clr |= bit; + } + bridge->b_rrb_map[slot & 1].reg = reg; + + for (i = 0; i < 8; i++) + if (clr & (8 << (4 * i))) + do_pcibr_rrb_clear(bridge, (2 * i) + (slot & 1)); + + return rv; +} + +LOCAL void +do_pcibr_rrb_autoalloc(pcibr_soft_t pcibr_soft, + int slot, + int more_rrbs) +{ + bridge_t *bridge = pcibr_soft->bs_base; + int got; + + for (got = 0; got < more_rrbs; ++got) { + if (pcibr_soft->bs_rrb_res[slot & 7] > 0) + pcibr_soft->bs_rrb_res[slot & 7]--; + else if (pcibr_soft->bs_rrb_avail[slot & 1] > 0) + pcibr_soft->bs_rrb_avail[slot & 1]--; + else + break; + if (do_pcibr_rrb_alloc(bridge, slot, 1) < 0) + break; +#if PCIBR_RRB_DEBUG + printk( "do_pcibr_rrb_autoalloc: add one to slot %d%s\n", + slot & 7, slot & 8 ? "v" : ""); +#endif + pcibr_soft->bs_rrb_valid[slot]++; + } +#if PCIBR_RRB_DEBUG + printk("%s: %d+%d free RRBs. Allocation list:\n", pcibr_soft->bs_name, + pcibr_soft->bs_rrb_avail[0], + pcibr_soft->bs_rrb_avail[1]); + for (slot = 0; slot < 8; ++slot) + printk("\t%d+%d+%d", + 0xFFF & pcibr_soft->bs_rrb_valid[slot], + 0xFFF & pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL], + pcibr_soft->bs_rrb_res[slot]); + printk("\n"); +#endif +} + +/* + * Device driver interface to flush the write buffers for a specified + * device hanging off the bridge. + */ +int +pcibr_wrb_flush(devfs_handle_t pconn_vhdl) +{ + pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); + pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + bridge_t *bridge = pcibr_soft->bs_base; + volatile bridgereg_t *wrb_flush; + + wrb_flush = &(bridge->b_wr_req_buf[pciio_slot].reg); + while (*wrb_flush); + + return(0); +} +/* + * Device driver interface to request RRBs for a specified device + * hanging off a Bridge. The driver requests the total number of + * RRBs it would like for the normal channel (vchan0) and for the + * "virtual channel" (vchan1). The actual number allocated to each + * channel is returned. + * + * If we cannot allocate at least one RRB to a channel that needs + * at least one, return -1 (failure). Otherwise, satisfy the request + * as best we can and return 0. + */ +int +pcibr_rrb_alloc(devfs_handle_t pconn_vhdl, + int *count_vchan0, + int *count_vchan1) +{ + pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); + pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + bridge_t *bridge = pcibr_soft->bs_base; + int desired_vchan0; + int desired_vchan1; + int orig_vchan0; + int orig_vchan1; + int delta_vchan0; + int delta_vchan1; + int final_vchan0; + int final_vchan1; + int avail_rrbs; + unsigned s; + int error; + + /* + * TBD: temper request with admin info about RRB allocation, + * and according to demand from other devices on this Bridge. + * + * One way of doing this would be to allocate two RRBs + * for each device on the bus, before any drivers start + * asking for extras. This has the weakness that one + * driver might not give back an "extra" RRB until after + * another driver has already failed to get one that + * it wanted. + */ + + s = pcibr_lock(pcibr_soft); + + /* How many RRBs do we own? */ + orig_vchan0 = pcibr_soft->bs_rrb_valid[pciio_slot]; + orig_vchan1 = pcibr_soft->bs_rrb_valid[pciio_slot + PCIBR_RRB_SLOT_VIRTUAL]; + + /* How many RRBs do we want? */ + desired_vchan0 = count_vchan0 ? *count_vchan0 : orig_vchan0; + desired_vchan1 = count_vchan1 ? *count_vchan1 : orig_vchan1; + + /* How many RRBs are free? */ + avail_rrbs = pcibr_soft->bs_rrb_avail[pciio_slot & 1] + + pcibr_soft->bs_rrb_res[pciio_slot]; + + /* Figure desired deltas */ + delta_vchan0 = desired_vchan0 - orig_vchan0; + delta_vchan1 = desired_vchan1 - orig_vchan1; + + /* Trim back deltas to something + * that we can actually meet, by + * decreasing the ending allocation + * for whichever channel wants + * more RRBs. If both want the same + * number, cut the second channel. + * NOTE: do not change the allocation for + * a channel that was passed as NULL. + */ + while ((delta_vchan0 + delta_vchan1) > avail_rrbs) { + if (count_vchan0 && + (!count_vchan1 || + ((orig_vchan0 + delta_vchan0) > + (orig_vchan1 + delta_vchan1)))) + delta_vchan0--; + else + delta_vchan1--; + } + + /* Figure final RRB allocations + */ + final_vchan0 = orig_vchan0 + delta_vchan0; + final_vchan1 = orig_vchan1 + delta_vchan1; + + /* If either channel wants RRBs but our actions + * would leave it with none, declare an error, + * but DO NOT change any RRB allocations. + */ + if ((desired_vchan0 && !final_vchan0) || + (desired_vchan1 && !final_vchan1)) { + + error = -1; + + } else { + + /* Commit the allocations: free, then alloc. + */ + if (delta_vchan0 < 0) + (void) do_pcibr_rrb_free(bridge, pciio_slot, -delta_vchan0); + if (delta_vchan1 < 0) + (void) do_pcibr_rrb_free(bridge, PCIBR_RRB_SLOT_VIRTUAL + pciio_slot, -delta_vchan1); + + if (delta_vchan0 > 0) + (void) do_pcibr_rrb_alloc(bridge, pciio_slot, delta_vchan0); + if (delta_vchan1 > 0) + (void) do_pcibr_rrb_alloc(bridge, PCIBR_RRB_SLOT_VIRTUAL + pciio_slot, delta_vchan1); + + /* Return final values to caller. + */ + if (count_vchan0) + *count_vchan0 = final_vchan0; + if (count_vchan1) + *count_vchan1 = final_vchan1; + + /* prevent automatic changes to this slot's RRBs + */ + pcibr_soft->bs_rrb_fixed |= 1 << pciio_slot; + + /* Track the actual allocations, release + * any further reservations, and update the + * number of available RRBs. + */ + + pcibr_soft->bs_rrb_valid[pciio_slot] = final_vchan0; + pcibr_soft->bs_rrb_valid[pciio_slot + PCIBR_RRB_SLOT_VIRTUAL] = final_vchan1; + pcibr_soft->bs_rrb_avail[pciio_slot & 1] = + pcibr_soft->bs_rrb_avail[pciio_slot & 1] + + pcibr_soft->bs_rrb_res[pciio_slot] + - delta_vchan0 + - delta_vchan1; + pcibr_soft->bs_rrb_res[pciio_slot] = 0; + +#if PCIBR_RRB_DEBUG + printk("pcibr_rrb_alloc: slot %d set to %d+%d; %d+%d free\n", + pciio_slot, final_vchan0, final_vchan1, + pcibr_soft->bs_rrb_avail[0], + pcibr_soft->bs_rrb_avail[1]); + for (pciio_slot = 0; pciio_slot < 8; ++pciio_slot) + printk("\t%d+%d+%d", + 0xFFF & pcibr_soft->bs_rrb_valid[pciio_slot], + 0xFFF & pcibr_soft->bs_rrb_valid[pciio_slot + PCIBR_RRB_SLOT_VIRTUAL], + pcibr_soft->bs_rrb_res[pciio_slot]); + printk("\n"); +#endif + + error = 0; + } + + pcibr_unlock(pcibr_soft, s); + return error; +} + +/* + * Device driver interface to check the current state + * of the RRB allocations. + * + * pconn_vhdl is your PCI connection point (specifies which + * PCI bus and which slot). + * + * count_vchan0 points to where to return the number of RRBs + * assigned to the primary DMA channel, used by all DMA + * that does not explicitly ask for the alternate virtual + * channel. + * + * count_vchan1 points to where to return the number of RRBs + * assigned to the secondary DMA channel, used when + * PCIBR_VCHAN1 and PCIIO_DMA_A64 are specified. + * + * count_reserved points to where to return the number of RRBs + * that have been automatically reserved for your device at + * startup, but which have not been assigned to a + * channel. RRBs must be assigned to a channel to be used; + * this can be done either with an explicit pcibr_rrb_alloc + * call, or automatically by the infrastructure when a DMA + * translation is constructed. Any call to pcibr_rrb_alloc + * will release any unassigned reserved RRBs back to the + * free pool. + * + * count_pool points to where to return the number of RRBs + * that are currently unassigned and unreserved. This + * number can (and will) change as other drivers make calls + * to pcibr_rrb_alloc, or automatically allocate RRBs for + * DMA beyond their initial reservation. + * + * NULL may be passed for any of the return value pointers + * the caller is not interested in. + * + * The return value is "0" if all went well, or "-1" if + * there is a problem. Additionally, if the wrong vertex + * is passed in, one of the subsidiary support functions + * could panic with a "bad pciio fingerprint." + */ + +int +pcibr_rrb_check(devfs_handle_t pconn_vhdl, + int *count_vchan0, + int *count_vchan1, + int *count_reserved, + int *count_pool) +{ + pciio_info_t pciio_info; + pciio_slot_t pciio_slot; + pcibr_soft_t pcibr_soft; + unsigned s; + int error = -1; + + if ((pciio_info = pciio_info_get(pconn_vhdl)) && + (pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info)) && + ((pciio_slot = pciio_info_slot_get(pciio_info)) < 8)) { + + s = pcibr_lock(pcibr_soft); + + if (count_vchan0) + *count_vchan0 = + pcibr_soft->bs_rrb_valid[pciio_slot]; + + if (count_vchan1) + *count_vchan1 = + pcibr_soft->bs_rrb_valid[pciio_slot + PCIBR_RRB_SLOT_VIRTUAL]; + + if (count_reserved) + *count_reserved = + pcibr_soft->bs_rrb_res[pciio_slot]; + + if (count_pool) + *count_pool = + pcibr_soft->bs_rrb_avail[pciio_slot & 1]; + + error = 0; + + pcibr_unlock(pcibr_soft, s); + } + return error; +} + +/* pcibr_alloc_all_rrbs allocates all the rrbs available in the quantities + * requested for each of the devies. The evn_odd argument indicates whether + * allcoation for the odd or even rrbs is requested and next group of four pairse + * are the amount to assign to each device (they should sum to <= 8) and + * whether to set the viritual bit for that device (1 indictaes yes, 0 indicates no) + * the devices in order are either 0, 2, 4, 6 or 1, 3, 5, 7 + * if even_odd is even we alloc even rrbs else we allocate odd rrbs + * returns 0 if no errors else returns -1 + */ + +int +pcibr_alloc_all_rrbs(devfs_handle_t vhdl, int even_odd, + int dev_1_rrbs, int virt1, int dev_2_rrbs, int virt2, + int dev_3_rrbs, int virt3, int dev_4_rrbs, int virt4) +{ + devfs_handle_t pcibr_vhdl; +#ifdef colin + pcibr_soft_t pcibr_soft; +#else + pcibr_soft_t pcibr_soft = NULL; +#endif + bridge_t *bridge = NULL; + + uint32_t rrb_setting = 0; + int rrb_shift = 7; + uint32_t cur_rrb; + int dev_rrbs[4]; + int virt[4]; + int i, j; + unsigned s; + + if (GRAPH_SUCCESS == + hwgraph_traverse(vhdl, EDGE_LBL_PCI, &pcibr_vhdl)) { + pcibr_soft = pcibr_soft_get(pcibr_vhdl); + if (pcibr_soft) + bridge = pcibr_soft->bs_base; + hwgraph_vertex_unref(pcibr_vhdl); + } + if (bridge == NULL) + bridge = (bridge_t *) xtalk_piotrans_addr + (vhdl, NULL, 0, sizeof(bridge_t), 0); + + even_odd &= 1; + + dev_rrbs[0] = dev_1_rrbs; + dev_rrbs[1] = dev_2_rrbs; + dev_rrbs[2] = dev_3_rrbs; + dev_rrbs[3] = dev_4_rrbs; + + virt[0] = virt1; + virt[1] = virt2; + virt[2] = virt3; + virt[3] = virt4; + + if ((dev_1_rrbs + dev_2_rrbs + dev_3_rrbs + dev_4_rrbs) > 8) { + return -1; + } + if ((dev_1_rrbs < 0) || (dev_2_rrbs < 0) || (dev_3_rrbs < 0) || (dev_4_rrbs < 0)) { + return -1; + } + /* walk through rrbs */ + for (i = 0; i < 4; i++) { + if (virt[i]) { + cur_rrb = i | 0xc; + cur_rrb = cur_rrb << (rrb_shift * 4); + rrb_shift--; + rrb_setting = rrb_setting | cur_rrb; + dev_rrbs[i] = dev_rrbs[i] - 1; + } + for (j = 0; j < dev_rrbs[i]; j++) { + cur_rrb = i | 0x8; + cur_rrb = cur_rrb << (rrb_shift * 4); + rrb_shift--; + rrb_setting = rrb_setting | cur_rrb; + } + } + + if (pcibr_soft) + s = pcibr_lock(pcibr_soft); + + bridge->b_rrb_map[even_odd].reg = rrb_setting; + + if (pcibr_soft) { + + pcibr_soft->bs_rrb_fixed |= 0x55 << even_odd; + + /* since we've "FIXED" the allocations + * for these slots, we probably can dispense + * with tracking avail/res/valid data, but + * keeping it up to date helps debugging. + */ + + pcibr_soft->bs_rrb_avail[even_odd] = + 8 - (dev_1_rrbs + dev_2_rrbs + dev_3_rrbs + dev_4_rrbs); + + pcibr_soft->bs_rrb_res[even_odd + 0] = 0; + pcibr_soft->bs_rrb_res[even_odd + 2] = 0; + pcibr_soft->bs_rrb_res[even_odd + 4] = 0; + pcibr_soft->bs_rrb_res[even_odd + 6] = 0; + + pcibr_soft->bs_rrb_valid[even_odd + 0] = dev_1_rrbs - virt1; + pcibr_soft->bs_rrb_valid[even_odd + 2] = dev_2_rrbs - virt2; + pcibr_soft->bs_rrb_valid[even_odd + 4] = dev_3_rrbs - virt3; + pcibr_soft->bs_rrb_valid[even_odd + 6] = dev_4_rrbs - virt4; + + pcibr_soft->bs_rrb_valid[even_odd + 0 + PCIBR_RRB_SLOT_VIRTUAL] = virt1; + pcibr_soft->bs_rrb_valid[even_odd + 2 + PCIBR_RRB_SLOT_VIRTUAL] = virt2; + pcibr_soft->bs_rrb_valid[even_odd + 4 + PCIBR_RRB_SLOT_VIRTUAL] = virt3; + pcibr_soft->bs_rrb_valid[even_odd + 6 + PCIBR_RRB_SLOT_VIRTUAL] = virt4; + + pcibr_unlock(pcibr_soft, s); + } + return 0; +} + +/* + * pcibr_rrb_flush: chase down all the RRBs assigned + * to the specified connection point, and flush + * them. + */ +void +pcibr_rrb_flush(devfs_handle_t pconn_vhdl) +{ + pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info); + bridge_t *bridge = pcibr_soft->bs_base; + unsigned s; + reg_p rrbp; + unsigned rrbm; + int i; + int rrbn; + unsigned sval; + unsigned mask; + + sval = BRIDGE_RRB_EN | (pciio_slot >> 1); + mask = BRIDGE_RRB_EN | BRIDGE_RRB_PDEV; + rrbn = pciio_slot & 1; + rrbp = &bridge->b_rrb_map[rrbn].reg; + + s = pcibr_lock(pcibr_soft); + rrbm = *rrbp; + for (i = 0; i < 8; ++i) { + if ((rrbm & mask) == sval) + do_pcibr_rrb_flush(bridge, rrbn); + rrbm >>= 4; + rrbn += 2; + } + pcibr_unlock(pcibr_soft, s); +} + +/* ===================================================================== + * Device(x) register management + */ + +/* pcibr_try_set_device: attempt to modify Device(x) + * for the specified slot on the specified bridge + * as requested in flags, limited to the specified + * bits. Returns which BRIDGE bits were in conflict, + * or ZERO if everything went OK. + * + * Caller MUST hold pcibr_lock when calling this function. + */ +LOCAL int +pcibr_try_set_device(pcibr_soft_t pcibr_soft, + pciio_slot_t slot, + unsigned flags, + bridgereg_t mask) +{ + bridge_t *bridge; + pcibr_soft_slot_t slotp; + bridgereg_t old; + bridgereg_t new; + bridgereg_t chg; + bridgereg_t bad; + bridgereg_t badpmu; + bridgereg_t badd32; + bridgereg_t badd64; + bridgereg_t fix; + unsigned s; + bridgereg_t xmask; + + xmask = mask; + if (pcibr_soft->bs_xbridge) { + if (mask == BRIDGE_DEV_PMU_BITS) + xmask = XBRIDGE_DEV_PMU_BITS; + if (mask == BRIDGE_DEV_D64_BITS) + xmask = XBRIDGE_DEV_D64_BITS; + } + + slotp = &pcibr_soft->bs_slot[slot]; + + s = pcibr_lock(pcibr_soft); + + bridge = pcibr_soft->bs_base; + + old = slotp->bss_device; + + /* figure out what the desired + * Device(x) bits are based on + * the flags specified. + */ + + new = old; + + /* Currently, we inherit anything that + * the new caller has not specified in + * one way or another, unless we take + * action here to not inherit. + * + * This is needed for the "swap" stuff, + * since it could have been set via + * pcibr_endian_set -- altho note that + * any explicit PCIBR_BYTE_STREAM or + * PCIBR_WORD_VALUES will freely override + * the effect of that call (and vice + * versa, no protection either way). + * + * I want to get rid of pcibr_endian_set + * in favor of tracking DMA endianness + * using the flags specified when DMA + * channels are created. + */ + +#define BRIDGE_DEV_WRGA_BITS (BRIDGE_DEV_PMU_WRGA_EN | BRIDGE_DEV_DIR_WRGA_EN) +#define BRIDGE_DEV_SWAP_BITS (BRIDGE_DEV_SWAP_PMU | BRIDGE_DEV_SWAP_DIR) + + /* Do not use Barrier, Write Gather, + * or Prefetch unless asked. + * Leave everything else as it + * was from the last time. + */ + new = new + & ~BRIDGE_DEV_BARRIER + & ~BRIDGE_DEV_WRGA_BITS + & ~BRIDGE_DEV_PREF + ; + + /* Generic macro flags + */ + if (flags & PCIIO_DMA_DATA) { +#ifdef colin + new = new + & ~BRIDGE_DEV_BARRIER /* barrier off */ + | BRIDGE_DEV_PREF; /* prefetch on */ +#else + new = (new + & ~BRIDGE_DEV_BARRIER) /* barrier off */ + | BRIDGE_DEV_PREF; /* prefetch on */ +#endif + + } + if (flags & PCIIO_DMA_CMD) { +#ifdef colin + new = new + & ~BRIDGE_DEV_PREF /* prefetch off */ + & ~BRIDGE_DEV_WRGA_BITS /* write gather off */ + | BRIDGE_DEV_BARRIER; /* barrier on */ +#else + new = ((new + & ~BRIDGE_DEV_PREF) /* prefetch off */ + & ~BRIDGE_DEV_WRGA_BITS) /* write gather off */ + | BRIDGE_DEV_BARRIER; /* barrier on */ +#endif + } + /* Generic detail flags + */ + if (flags & PCIIO_WRITE_GATHER) + new |= BRIDGE_DEV_WRGA_BITS; + if (flags & PCIIO_NOWRITE_GATHER) + new &= ~BRIDGE_DEV_WRGA_BITS; + + if (flags & PCIIO_PREFETCH) + new |= BRIDGE_DEV_PREF; + if (flags & PCIIO_NOPREFETCH) + new &= ~BRIDGE_DEV_PREF; + + if (flags & PCIBR_WRITE_GATHER) + new |= BRIDGE_DEV_WRGA_BITS; + if (flags & PCIBR_NOWRITE_GATHER) + new &= ~BRIDGE_DEV_WRGA_BITS; + + if (flags & PCIIO_BYTE_STREAM) + new |= (pcibr_soft->bs_xbridge) ? + BRIDGE_DEV_SWAP_DIR : BRIDGE_DEV_SWAP_BITS; + if (flags & PCIIO_WORD_VALUES) + new &= (pcibr_soft->bs_xbridge) ? + ~BRIDGE_DEV_SWAP_DIR : ~BRIDGE_DEV_SWAP_BITS; + + /* Provider-specific flags + */ + if (flags & PCIBR_PREFETCH) + new |= BRIDGE_DEV_PREF; + if (flags & PCIBR_NOPREFETCH) + new &= ~BRIDGE_DEV_PREF; + + if (flags & PCIBR_PRECISE) + new |= BRIDGE_DEV_PRECISE; + if (flags & PCIBR_NOPRECISE) + new &= ~BRIDGE_DEV_PRECISE; + + if (flags & PCIBR_BARRIER) + new |= BRIDGE_DEV_BARRIER; + if (flags & PCIBR_NOBARRIER) + new &= ~BRIDGE_DEV_BARRIER; + + if (flags & PCIBR_64BIT) + new |= BRIDGE_DEV_DEV_SIZE; + if (flags & PCIBR_NO64BIT) + new &= ~BRIDGE_DEV_DEV_SIZE; + + chg = old ^ new; /* what are we changing, */ + chg &= xmask; /* of the interesting bits */ + + if (chg) { + + badd32 = slotp->bss_d32_uctr ? (BRIDGE_DEV_D32_BITS & chg) : 0; + if (pcibr_soft->bs_xbridge) { + badpmu = slotp->bss_pmu_uctr ? (XBRIDGE_DEV_PMU_BITS & chg) : 0; + badd64 = slotp->bss_d64_uctr ? (XBRIDGE_DEV_D64_BITS & chg) : 0; + } else { + badpmu = slotp->bss_pmu_uctr ? (BRIDGE_DEV_PMU_BITS & chg) : 0; + badd64 = slotp->bss_d64_uctr ? (BRIDGE_DEV_D64_BITS & chg) : 0; + } + bad = badpmu | badd32 | badd64; + + if (bad) { + + /* some conflicts can be resolved by + * forcing the bit on. this may cause + * some performance degredation in + * the stream(s) that want the bit off, + * but the alternative is not allowing + * the new stream at all. + */ +#ifdef colin + if (fix = bad & (BRIDGE_DEV_PRECISE | + BRIDGE_DEV_BARRIER)) { +#else + if ( (fix = bad & (BRIDGE_DEV_PRECISE | + BRIDGE_DEV_BARRIER)) ){ +#endif + bad &= ~fix; + /* don't change these bits if + * they are already set in "old" + */ + chg &= ~(fix & old); + } + /* some conflicts can be resolved by + * forcing the bit off. this may cause + * some performance degredation in + * the stream(s) that want the bit on, + * but the alternative is not allowing + * the new stream at all. + */ +#ifdef colin + if (fix = bad & (BRIDGE_DEV_WRGA_BITS | + BRIDGE_DEV_PREF)) { +#else + if ( (fix = bad & (BRIDGE_DEV_WRGA_BITS | + BRIDGE_DEV_PREF)) ){ +#endif + bad &= ~fix; + /* don't change these bits if + * we wanted to turn them on. + */ + chg &= ~(fix & new); + } + /* conflicts in other bits mean + * we can not establish this DMA + * channel while the other(s) are + * still present. + */ + if (bad) { + pcibr_unlock(pcibr_soft, s); +#if (DEBUG && PCIBR_DEV_DEBUG) + printk("pcibr_try_set_device: mod blocked by %R\n", bad, device_bits); +#endif + return bad; + } + } + } + if (mask == BRIDGE_DEV_PMU_BITS) + slotp->bss_pmu_uctr++; + if (mask == BRIDGE_DEV_D32_BITS) + slotp->bss_d32_uctr++; + if (mask == BRIDGE_DEV_D64_BITS) + slotp->bss_d64_uctr++; + + /* the value we want to write is the + * original value, with the bits for + * our selected changes flipped, and + * with any disabled features turned off. + */ + new = old ^ chg; /* only change what we want to change */ + + if (slotp->bss_device == new) { + pcibr_unlock(pcibr_soft, s); + return 0; + } + bridge->b_device[slot].reg = new; + slotp->bss_device = new; + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ + pcibr_unlock(pcibr_soft, s); +#if DEBUG && PCIBR_DEV_DEBUG + printk("pcibr Device(%d): 0x%p\n", slot, bridge->b_device[slot].reg); +#endif + + return 0; +} + +void +pcibr_release_device(pcibr_soft_t pcibr_soft, + pciio_slot_t slot, + bridgereg_t mask) +{ + pcibr_soft_slot_t slotp; + unsigned s; + + slotp = &pcibr_soft->bs_slot[slot]; + + s = pcibr_lock(pcibr_soft); + + if (mask == BRIDGE_DEV_PMU_BITS) + slotp->bss_pmu_uctr--; + if (mask == BRIDGE_DEV_D32_BITS) + slotp->bss_d32_uctr--; + if (mask == BRIDGE_DEV_D64_BITS) + slotp->bss_d64_uctr--; + + pcibr_unlock(pcibr_soft, s); +} + +/* + * flush write gather buffer for slot + */ +LOCAL void +pcibr_device_write_gather_flush(pcibr_soft_t pcibr_soft, + pciio_slot_t slot) +{ + bridge_t *bridge; + unsigned s; + volatile uint32_t wrf; + s = pcibr_lock(pcibr_soft); + bridge = pcibr_soft->bs_base; + wrf = bridge->b_wr_req_buf[slot].reg; + pcibr_unlock(pcibr_soft, s); +} + +/* ===================================================================== + * Bridge (pcibr) "Device Driver" entry points + */ + +/* + * pcibr_probe_slot: read a config space word + * while trapping any errors; reutrn zero if + * all went OK, or nonzero if there was an error. + * The value read, if any, is passed back + * through the valp parameter. + */ +LOCAL int +pcibr_probe_slot(bridge_t *bridge, + cfg_p cfg, + unsigned *valp) +{ + int rv; + bridgereg_t old_enable, new_enable; + + old_enable = bridge->b_int_enable; + new_enable = old_enable & ~BRIDGE_IMR_PCI_MST_TIMEOUT; + + bridge->b_int_enable = new_enable; + +#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) +#if defined(BRINGUP) + /* + * The xbridge doesn't clear b_err_int_view unless + * multi-err is cleared... + */ + if (is_xbridge(bridge)) + if (bridge->b_err_int_view & BRIDGE_ISR_PCI_MST_TIMEOUT) { + bridge->b_int_rst_stat = BRIDGE_IRR_MULTI_CLR; + } +#endif /* BRINGUP */ +#endif /* CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 */ + + if (bridge->b_int_status & BRIDGE_IRR_PCI_GRP) { + bridge->b_int_rst_stat = BRIDGE_IRR_PCI_GRP_CLR; + (void) bridge->b_wid_tflush; /* flushbus */ + } + rv = badaddr_val((void *) cfg, 4, valp); + +#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) +#if defined(BRINGUP) + /* + * The xbridge doesn't set master timeout in b_int_status + * here. Fortunately it's in error_interrupt_view. + */ + if (is_xbridge(bridge)) + if (bridge->b_err_int_view & BRIDGE_ISR_PCI_MST_TIMEOUT) { + bridge->b_int_rst_stat = BRIDGE_IRR_MULTI_CLR; + rv = 1; /* unoccupied slot */ + } +#endif /* BRINGUP */ +#endif /* CONFIG_SGI_IP35 */ + + bridge->b_int_enable = old_enable; + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ + + return rv; +} + +/* + * pcibr_init: called once during system startup or + * when a loadable driver is loaded. + * + * The driver_register function should normally + * be in _reg, not _init. But the pcibr driver is + * required by devinit before the _reg routines + * are called, so this is an exception. + */ +void +pcibr_init(void) +{ +#if DEBUG && ATTACH_DEBUG + printk("pcibr_init\n"); +#endif + + xwidget_driver_register(XBRIDGE_WIDGET_PART_NUM, + XBRIDGE_WIDGET_MFGR_NUM, + "pcibr_", + 0); + xwidget_driver_register(BRIDGE_WIDGET_PART_NUM, + BRIDGE_WIDGET_MFGR_NUM, + "pcibr_", + 0); +} + +/* + * open/close mmap/munmap interface would be used by processes + * that plan to map the PCI bridge, and muck around with the + * registers. This is dangerous to do, and will be allowed + * to a select brand of programs. Typically these are + * diagnostics programs, or some user level commands we may + * write to do some weird things. + * To start with expect them to have root priveleges. + * We will ask for more later. + */ +/* ARGSUSED */ +int +pcibr_open(devfs_handle_t *devp, int oflag, int otyp, cred_t *credp) +{ +#ifndef CONFIG_IA64_SGI_IO + if (!_CAP_CRABLE((uint64_t)credp, (uint64_t)CAP_DEVICE_MGT)) + return EPERM; +#endif + return 0; +} + +/*ARGSUSED */ +int +pcibr_close(devfs_handle_t dev, int oflag, int otyp, cred_t *crp) +{ + return 0; +} + +/*ARGSUSED */ +int +pcibr_map(devfs_handle_t dev, vhandl_t *vt, off_t off, size_t len, uint prot) +{ + int error; + devfs_handle_t vhdl = dev_to_vhdl(dev); + devfs_handle_t pcibr_vhdl = hwgraph_connectpt_get(vhdl); + pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); + bridge_t *bridge = pcibr_soft->bs_base; + + hwgraph_vertex_unref(pcibr_vhdl); + + ASSERT(pcibr_soft); + len = ctob(btoc(len)); /* Make len page aligned */ + error = v_mapphys(vt, (void *) ((__psunsigned_t) bridge + off), len); + + /* + * If the offset being mapped corresponds to the flash prom + * base, and if the mapping succeeds, and if the user + * has requested the protections to be WRITE, enable the + * flash prom to be written. + * + * XXX- deprecate this in favor of using the + * real flash driver ... + */ + if (!error && + ((off == BRIDGE_EXTERNAL_FLASH) || + (len > BRIDGE_EXTERNAL_FLASH))) { + int s; + + /* + * ensure that we write and read without any interruption. + * The read following the write is required for the Bridge war + */ + s = splhi(); + bridge->b_wid_control |= BRIDGE_CTRL_FLASH_WR_EN; + bridge->b_wid_control; /* inval addr bug war */ + splx(s); + } + return error; +} + +/*ARGSUSED */ +int +pcibr_unmap(devfs_handle_t dev, vhandl_t *vt) +{ + devfs_handle_t pcibr_vhdl = hwgraph_connectpt_get((devfs_handle_t) dev); + pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); + bridge_t *bridge = pcibr_soft->bs_base; + + hwgraph_vertex_unref(pcibr_vhdl); + + /* + * If flashprom write was enabled, disable it, as + * this is the last unmap. + */ + if (bridge->b_wid_control & BRIDGE_CTRL_FLASH_WR_EN) { + int s; + + /* + * ensure that we write and read without any interruption. + * The read following the write is required for the Bridge war + */ + s = splhi(); + bridge->b_wid_control &= ~BRIDGE_CTRL_FLASH_WR_EN; + bridge->b_wid_control; /* inval addr bug war */ + splx(s); + } + return 0; +} + +/* This is special case code used by grio. There are plans to make + * this a bit more general in the future, but till then this should + * be sufficient. + */ +pciio_slot_t +pcibr_device_slot_get(devfs_handle_t dev_vhdl) +{ + char devname[MAXDEVNAME]; + devfs_handle_t tdev; + pciio_info_t pciio_info; + pciio_slot_t slot = PCIIO_SLOT_NONE; + + vertex_to_name(dev_vhdl, devname, MAXDEVNAME); + + /* run back along the canonical path + * until we find a PCI connection point. + */ + tdev = hwgraph_connectpt_get(dev_vhdl); + while (tdev != GRAPH_VERTEX_NONE) { + pciio_info = pciio_info_chk(tdev); + if (pciio_info) { + slot = pciio_info_slot_get(pciio_info); + break; + } + hwgraph_vertex_unref(tdev); + tdev = hwgraph_connectpt_get(tdev); + } + hwgraph_vertex_unref(tdev); + + return slot; +} +/*========================================================================== + * BRIDGE PCI SLOT RELATED IOCTLs + */ +/* + * pcibr_slot_powerup + * Software initialize the pci slot. + */ +int +pcibr_slot_powerup(devfs_handle_t pcibr_vhdl,pciio_slot_t slot) +{ + /* Check for the valid slot */ + if (!PCIBR_VALID_SLOT(slot)) + return(EINVAL); + + if (pcibr_device_attach(pcibr_vhdl,slot)) + return(EINVAL); + + return(0); +} +/* + * pcibr_slot_shutdown + * Software shutdown the pci slot + */ +int +pcibr_slot_shutdown(devfs_handle_t pcibr_vhdl,pciio_slot_t slot) +{ + /* Check for valid slot */ + if (!PCIBR_VALID_SLOT(slot)) + return(EINVAL); + + if (pcibr_device_detach(pcibr_vhdl,slot)) + return(EINVAL); + + return(0); +} + +char *pci_space_name[] = {"NONE", + "ROM", + "IO", + "", + "MEM", + "MEM32", + "MEM64", + "CFG", + "WIN0", + "WIN1", + "WIN2", + "WIN3", + "WIN4", + "WIN5", + "", + "BAD"}; + +void +pcibr_slot_func_info_print(pcibr_info_h pcibr_infoh, int func, int verbose) +{ + pcibr_info_t pcibr_info = pcibr_infoh[func]; + char name[MAXDEVNAME]; + int win; + + if (!pcibr_info) + return; + +#ifdef SUPPORT_PRINTING_V_FORMAT + sprintf(name, "%v", pcibr_info->f_vertex); +#endif + if (!verbose) { + printk("\tSlot Name : %s\n",name); + } else { + printk("\tPER-SLOT FUNCTION INFO\n"); +#ifdef SUPPORT_PRINTING_V_FORMAT + sprintf(name, "%v", pcibr_info->f_vertex); +#endif + printk("\tSlot Name : %s\n",name); + printk("\tPCI Bus : %d ",pcibr_info->f_bus); + printk("Slot : %d ", pcibr_info->f_slot); + printk("Function : %d\n", pcibr_info->f_func); +#ifdef SUPPORT_PRINTING_V_FORMAT + sprintf(name, "%v", pcibr_info->f_master); +#endif + printk("\tBus provider : %s\n",name); + printk("\tProvider Fns : 0x%p ", pcibr_info->f_pops); + printk("Error Handler : 0x%p Arg 0x%p\n", + pcibr_info->f_efunc,pcibr_info->f_einfo); + } + printk("\tVendorId : 0x%x " , pcibr_info->f_vendor); + printk("DeviceId : 0x%x\n", pcibr_info->f_device); + + printk("\n\tBase Register Info\n"); + printk("\t\tReg#\tBase\t\tSize\t\tSpace\n"); + for(win = 0 ; win < 6 ; win++) + printk("\t\t%d\t0x%lx\t%s0x%lx\t%s%s\n", + win, + pcibr_info->f_window[win].w_base, + pcibr_info->f_window[win].w_base >= 0x100000 ? "": "\t", + pcibr_info->f_window[win].w_size, + pcibr_info->f_window[win].w_size >= 0x100000 ? "": "\t", + pci_space_name[pcibr_info->f_window[win].w_space]); + + printk("\t\t7\t0x%x\t%s0x%x\t%sROM\n", + pcibr_info->f_rbase, + pcibr_info->f_rbase > 0x100000 ? "" : "\t", + pcibr_info->f_rsize, + pcibr_info->f_rsize > 0x100000 ? "" : "\t"); + + printk("\n\tInterrupt Bit Map\n"); + printk("\t\tPCI Int#\tBridge Pin#\n"); + for (win = 0 ; win < 4; win++) + printk("\t\tINT%c\t\t%d\n",win+'A',pcibr_info->f_ibit[win]); + printk("\n"); +} + + +void +pcibr_slot_info_print(pcibr_soft_t pcibr_soft, + pciio_slot_t slot, + int verbose) +{ + pcibr_soft_slot_t pss; + char slot_conn_name[MAXDEVNAME]; + int func; + bridge_t *bridge = pcibr_soft->bs_base; + bridgereg_t b_resp; + reg_p b_respp; + int dev; + bridgereg_t b_int_device; + bridgereg_t b_int_host; + bridgereg_t b_int_enable; + int pin = 0; + int int_bits = 0; + + pss = &pcibr_soft->bs_slot[slot]; + + printk("\nPCI INFRASTRUCTURAL INFO FOR SLOT %d\n\n", slot); + + if (verbose) { + printk("\tHost Present ? %s ", pss->has_host ? "yes" : "no"); + printk("\tHost Slot : %d\n",pss->host_slot); +#ifdef SUPPORT_PRINTING_V_FORMAT + sprintf(slot_conn_name, "%v", pss->slot_conn); +#endif + printk("\tSlot Conn : %s\n",slot_conn_name); + printk("\t#Functions : %d\n",pss->bss_ninfo); + } + for (func = 0; func < pss->bss_ninfo; func++) + pcibr_slot_func_info_print(pss->bss_infos,func, verbose); + printk("\tDevio[Space:%s,Base:0x%lx,Shadow:0x%x]\n", + pci_space_name[pss->bss_devio.bssd_space], + pss->bss_devio.bssd_base, + pss->bss_device); + + if (verbose) { + printk("\tUsage counts : pmu %d d32 %d d64 %d\n", + pss->bss_pmu_uctr,pss->bss_d32_uctr,pss->bss_d64_uctr); + + printk("\tDirect Trans Info : d64_base 0x%x d64_flags 0x%x" + "d32_base 0x%x d32_flags 0x%x\n", + (unsigned int)pss->bss_d64_base, pss->bss_d64_flags, + (unsigned int)pss->bss_d32_base, pss->bss_d32_flags); + + printk("\tExt ATEs active ? %s", + pss->bss_ext_ates_active ? "yes" : "no"); + printk(" Command register : 0x%p ", pss->bss_cmd_pointer); + printk(" Shadow command val : 0x%x\n", pss->bss_cmd_shadow); + } + + printk("\tSoft RRB Info[Valid %d+%d, Reserved %d]\n", + pcibr_soft->bs_rrb_valid[slot], + pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL], + pcibr_soft->bs_rrb_res[slot]); + + + if (slot & 1) + b_respp = &bridge->b_odd_resp; + else + b_respp = &bridge->b_even_resp; + + b_resp = *b_respp; + + printk("\n\tBridge RRB Info\n"); + printk("\t\tRRB#\tVirtual\n"); + for (dev = 0; dev < 8; dev++) { + if ((b_resp & BRIDGE_RRB_EN) && + (b_resp & BRIDGE_RRB_PDEV) == (slot >> 1)) + printk( "\t\t%d\t%s\n", + dev, + (b_resp & BRIDGE_RRB_VDEV) ? "yes" : "no"); + b_resp >>= 4; + + } + b_int_device = bridge->b_int_device; + b_int_enable = bridge->b_int_enable; + + printk("\n\tBridge Interrupt Info\n" + "\t\tInt_device 0x%x\n\t\tInt_enable 0x%x " + "\n\t\tEnabled pin#s for this slot: ", + b_int_device, + b_int_enable); + + while (b_int_device) { + if (((b_int_device & 7) == slot) && + (b_int_enable & (1 << pin))) { + int_bits |= (1 << pin); + printk("%d ", pin); + } + pin++; + b_int_device >>= 3; + } + + if (!int_bits) + printk("NONE "); + + b_int_host = bridge->b_int_addr[slot].addr; + + printk("\n\t\tInt_host_addr 0x%x\n", + b_int_host); + +} + +int verbose = 0; +/* + * pcibr_slot_inquiry + * Print information about the pci slot maintained by the infrastructure. + * Current information displayed + * Slot hwgraph name + * Vendor/Device info + * Base register info + * Interrupt mapping from device pins to the bridge pins + * Devio register + * Software RRB info + * RRB register info + * In verbose mode following additional info is displayed + * Host/Gues info + * PCI Bus #,slot #, function # + * Slot provider hwgraph name + * Provider Functions + * Error handler + * DMA mapping usage counters + * DMA direct translation info + * External SSRAM workaround info + */ +int +pcibr_slot_inquiry(devfs_handle_t pcibr_vhdl, pciio_slot_t slot) +{ + pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); + + /* Make sure that we are dealing with a bridge device vertex */ + if (!pcibr_soft) + return(EINVAL); + + /* Make sure that we have a valid pci slot number or PCIIO_SLOT_NONE */ + if ((!PCIBR_VALID_SLOT(slot)) && (slot != PCIIO_SLOT_NONE)) + return(EINVAL); + + /* Print information for the requested pci slot */ + if (slot != PCIIO_SLOT_NONE) { + pcibr_slot_info_print(pcibr_soft,slot,verbose); + return(0); + } + /* Print information for all the slots */ + for (slot = 0; slot < 8; slot++) + pcibr_slot_info_print(pcibr_soft, slot,verbose); + return(0); +} + +/*ARGSUSED */ +int +pcibr_ioctl(devfs_handle_t dev, + int cmd, + void *arg, + int flag, + struct cred *cr, + int *rvalp) +{ + devfs_handle_t pcibr_vhdl = hwgraph_connectpt_get((devfs_handle_t)dev); +#ifdef colin + pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); +#endif + int error = 0; + + hwgraph_vertex_unref(pcibr_vhdl); + + switch (cmd) { +#ifdef colin + case GIOCSETBW: + { + grio_ioctl_info_t info; + pciio_slot_t slot = 0; + + if (!cap_able((uint64_t)CAP_DEVICE_MGT)) { + error = EPERM; + break; + } + if (COPYIN(arg, &info, sizeof(grio_ioctl_info_t))) { + error = EFAULT; + break; + } +#ifdef GRIO_DEBUG + printk("pcibr:: prev_vhdl: %d reqbw: %lld\n", + info.prev_vhdl, info.reqbw); +#endif /* GRIO_DEBUG */ + + if ((slot = pcibr_device_slot_get(info.prev_vhdl)) == + PCIIO_SLOT_NONE) { + error = EIO; + break; + } + if (info.reqbw) + pcibr_priority_bits_set(pcibr_soft, slot, PCI_PRIO_HIGH); + break; + } + + case GIOCRELEASEBW: + { + grio_ioctl_info_t info; + pciio_slot_t slot = 0; + + if (!cap_able(CAP_DEVICE_MGT)) { + error = EPERM; + break; + } + if (COPYIN(arg, &info, sizeof(grio_ioctl_info_t))) { + error = EFAULT; + break; + } +#ifdef GRIO_DEBUG + printk("pcibr:: prev_vhdl: %d reqbw: %lld\n", + info.prev_vhdl, info.reqbw); +#endif /* GRIO_DEBUG */ + + if ((slot = pcibr_device_slot_get(info.prev_vhdl)) == + PCIIO_SLOT_NONE) { + error = EIO; + break; + } + if (info.reqbw) + pcibr_priority_bits_set(pcibr_soft, slot, PCI_PRIO_LOW); + break; + } +#endif /* colin */ + + case PCIBR_SLOT_POWERUP: + { + pciio_slot_t slot; + + if (!cap_able(CAP_DEVICE_MGT)) { + error = EPERM; + break; + } + + slot = (pciio_slot_t)(uint64_t)arg; + error = pcibr_slot_powerup(pcibr_vhdl,slot); + break; + } + case PCIBR_SLOT_SHUTDOWN: + { + pciio_slot_t slot; + + if (!cap_able(CAP_DEVICE_MGT)) { + error = EPERM; + break; + } + + slot = (pciio_slot_t)(uint64_t)arg; + error = pcibr_slot_shutdown(pcibr_vhdl,slot); + break; + } + case PCIBR_SLOT_INQUIRY: + { + pciio_slot_t slot; + + if (!cap_able(CAP_DEVICE_MGT)) { + error = EPERM; + break; + } + + slot = (pciio_slot_t)(uint64_t)arg; + error = pcibr_slot_inquiry(pcibr_vhdl,slot); + break; + } + default: + break; + + } + + return error; +} + +void +pcibr_freeblock_sub(iopaddr_t *free_basep, + iopaddr_t *free_lastp, + iopaddr_t base, + size_t size) +{ + iopaddr_t free_base = *free_basep; + iopaddr_t free_last = *free_lastp; + iopaddr_t last = base + size - 1; + + if ((last < free_base) || (base > free_last)); /* free block outside arena */ + + else if ((base <= free_base) && (last >= free_last)) + /* free block contains entire arena */ + *free_basep = *free_lastp = 0; + + else if (base <= free_base) + /* free block is head of arena */ + *free_basep = last + 1; + + else if (last >= free_last) + /* free block is tail of arena */ + *free_lastp = base - 1; + + /* + * We are left with two regions: the free area + * in the arena "below" the block, and the free + * area in the arena "above" the block. Keep + * the one that is bigger. + */ + + else if ((base - free_base) > (free_last - last)) + *free_lastp = base - 1; /* keep lower chunk */ + else + *free_basep = last + 1; /* keep upper chunk */ +} + +#ifdef IRIX +/* Convert from ssram_bits in control register to number of SSRAM entries */ +#define ATE_NUM_ENTRIES(n) _ate_info[n] + +/* Possible choices for number of ATE entries in Bridge's SSRAM */ +LOCAL int _ate_info[] = +{ + 0, /* 0 entries */ + 8 * 1024, /* 8K entries */ + 16 * 1024, /* 16K entries */ + 64 * 1024 /* 64K entries */ +}; + +#define ATE_NUM_SIZES (sizeof(_ate_info) / sizeof(int)) +#define ATE_PROBE_VALUE 0x0123456789abcdefULL +#endif /* IRIX */ + +/* + * Determine the size of this bridge's external mapping SSRAM, and set + * the control register appropriately to reflect this size, and initialize + * the external SSRAM. + */ +#ifndef BRINGUP +LOCAL int +pcibr_init_ext_ate_ram(bridge_t *bridge) +{ + int largest_working_size = 0; + int num_entries, entry; + int i, j; + bridgereg_t old_enable, new_enable; + int s; + + if (is_xbridge(bridge)) + return 0; + + /* Probe SSRAM to determine its size. */ + old_enable = bridge->b_int_enable; + new_enable = old_enable & ~BRIDGE_IMR_PCI_MST_TIMEOUT; + bridge->b_int_enable = new_enable; + + for (i = 1; i < ATE_NUM_SIZES; i++) { + /* Try writing a value */ + bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(i) - 1] = ATE_PROBE_VALUE; + + /* Guard against wrap */ + for (j = 1; j < i; j++) + bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(j) - 1] = 0; + + /* See if value was written */ + if (bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(i) - 1] == ATE_PROBE_VALUE) + largest_working_size = i; + } + bridge->b_int_enable = old_enable; + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ + + /* + * ensure that we write and read without any interruption. + * The read following the write is required for the Bridge war + */ + + s = splhi(); +#ifdef colin + bridge->b_wid_control = (bridge->b_wid_control + & ~BRIDGE_CTRL_SSRAM_SIZE_MASK) + | BRIDGE_CTRL_SSRAM_SIZE(largest_working_size); +#endif + bridge->b_wid_control; /* inval addr bug war */ + splx(s); + + num_entries = ATE_NUM_ENTRIES(largest_working_size); + +#if PCIBR_ATE_DEBUG + if (num_entries) + printk("bridge at 0x%x: clearing %d external ATEs\n", bridge, num_entries); + else + printk("bridge at 0x%x: no externa9422l ATE RAM found\n", bridge); +#endif + + /* Initialize external mapping entries */ + for (entry = 0; entry < num_entries; entry++) + bridge->b_ext_ate_ram[entry] = 0; + + return (num_entries); +} +#endif /* !BRINGUP */ + +/* + * Allocate "count" contiguous Bridge Address Translation Entries + * on the specified bridge to be used for PCI to XTALK mappings. + * Indices in rm map range from 1..num_entries. Indicies returned + * to caller range from 0..num_entries-1. + * + * Return the start index on success, -1 on failure. + */ +LOCAL int +pcibr_ate_alloc(pcibr_soft_t pcibr_soft, int count) +{ + int index = 0; + + index = (int) rmalloc(pcibr_soft->bs_int_ate_map, (size_t) count); + + if (!index && pcibr_soft->bs_ext_ate_map) + index = (int) rmalloc(pcibr_soft->bs_ext_ate_map, (size_t) count); + + /* rmalloc manages resources in the 1..n + * range, with 0 being failure. + * pcibr_ate_alloc manages resources + * in the 0..n-1 range, with -1 being failure. + */ + return index - 1; +} + +LOCAL void +pcibr_ate_free(pcibr_soft_t pcibr_soft, int index, int count) +/* Who says there's no such thing as a free meal? :-) */ +{ + /* note the "+1" since rmalloc handles 1..n but + * we start counting ATEs at zero. + */ + rmfree((index < pcibr_soft->bs_int_ate_size) + ? pcibr_soft->bs_int_ate_map + : pcibr_soft->bs_ext_ate_map, + count, index + 1); +} + +LOCAL pcibr_info_t +pcibr_info_get(devfs_handle_t vhdl) +{ + return (pcibr_info_t) pciio_info_get(vhdl); +} + +pcibr_info_t +pcibr_device_info_new( + pcibr_soft_t pcibr_soft, + pciio_slot_t slot, + pciio_function_t rfunc, + pciio_vendor_id_t vendor, + pciio_device_id_t device) +{ + pcibr_info_t pcibr_info; + pciio_function_t func; + int ibit; + + func = (rfunc == PCIIO_FUNC_NONE) ? 0 : rfunc; + + NEW(pcibr_info); + pciio_device_info_new(&pcibr_info->f_c, + pcibr_soft->bs_vhdl, + slot, rfunc, + vendor, device); + + if (slot != PCIIO_SLOT_NONE) { + + /* + * Currently favored mapping from PCI + * slot number and INTA/B/C/D to Bridge + * PCI Interrupt Bit Number: + * + * SLOT A B C D + * 0 0 4 0 4 + * 1 1 5 1 5 + * 2 2 6 2 6 + * 3 3 7 3 7 + * 4 4 0 4 0 + * 5 5 1 5 1 + * 6 6 2 6 2 + * 7 7 3 7 3 + * + * XXX- allow pcibr_hints to override default + * XXX- allow ADMIN to override pcibr_hints + */ + for (ibit = 0; ibit < 4; ++ibit) + pcibr_info->f_ibit[ibit] = + (slot + 4 * ibit) & 7; + + /* + * Record the info in the sparse func info space. + */ +printk("pcibr_device_info_new: slot= %d func= %d bss_ninfo= %d pcibr_info= 0x%p\n", slot, func, pcibr_soft->bs_slot[slot].bss_ninfo, pcibr_info); + + if (func < pcibr_soft->bs_slot[slot].bss_ninfo) + pcibr_soft->bs_slot[slot].bss_infos[func] = pcibr_info; + } + return pcibr_info; +} + +void +pcibr_device_info_free(devfs_handle_t pcibr_vhdl, pciio_slot_t slot) +{ + pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); + pcibr_info_t pcibr_info; + pciio_function_t func; + pcibr_soft_slot_t slotp = &pcibr_soft->bs_slot[slot]; + int nfunc = slotp->bss_ninfo; + + + for (func = 0; func < nfunc; func++) { + pcibr_info = slotp->bss_infos[func]; + + if (!pcibr_info) + continue; + + slotp->bss_infos[func] = 0; + pciio_device_info_unregister(pcibr_vhdl, &pcibr_info->f_c); + pciio_device_info_free(&pcibr_info->f_c); + DEL(pcibr_info); + } + + /* Clear the DEVIO(x) for this slot */ + slotp->bss_devio.bssd_space = PCIIO_SPACE_NONE; + slotp->bss_devio.bssd_base = PCIBR_D32_BASE_UNSET; + slotp->bss_device = 0; + + + /* Reset the mapping usage counters */ + slotp->bss_pmu_uctr = 0; + slotp->bss_d32_uctr = 0; + slotp->bss_d64_uctr = 0; + + /* Clear the Direct translation info */ + slotp->bss_d64_base = PCIBR_D64_BASE_UNSET; + slotp->bss_d64_flags = 0; + slotp->bss_d32_base = PCIBR_D32_BASE_UNSET; + slotp->bss_d32_flags = 0; + + /* Clear out shadow info necessary for the external SSRAM workaround */ + slotp->bss_ext_ates_active = 0; + slotp->bss_cmd_pointer = 0; + slotp->bss_cmd_shadow = 0; + +} + +/* + * PCI_ADDR_SPACE_LIMITS_LOAD + * Gets the current values of + * pci io base, + * pci io last, + * pci low memory base, + * pci low memory last, + * pci high memory base, + * pci high memory last + */ +#define PCI_ADDR_SPACE_LIMITS_LOAD() \ + pci_io_fb = pcibr_soft->bs_spinfo.pci_io_base; \ + pci_io_fl = pcibr_soft->bs_spinfo.pci_io_last; \ + pci_lo_fb = pcibr_soft->bs_spinfo.pci_swin_base; \ + pci_lo_fl = pcibr_soft->bs_spinfo.pci_swin_last; \ + pci_hi_fb = pcibr_soft->bs_spinfo.pci_mem_base; \ + pci_hi_fl = pcibr_soft->bs_spinfo.pci_mem_last; +/* + * PCI_ADDR_SPACE_LIMITS_STORE + * Sets the current values of + * pci io base, + * pci io last, + * pci low memory base, + * pci low memory last, + * pci high memory base, + * pci high memory last + */ +#define PCI_ADDR_SPACE_LIMITS_STORE() \ + pcibr_soft->bs_spinfo.pci_io_base = pci_io_fb; \ + pcibr_soft->bs_spinfo.pci_io_last = pci_io_fl; \ + pcibr_soft->bs_spinfo.pci_swin_base = pci_lo_fb; \ + pcibr_soft->bs_spinfo.pci_swin_last = pci_lo_fl; \ + pcibr_soft->bs_spinfo.pci_mem_base = pci_hi_fb; \ + pcibr_soft->bs_spinfo.pci_mem_last = pci_hi_fl; + +#define PCI_ADDR_SPACE_LIMITS_PRINT() \ + printf("+++++++++++++++++++++++\n" \ + "IO base 0x%x last 0x%x\n" \ + "SWIN base 0x%x last 0x%x\n" \ + "MEM base 0x%x last 0x%x\n" \ + "+++++++++++++++++++++++\n", \ + pcibr_soft->bs_spinfo.pci_io_base, \ + pcibr_soft->bs_spinfo.pci_io_last, \ + pcibr_soft->bs_spinfo.pci_swin_base, \ + pcibr_soft->bs_spinfo.pci_swin_last, \ + pcibr_soft->bs_spinfo.pci_mem_base, \ + pcibr_soft->bs_spinfo.pci_mem_last); + +/* + * pcibr_slot_reset + * Reset the pci device in the particular slot . + */ +int +pcibr_slot_reset(devfs_handle_t pcibr_vhdl,pciio_slot_t slot) +{ + pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); + bridge_t *bridge; + bridgereg_t ctrlreg,tmp; + volatile bridgereg_t *wrb_flush; + + if (!PCIBR_VALID_SLOT(slot)) + return(1); + + if (!pcibr_soft) + return(1); + + /* Enable the DMA operations from this device of the xtalk widget + * (PCI host bridge in this case). + */ + xtalk_widgetdev_enable(pcibr_soft->bs_conn, slot); + /* Set the reset slot bit in the bridge's wid control register + * to reset the pci slot + */ + bridge = pcibr_soft->bs_base; + /* Read the bridge widget control and clear out the reset pin + * bit for the corresponding slot. + */ + tmp = ctrlreg = bridge->b_wid_control; + tmp &= ~BRIDGE_CTRL_RST_PIN(slot); + bridge->b_wid_control = tmp; + tmp = bridge->b_wid_control; + /* Restore the old control register back. + * NOTE : pci card gets reset when the reset pin bit + * changes from 0 (set above) to 1 (going to be set now). + */ + bridge->b_wid_control = ctrlreg; + + /* Flush the write buffers if any !! */ + wrb_flush = &(bridge->b_wr_req_buf[slot].reg); + while (*wrb_flush); + + return(0); +} +/* + * pcibr_slot_info_init + * Probe for this slot and see if it is populated. + * If it is populated initialize the generic pci infrastructural + * information associated with this particular pci device. + */ +int +pcibr_slot_info_init(devfs_handle_t pcibr_vhdl, + pciio_slot_t slot) +{ + pcibr_soft_t pcibr_soft; + pcibr_info_h pcibr_infoh; + pcibr_info_t pcibr_info; + bridge_t *bridge; + cfg_p cfgw; + unsigned idword; + unsigned pfail; + unsigned idwords[8]; + pciio_vendor_id_t vendor; + pciio_device_id_t device; + unsigned htype; + cfg_p wptr; + int win; + pciio_space_t space; + iopaddr_t pci_io_fb, pci_io_fl; + iopaddr_t pci_lo_fb, pci_lo_fl; + iopaddr_t pci_hi_fb, pci_hi_fl; + int nfunc; + pciio_function_t rfunc; + int func; + devfs_handle_t conn_vhdl; + pcibr_soft_slot_t slotp; + + /* Get the basic software information required to proceed */ + pcibr_soft = pcibr_soft_get(pcibr_vhdl); + if (!pcibr_soft) + return(1); + + bridge = pcibr_soft->bs_base; + if (!PCIBR_VALID_SLOT(slot)) + return(1); + + slotp = &pcibr_soft->bs_slot[slot]; + + /* Load the current values of allocated pci address spaces */ + PCI_ADDR_SPACE_LIMITS_LOAD(); + + /* If we have a host slot (eg:- IOC3 has 2 pci slots and the initialization + * is done by the host slot then we are done. + */ + if (pcibr_soft->bs_slot[slot].has_host) + return(0); + + /* Try to read the device-id/vendor-id from the config space */ + cfgw = bridge->b_type0_cfg_dev[slot].l; + +#ifdef BRINGUP + if (slot < 3 || slot == 7) + return (0); + else +#endif /* BRINGUP */ + if (pcibr_probe_slot(bridge, cfgw, &idword)) + return(0); + + vendor = 0xFFFF & idword; + /* If the vendor id is not valid then the slot is not populated + * and we are done. + */ + if (vendor == 0xFFFF) + return(0); /* next slot */ + + device = 0xFFFF & (idword >> 16); + htype = do_pcibr_config_get(cfgw, PCI_CFG_HEADER_TYPE, 1); + + nfunc = 1; + rfunc = PCIIO_FUNC_NONE; + pfail = 0; + + /* NOTE: if a card claims to be multifunction + * but only responds to config space 0, treat + * it as a unifunction card. + */ + + if (htype & 0x80) { /* MULTIFUNCTION */ + for (func = 1; func < 8; ++func) { + cfgw = bridge->b_type0_cfg_dev[slot].f[func].l; + if (pcibr_probe_slot(bridge, cfgw, &idwords[func])) { + pfail |= 1 << func; + continue; + } + vendor = 0xFFFF & idwords[func]; + if (vendor == 0xFFFF) { + pfail |= 1 << func; + continue; + } + nfunc = func + 1; + rfunc = 0; + } + cfgw = bridge->b_type0_cfg_dev[slot].l; + } + NEWA(pcibr_infoh, nfunc); + + pcibr_soft->bs_slot[slot].bss_ninfo = nfunc; + pcibr_soft->bs_slot[slot].bss_infos = pcibr_infoh; + + for (func = 0; func < nfunc; ++func) { + unsigned cmd_reg; + + if (func) { + if (pfail & (1 << func)) + continue; + + idword = idwords[func]; + cfgw = bridge->b_type0_cfg_dev[slot].f[func].l; + + device = 0xFFFF & (idword >> 16); + htype = do_pcibr_config_get(cfgw, PCI_CFG_HEADER_TYPE, 1); + rfunc = func; + } + htype &= 0x7f; + if (htype != 0x00) { + PRINT_WARNING("%s pcibr: pci slot %d func %d has strange header type 0x%x\n", + pcibr_soft->bs_name, slot, func, htype); + continue; + } +#if DEBUG && ATTACH_DEBUG + PRINT_NOTICE( + "%s pcibr: pci slot %d func %d: vendor 0x%x device 0x%x", + pcibr_soft->bs_name, slot, func, vendor, device); +#endif + + pcibr_info = pcibr_device_info_new + (pcibr_soft, slot, rfunc, vendor, device); + conn_vhdl = pciio_device_info_register(pcibr_vhdl, &pcibr_info->f_c); + if (func == 0) + slotp->slot_conn = conn_vhdl; + + cmd_reg = cfgw[PCI_CFG_COMMAND / 4]; + + wptr = cfgw + PCI_CFG_BASE_ADDR_0 / 4; + + + for (win = 0; win < PCI_CFG_BASE_ADDRS; ++win) { + iopaddr_t base, mask, code; + size_t size; + + /* + * GET THE BASE & SIZE OF THIS WINDOW: + * + * The low two or four bits of the BASE register + * determines which address space we are in; the + * rest is a base address. BASE registers + * determine windows that are power-of-two sized + * and naturally aligned, so we can get the size + * of a window by writing all-ones to the + * register, reading it back, and seeing which + * bits are used for decode; the least + * significant nonzero bit is also the size of + * the window. + * + * WARNING: someone may already have allocated + * some PCI space to this window, and in fact + * PIO may be in process at this very moment + * from another processor (or even from this + * one, if we get interrupted)! So, if the BASE + * already has a nonzero address, be generous + * and use the LSBit of that address as the + * size; this could overstate the window size. + * Usually, when one card is set up, all are set + * up; so, since we don't bitch about + * overlapping windows, we are ok. + * + * UNFORTUNATELY, some cards do not clear their + * BASE registers on reset. I have two heuristics + * that can detect such cards: first, if the + * decode enable is turned off for the space + * that the window uses, we can disregard the + * initial value. second, if the address is + * outside the range that we use, we can disregard + * it as well. + * + * This is looking very PCI generic. Except for + * knowing how many slots and where their config + * spaces are, this window loop and the next one + * could probably be shared with other PCI host + * adapters. It would be interesting to see if + * this could be pushed up into pciio, when we + * start supporting more PCI providers. + */ +#ifdef LITTLE_ENDIAN + base = wptr[((win*4)^4)/4]; +#else + base = wptr[win]; +#endif /* LITTLE_ENDIAN */ + + if (base & 1) { + /* BASE is in I/O space. */ + space = PCIIO_SPACE_IO; + mask = -4; + code = base & 3; + base = base & mask; + if (base == 0) { + ; /* not assigned */ + } else if (!(cmd_reg & PCI_CMD_IO_SPACE)) { + base = 0; /* decode not enabled */ + } + } else { + /* BASE is in MEM space. */ + space = PCIIO_SPACE_MEM; + mask = -16; + code = base & 15; + base = base & mask; + if (base == 0) { + ; /* not assigned */ + } else if (!(cmd_reg & PCI_CMD_MEM_SPACE)) { + base = 0; /* decode not enabled */ + } else if (base & 0xC0000000) { + base = 0; /* outside permissable range */ + } else if ((code == PCI_BA_MEM_64BIT) && +#ifdef LITTLE_ENDIAN + (wptr[(((win + 1)*4)^4)/4] != 0)) { +#else + (wptr[win + 1] != 0)) { +#endif /* LITTLE_ENDIAN */ + base = 0; /* outside permissable range */ + } + } + + if (base != 0) { /* estimate size */ + size = base & -base; + } else { /* calculate size */ +#ifdef LITTLE_ENDIAN + wptr[((win*4)^4)/4] = ~0; /* turn on all bits */ + size = wptr[((win*4)^4)/4]; /* get stored bits */ +#else + wptr[win] = ~0; /* turn on all bits */ + size = wptr[win]; /* get stored bits */ +#endif /* LITTLE_ENDIAN */ + size &= mask; /* keep addr */ + size &= -size; /* keep lsbit */ + if (size == 0) + continue; + } + + pcibr_info->f_window[win].w_space = space; + pcibr_info->f_window[win].w_base = base; + pcibr_info->f_window[win].w_size = size; + + /* + * If this window already has PCI space + * allocated for it, "subtract" that space from + * our running freeblocks. Don't worry about + * overlaps in existing allocated windows; we + * may be overstating their sizes anyway. + */ + + if (base && size) { + if (space == PCIIO_SPACE_IO) { + pcibr_freeblock_sub(&pci_io_fb, + &pci_io_fl, + base, size); + } else { + pcibr_freeblock_sub(&pci_lo_fb, + &pci_lo_fl, + base, size); + pcibr_freeblock_sub(&pci_hi_fb, + &pci_hi_fl, + base, size); + } + } +#if defined(IOC3_VENDOR_ID_NUM) && defined(IOC3_DEVICE_ID_NUM) + /* + * IOC3 BASE_ADDR* BUG WORKAROUND + * + + * If we write to BASE1 on the IOC3, the + * data in BASE0 is replaced. The + * original workaround was to remember + * the value of BASE0 and restore it + * when we ran off the end of the BASE + * registers; however, a later + * workaround was added (I think it was + * rev 1.44) to avoid setting up + * anything but BASE0, with the comment + * that writing all ones to BASE1 set + * the enable-parity-error test feature + * in IOC3's SCR bit 14. + * + * So, unless we defer doing any PCI + * space allocation until drivers + * attach, and set up a way for drivers + * (the IOC3 in paricular) to tell us + * generically to keep our hands off + * BASE registers, we gotta "know" about + * the IOC3 here. + * + * Too bad the PCI folks didn't reserve the + * all-zero value for 'no BASE here' (it is a + * valid code for an uninitialized BASE in + * 32-bit PCI memory space). + */ + + if ((vendor == IOC3_VENDOR_ID_NUM) && + (device == IOC3_DEVICE_ID_NUM)) + break; +#endif + if (code == PCI_BA_MEM_64BIT) { + win++; /* skip upper half */ +#ifdef LITTLE_ENDIAN + wptr[((win*4)^4)/4] = 0; /* which must be zero */ +#else + wptr[win] = 0; /* which must be zero */ +#endif /* LITTLE_ENDIAN */ + } + } /* next win */ + } /* next func */ + + /* Store back the values for allocated pci address spaces */ + PCI_ADDR_SPACE_LIMITS_STORE(); + return(0); +} + +/* + * pcibr_slot_info_free + * Remove all the pci infrastructural information associated + * with a particular pci device. + */ +int +pcibr_slot_info_free(devfs_handle_t pcibr_vhdl, + pciio_slot_t slot) +{ + pcibr_soft_t pcibr_soft; + pcibr_info_h pcibr_infoh; + int nfunc; +#if defined(PCI_HOTSWAP_DEBUG) + cfg_p cfgw; + bridge_t *bridge; + int win; + cfg_p wptr; +#endif /* PCI_HOTSWAP_DEBUG */ + + + + pcibr_soft = pcibr_soft_get(pcibr_vhdl); + if (!pcibr_soft || !PCIBR_VALID_SLOT(slot)) + return(1); + +#if defined(PCI_HOTSWAP_DEBUG) + /* Clean out all the base registers */ + bridge = pcibr_soft->bs_base; + cfgw = bridge->b_type0_cfg_dev[slot].l; + wptr = cfgw + PCI_CFG_BASE_ADDR_0 / 4; + + for (win = 0; win < PCI_CFG_BASE_ADDRS; ++win) +#ifdef LITTLE_ENDIAN + wptr[((win*4)^4)/4] = 0; +#else + wptr[win] = 0; +#endif /* LITTLE_ENDIAN */ +#endif /* PCI_HOTSWAP_DEBUG */ + + nfunc = pcibr_soft->bs_slot[slot].bss_ninfo; + + pcibr_device_info_free(pcibr_vhdl, slot); + + pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos; + DELA(pcibr_infoh,nfunc); + pcibr_soft->bs_slot[slot].bss_ninfo = 0; + + return(0); + + +} +int as_debug = 0; +/* + * pcibr_slot_addr_space_init + * Reserve chunks of pci address space as required by + * the base registers in the card. + */ +int +pcibr_slot_addr_space_init(devfs_handle_t pcibr_vhdl, + pciio_slot_t slot) +{ + pcibr_soft_t pcibr_soft; + pcibr_info_h pcibr_infoh; + pcibr_info_t pcibr_info; + bridge_t *bridge; + iopaddr_t pci_io_fb, pci_io_fl; + iopaddr_t pci_lo_fb, pci_lo_fl; + iopaddr_t pci_hi_fb, pci_hi_fl; + size_t align; + iopaddr_t mask; + int nfunc; + int func; + int win; + + pcibr_soft = pcibr_soft_get(pcibr_vhdl); + if (!pcibr_soft || !PCIBR_VALID_SLOT(slot)) + return(1); + + bridge = pcibr_soft->bs_base; + + /* Get the current values for the allocated pci address spaces */ + PCI_ADDR_SPACE_LIMITS_LOAD(); + + if (as_debug) +#ifdef colin + PCI_ADDR_SPACE_LIMITS_PRINT(); +#endif + /* allocate address space, + * for windows that have not been + * previously assigned. + */ + + if (pcibr_soft->bs_slot[slot].has_host) + return(0); + + nfunc = pcibr_soft->bs_slot[slot].bss_ninfo; + if (nfunc < 1) + return(0); + + pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos; + if (!pcibr_infoh) + return(0); + + /* + * Try to make the DevIO windows not + * overlap by pushing the "io" and "hi" + * allocation areas up to the next one + * or two megabyte bound. This also + * keeps them from being zero. + * + * DO NOT do this with "pci_lo" since + * the entire "lo" area is only a + * megabyte, total ... + */ + align = (slot < 2) ? 0x200000 : 0x100000; + mask = -align; + pci_io_fb = (pci_io_fb + align - 1) & mask; + pci_hi_fb = (pci_hi_fb + align - 1) & mask; + + for (func = 0; func < nfunc; ++func) { + cfg_p cfgw; + cfg_p wptr; + pciio_space_t space; + iopaddr_t base; + size_t size; + cfg_p pci_cfg_cmd_reg_p; + unsigned pci_cfg_cmd_reg; + unsigned pci_cfg_cmd_reg_add = 0; + + pcibr_info = pcibr_infoh[func]; + + if (!pcibr_info) + continue; + + if (pcibr_info->f_vendor == PCIIO_VENDOR_ID_NONE) + continue; + + cfgw = bridge->b_type0_cfg_dev[slot].f[func].l; + wptr = cfgw + PCI_CFG_BASE_ADDR_0 / 4; + + for (win = 0; win < PCI_CFG_BASE_ADDRS; ++win) { + + space = pcibr_info->f_window[win].w_space; + base = pcibr_info->f_window[win].w_base; + size = pcibr_info->f_window[win].w_size; + + if (size < 1) + continue; + + if (base >= size) { +#if DEBUG && PCI_DEBUG + printk("pcibr: slot %d func %d window %d is in %d[0x%x..0x%x], alloc by prom\n", + slot, func, win, space, base, base + size - 1); +#endif + continue; /* already allocated */ + } + align = size; /* ie. 0x00001000 */ + if (align < _PAGESZ) + align = _PAGESZ; /* ie. 0x00004000 */ + mask = -align; /* ie. 0xFFFFC000 */ + + switch (space) { + case PCIIO_SPACE_IO: + base = (pci_io_fb + align - 1) & mask; + if ((base + size) > pci_io_fl) { + base = 0; + break; + } + pci_io_fb = base + size; + break; + + case PCIIO_SPACE_MEM: +#ifdef LITTLE_ENDIAN + if ((wptr[((win*4)^4)/4] & PCI_BA_MEM_LOCATION) == +#else + if ((wptr[win] & PCI_BA_MEM_LOCATION) == +#endif /* LITTLE_ENDIAN */ + PCI_BA_MEM_1MEG) { + /* allocate from 20-bit PCI space */ + base = (pci_lo_fb + align - 1) & mask; + if ((base + size) > pci_lo_fl) { + base = 0; + break; + } + pci_lo_fb = base + size; + } else { + /* allocate from 32-bit or 64-bit PCI space */ + base = (pci_hi_fb + align - 1) & mask; + if ((base + size) > pci_hi_fl) { + base = 0; + break; + } + pci_hi_fb = base + size; + } + break; + + default: + base = 0; +#if DEBUG && PCI_DEBUG + printk("pcibr: slot %d window %d had bad space code %d\n", + slot, win, space); +#endif + } + pcibr_info->f_window[win].w_base = base; +#ifdef LITTLE_ENDIAN + wptr[((win*4)^4)/4] = base; + printk("Setting base address 0x%p base 0x%x\n", &(wptr[((win*4)^4)/4]), base); +#else + wptr[win] = base; +#endif /* LITTLE_ENDIAN */ + +#if DEBUG && PCI_DEBUG + if (base >= size) + printk("pcibr: slot %d func %d window %d is in %d [0x%x..0x%x], alloc by pcibr\n", + slot, func, win, space, base, base + size - 1); + else + printk("pcibr: slot %d func %d window %d, unable to alloc 0x%x in 0x%p\n", + slot, func, win, size, space); +#endif + } /* next base */ + + /* + * Allocate space for the EXPANSION ROM + * NOTE: DO NOT DO THIS ON AN IOC3, + * as it blows the system away. + */ + base = size = 0; + if ((pcibr_soft->bs_slot[slot].bss_vendor_id != IOC3_VENDOR_ID_NUM) || + (pcibr_soft->bs_slot[slot].bss_device_id != IOC3_DEVICE_ID_NUM)) { + + wptr = cfgw + PCI_EXPANSION_ROM / 4; +#ifdef LITTLE_ENDIAN + wptr[1] = 0xFFFFF000; + mask = wptr[1]; +#else + *wptr = 0xFFFFF000; + mask = *wptr; +#endif /* LITTLE_ENDIAN */ + if (mask & 0xFFFFF000) { + size = mask & -mask; + align = size; + if (align < _PAGESZ) + align = _PAGESZ; + mask = -align; + base = (pci_hi_fb + align - 1) & mask; + if ((base + size) > pci_hi_fl) + base = size = 0; + else { + pci_hi_fb = base + size; +#ifdef LITTLE_ENDIAN + wptr[1] = base; +#else + *wptr = base; +#endif /* LITTLE_ENDIAN */ +#if DEBUG && PCI_DEBUG + printk("%s/%d ROM in 0x%lx..0x%lx (alloc by pcibr)\n", + pcibr_soft->bs_name, slot, + base, base + size - 1); +#endif + } + } + } + pcibr_info->f_rbase = base; + pcibr_info->f_rsize = size; + + /* + * if necessary, update the board's + * command register to enable decoding + * in the windows we added. + * + * There are some bits we always want to + * be sure are set. + */ + pci_cfg_cmd_reg_add |= PCI_CMD_IO_SPACE; + pci_cfg_cmd_reg_add |= PCI_CMD_MEM_SPACE; + pci_cfg_cmd_reg_add |= PCI_CMD_BUS_MASTER; + + pci_cfg_cmd_reg_p = cfgw + PCI_CFG_COMMAND / 4; + pci_cfg_cmd_reg = *pci_cfg_cmd_reg_p; +#if PCI_FBBE /* XXX- check here to see if dev can do fast-back-to-back */ + if (!((pci_cfg_cmd_reg >> 16) & PCI_STAT_F_BK_BK_CAP)) + fast_back_to_back_enable = 0; +#endif + pci_cfg_cmd_reg &= 0xFFFF; + if (pci_cfg_cmd_reg_add & ~pci_cfg_cmd_reg) + *pci_cfg_cmd_reg_p = pci_cfg_cmd_reg | pci_cfg_cmd_reg_add; + + } /* next func */ + + /* Now that we have allocated new chunks of pci address spaces to this + * card we need to update the bookkeeping values which indicate + * the current pci address space allocations. + */ + PCI_ADDR_SPACE_LIMITS_STORE(); + return(0); +} +/* + * pcibr_slot_device_init + * Setup the device register in the bridge for this pci slot. + */ +int +pcibr_slot_device_init(devfs_handle_t pcibr_vhdl, + pciio_slot_t slot) +{ + pcibr_soft_t pcibr_soft; + bridge_t *bridge; + bridgereg_t devreg; + + pcibr_soft = pcibr_soft_get(pcibr_vhdl); + if (!pcibr_soft || !PCIBR_VALID_SLOT(slot)) + return(1); + + bridge = pcibr_soft->bs_base; + + /* + * Adjustments to Device(x) + * and init of bss_device shadow + */ + devreg = bridge->b_device[slot].reg; + devreg &= ~BRIDGE_DEV_PAGE_CHK_DIS; + devreg |= BRIDGE_DEV_COH | BRIDGE_DEV_VIRTUAL_EN; +#ifdef LITTLE_ENDIAN + devreg |= BRIDGE_DEV_DEV_SWAP; +#endif + pcibr_soft->bs_slot[slot].bss_device = devreg; + bridge->b_device[slot].reg = devreg; + +#if DEBUG && PCI_DEBUG + printk("pcibr Device(%d): 0x%lx\n", slot, bridge->b_device[slot].reg); +#endif + +#if DEBUG && PCI_DEBUG + printk("pcibr: PCI space allocation done.\n"); +#endif + + return(0); +} + +/* + * pcibr_slot_guest_info_init + * Setup the host/guest relations for a pci slot. + */ +int +pcibr_slot_guest_info_init(devfs_handle_t pcibr_vhdl, + pciio_slot_t slot) +{ + pcibr_soft_t pcibr_soft; + pcibr_info_h pcibr_infoh; + pcibr_info_t pcibr_info; + pcibr_soft_slot_t slotp; + + pcibr_soft = pcibr_soft_get(pcibr_vhdl); + + if (!pcibr_soft || !PCIBR_VALID_SLOT(slot)) + return(1); + + slotp = &pcibr_soft->bs_slot[slot]; + + /* create info and verticies for guest slots; + * for compatibilitiy macros, create info + * for even unpopulated slots (but do not + * build verticies for them). + */ + if (pcibr_soft->bs_slot[slot].bss_ninfo < 1) { + NEWA(pcibr_infoh, 1); + pcibr_soft->bs_slot[slot].bss_ninfo = 1; + pcibr_soft->bs_slot[slot].bss_infos = pcibr_infoh; + + pcibr_info = pcibr_device_info_new + (pcibr_soft, slot, PCIIO_FUNC_NONE, + PCIIO_VENDOR_ID_NONE, PCIIO_DEVICE_ID_NONE); + + if (pcibr_soft->bs_slot[slot].has_host) { + slotp->slot_conn = pciio_device_info_register + (pcibr_vhdl, &pcibr_info->f_c); + } + } + + /* generate host/guest relations + */ + if (pcibr_soft->bs_slot[slot].has_host) { + int host = pcibr_soft->bs_slot[slot].host_slot; + pcibr_soft_slot_t host_slotp = &pcibr_soft->bs_slot[host]; + + hwgraph_edge_add(slotp->slot_conn, + host_slotp->slot_conn, + EDGE_LBL_HOST); + + /* XXX- only gives us one guest edge per + * host. If/when we have a host with more than + * one guest, we will need to figure out how + * the host finds all its guests, and sorts + * out which one is which. + */ + hwgraph_edge_add(host_slotp->slot_conn, + slotp->slot_conn, + EDGE_LBL_GUEST); + } + + return(0); +} +/* + * pcibr_slot_initial_rrb_alloc + * Allocate a default number of rrbs for this slot on + * the two channels. This is dictated by the rrb allocation + * strategy routine defined per platform. + */ + +int +pcibr_slot_initial_rrb_alloc(devfs_handle_t pcibr_vhdl, + pciio_slot_t slot) + +{ + pcibr_soft_t pcibr_soft; + pcibr_info_h pcibr_infoh; + pcibr_info_t pcibr_info; + bridge_t *bridge; + int c0, c1; + int r; + + pcibr_soft = pcibr_soft_get(pcibr_vhdl); + if (!pcibr_soft || !PCIBR_VALID_SLOT(slot)) + return(1); + + bridge = pcibr_soft->bs_base; + + + /* How may RRBs are on this slot? + */ + c0 = do_pcibr_rrb_count_valid(bridge, slot); + c1 = do_pcibr_rrb_count_valid(bridge, slot + PCIBR_RRB_SLOT_VIRTUAL); +#if PCIBR_RRB_DEBUG + printk("pcibr_attach: slot %d started with %d+%d\n", slot, c0, c1); +#endif + + /* Do we really need any? + */ + pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos; + pcibr_info = pcibr_infoh[0]; + if ((pcibr_info->f_vendor == PCIIO_VENDOR_ID_NONE) && + !pcibr_soft->bs_slot[slot].has_host) { + if (c0 > 0) + do_pcibr_rrb_free(bridge, slot, c0); + if (c1 > 0) + do_pcibr_rrb_free(bridge, slot + PCIBR_RRB_SLOT_VIRTUAL, c1); + pcibr_soft->bs_rrb_valid[slot] = 0x1000; + pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL] = 0x1000; + return(0); + } + + pcibr_soft->bs_rrb_avail[slot & 1] -= c0 + c1; + pcibr_soft->bs_rrb_valid[slot] = c0; + pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL] = c1; + + pcibr_soft->bs_rrb_avail[0] = do_pcibr_rrb_count_avail(bridge, 0); + pcibr_soft->bs_rrb_avail[1] = do_pcibr_rrb_count_avail(bridge, 1); + + r = 3 - (c0 + c1); + + if (r > 0) { + pcibr_soft->bs_rrb_res[slot] = r; + pcibr_soft->bs_rrb_avail[slot & 1] -= r; + } + +#if PCIBR_RRB_DEBUG + printk("\t%d+%d+%d", + 0xFFF & pcibr_soft->bs_rrb_valid[slot], + 0xFFF & pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL], + pcibr_soft->bs_rrb_res[slot]); + printk("\n"); +#endif + return(0); +} + +/* + * pcibr_slot_call_device_attach + * This calls the associated driver attach routine for the pci + * card in this slot. + */ +int +pcibr_slot_call_device_attach(devfs_handle_t pcibr_vhdl, + pciio_slot_t slot) +{ + pcibr_soft_t pcibr_soft; + pcibr_info_h pcibr_infoh; + pcibr_info_t pcibr_info; + async_attach_t aa = NULL; + int func; + devfs_handle_t xconn_vhdl,conn_vhdl; + int nfunc; + + pcibr_soft = pcibr_soft_get(pcibr_vhdl); + if (!pcibr_soft || !PCIBR_VALID_SLOT(slot)) + return(1); + + + if (pcibr_soft->bs_slot[slot].has_host) + return(0); + + xconn_vhdl = pcibr_soft->bs_conn; + aa = async_attach_get_info(xconn_vhdl); + + nfunc = pcibr_soft->bs_slot[slot].bss_ninfo; + pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos; + + printk("\npcibr_slot_call_device_attach: link 0x%p pci bus 0x%p slot %d\n", xconn_vhdl, pcibr_vhdl, slot); + + for (func = 0; func < nfunc; ++func) { + + pcibr_info = pcibr_infoh[func]; + + if (!pcibr_info) + continue; + + if (pcibr_info->f_vendor == PCIIO_VENDOR_ID_NONE) + continue; + + conn_vhdl = pcibr_info->f_vertex; + + /* If the pci device has been disabled in the prom, + * do not set it up for driver attach. NOTE: usrpci + * and pciba will not "see" this connection point! + */ + if (device_admin_info_get(conn_vhdl, ADMIN_LBL_DISABLED)) { +#ifdef SUPPORT_PRINTING_V_FORMAT + PRINT_WARNING( "pcibr_slot_call_device_attach: %v disabled\n", + conn_vhdl); +#endif + continue; + } + if (aa) + async_attach_add_info(conn_vhdl, aa); + pciio_device_attach(conn_vhdl); + } /* next func */ + + printk("\npcibr_slot_call_device_attach: DONE\n"); + + return(0); +} +/* + * pcibr_slot_call_device_detach + * This calls the associated driver detach routine for the pci + * card in this slot. + */ +int +pcibr_slot_call_device_detach(devfs_handle_t pcibr_vhdl, + pciio_slot_t slot) +{ + pcibr_soft_t pcibr_soft; + pcibr_info_h pcibr_infoh; + pcibr_info_t pcibr_info; + int func; + devfs_handle_t conn_vhdl; + int nfunc; + int ndetach = 1; + + pcibr_soft = pcibr_soft_get(pcibr_vhdl); + if (!pcibr_soft || !PCIBR_VALID_SLOT(slot)) + return(1); + + + if (pcibr_soft->bs_slot[slot].has_host) + return(0); + + + nfunc = pcibr_soft->bs_slot[slot].bss_ninfo; + pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos; + + for (func = 0; func < nfunc; ++func) { + + pcibr_info = pcibr_infoh[func]; + + if (!pcibr_info) + continue; + + if (pcibr_info->f_vendor == PCIIO_VENDOR_ID_NONE) + continue; + + conn_vhdl = pcibr_info->f_vertex; + + /* Make sure that we do not detach a system critical device + * vertex. + */ + if (is_sys_critical_vertex(conn_vhdl)) { +#ifdef SUPPORT_PRINTING_V_FORMAT + PRINT_WARNING( "%v is a system critical device vertex\n", + conn_vhdl); +#endif + continue; + } + + ndetach = 0; + pciio_device_detach(conn_vhdl); + } /* next func */ + + + return(ndetach); +} + +/* + * pcibr_device_attach + * This is a place holder routine to keep track of all the + * slot-specific initialization that needs to be done. + * This is usually called when we want to initialize a new + * pci card on the bus. + */ +int +pcibr_device_attach(devfs_handle_t pcibr_vhdl, + pciio_slot_t slot) +{ + return ( + /* Reset the slot */ + pcibr_slot_reset(pcibr_vhdl,slot) || + /* FInd out what is out there */ + pcibr_slot_info_init(pcibr_vhdl,slot) || + + /* Set up the address space for this slot in the pci land */ + pcibr_slot_addr_space_init(pcibr_vhdl,slot) || + + /* Setup the device register */ + pcibr_slot_device_init(pcibr_vhdl, slot) || + + /* Setup host/guest relations */ + pcibr_slot_guest_info_init(pcibr_vhdl,slot) || + + /* Initial RRB management */ + pcibr_slot_initial_rrb_alloc(pcibr_vhdl,slot) || + + /* Call the device attach */ + pcibr_slot_call_device_attach(pcibr_vhdl,slot) + ); + +} +/* + * pcibr_device_detach + * This is a place holder routine to keep track of all the + * slot-specific freeing that needs to be done. + */ +int +pcibr_device_detach(devfs_handle_t pcibr_vhdl, + pciio_slot_t slot) +{ + + /* Call the device detach */ + return (pcibr_slot_call_device_detach(pcibr_vhdl,slot)); + +} +/* + * pcibr_device_unregister + * This frees up any hardware resources reserved for this pci device + * and removes any pci infrastructural information setup for it. + * This is usually used at the time of shutting down of the pci card. + */ +void +pcibr_device_unregister(devfs_handle_t pconn_vhdl) +{ + pciio_info_t pciio_info; + devfs_handle_t pcibr_vhdl; + pciio_slot_t slot; + pcibr_soft_t pcibr_soft; + bridge_t *bridge; + + pciio_info = pciio_info_get(pconn_vhdl); + + /* Detach the pciba name space */ + pciio_device_detach(pconn_vhdl); + + pcibr_vhdl = pciio_info_master_get(pciio_info); + slot = pciio_info_slot_get(pciio_info); + + pcibr_soft = pcibr_soft_get(pcibr_vhdl); + bridge = pcibr_soft->bs_base; + + /* Clear all the hardware xtalk resources for this device */ + xtalk_widgetdev_shutdown(pcibr_soft->bs_conn, slot); + + /* Flush all the rrbs */ + pcibr_rrb_flush(pconn_vhdl); + + /* Free the rrbs allocated to this slot */ + do_pcibr_rrb_free(bridge, slot, + pcibr_soft->bs_rrb_valid[slot] + + pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL]); + + + pcibr_soft->bs_rrb_valid[slot] = 0; + pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL] = 0; + pcibr_soft->bs_rrb_res[slot] = 0; + + /* Flush the write buffers !! */ + (void)pcibr_wrb_flush(pconn_vhdl); + /* Clear the information specific to the slot */ + (void)pcibr_slot_info_free(pcibr_vhdl, slot); + +} + +/* + * build a convenience link path in the + * form of "...//bus/" + * + * returns 1 on success, 0 otherwise + * + * depends on hwgraph separator == '/' + */ +int +pcibr_bus_cnvlink(devfs_handle_t f_c, int slot) +{ + char dst[MAXDEVNAME]; + char *dp = dst; + char *cp, *xp; + int widgetnum; + char pcibus[8]; + devfs_handle_t nvtx, svtx; + int rv; + +#if DEBUG + printk("pcibr_bus_cnvlink: slot= %d f_c= %p\n", + slot, f_c); + { + int pos; + char dname[256]; + pos = devfs_generate_path(f_c, dname, 256); + printk("%s : path= %s\n", __FUNCTION__, &dname[pos]); + } +#endif + + if (GRAPH_SUCCESS != hwgraph_vertex_name_get(f_c, dst, MAXDEVNAME)) + return 0; + + /* dst example == /hw/module/001c02/Pbrick/xtalk/8/pci/direct */ + + /* find the widget number */ + xp = strstr(dst, "/"EDGE_LBL_XTALK"/"); + if (xp == NULL) + return 0; + widgetnum = atoi(xp+7); + if (widgetnum < XBOW_PORT_8 || widgetnum > XBOW_PORT_F) + return 0; + + /* remove "/pci/direct" from path */ + cp = strstr(dst, "/" EDGE_LBL_PCI "/" "direct"); + if (cp == NULL) + return 0; + *cp = (char)NULL; + + /* get the vertex for the widget */ + if (GRAPH_SUCCESS != hwgraph_traverse(NULL, dp, &svtx)) + return 0; + + *xp = (char)NULL; /* remove "/xtalk/..." from path */ + + /* dst example now == /hw/module/001c02/Pbrick */ + + /* get the bus number */ + strcat(dst, "/bus"); + sprintf(pcibus, "%d", p_busnum[widgetnum]); + + /* link to bus to widget */ + rv = hwgraph_path_add(NULL, dp, &nvtx); + if (GRAPH_SUCCESS == rv) + rv = hwgraph_edge_add(nvtx, svtx, pcibus); + + return (rv == GRAPH_SUCCESS); +} + +/* + * pcibr_attach: called every time the crosstalk + * infrastructure is asked to initialize a widget + * that matches the part number we handed to the + * registration routine above. + */ +/*ARGSUSED */ +int +pcibr_attach(devfs_handle_t xconn_vhdl) +{ + /* REFERENCED */ + graph_error_t rc; + devfs_handle_t pcibr_vhdl; + devfs_handle_t ctlr_vhdl; + bridge_t *bridge = NULL; + bridgereg_t id; + int rev; + pcibr_soft_t pcibr_soft; + pcibr_info_t pcibr_info; + xwidget_info_t info; + xtalk_intr_t xtalk_intr; + device_desc_t dev_desc; + int slot; + int ibit; + devfs_handle_t noslot_conn; + char devnm[MAXDEVNAME], *s; + pcibr_hints_t pcibr_hints; + bridgereg_t b_int_enable; + unsigned rrb_fixed = 0; + + iopaddr_t pci_io_fb, pci_io_fl; + iopaddr_t pci_lo_fb, pci_lo_fl; + iopaddr_t pci_hi_fb, pci_hi_fl; + + int spl_level; + char *nicinfo = (char *)0; + +#if PCI_FBBE + int fast_back_to_back_enable; +#endif + + async_attach_t aa = NULL; + + aa = async_attach_get_info(xconn_vhdl); + +#if DEBUG && ATTACH_DEBUG + printk("pcibr_attach: xconn_vhdl= %p\n", xconn_vhdl); + { + int pos; + char dname[256]; + pos = devfs_generate_path(xconn_vhdl, dname, 256); + printk("%s : path= %s \n", __FUNCTION__, &dname[pos]); + } +#endif + + /* Setup the PRB for the bridge in CONVEYOR BELT + * mode. PRBs are setup in default FIRE-AND-FORGET + * mode during the initialization. + */ + hub_device_flags_set(xconn_vhdl, HUB_PIO_CONVEYOR); + + bridge = (bridge_t *) + xtalk_piotrans_addr(xconn_vhdl, NULL, + 0, sizeof(bridge_t), 0); + +#ifndef MEDUSA_HACK + if ((bridge->b_wid_stat & BRIDGE_STAT_PCI_GIO_N) == 0) + return -1; /* someone else handles GIO bridges. */ +#endif + +#ifdef BRINGUP + if (XWIDGET_PART_REV_NUM(bridge->b_wid_id) == XBRIDGE_PART_REV_A) + NeedXbridgeSwap = 1; +#endif + + printk("pcibr_attach: Called with vertex 0x%p, b_wid_stat 0x%x, gio 0x%x\n",xconn_vhdl, bridge->b_wid_stat, BRIDGE_STAT_PCI_GIO_N); + + /* + * Create the vertex for the PCI bus, which we + * will also use to hold the pcibr_soft and + * which will be the "master" vertex for all the + * pciio connection points we will hang off it. + * This needs to happen before we call nic_bridge_vertex_info + * as we are some of the *_vmc functions need access to the edges. + * + * Opening this vertex will provide access to + * the Bridge registers themselves. + */ + rc = hwgraph_path_add(xconn_vhdl, EDGE_LBL_PCI, &pcibr_vhdl); + ASSERT(rc == GRAPH_SUCCESS); + + rc = hwgraph_char_device_add(pcibr_vhdl, EDGE_LBL_CONTROLLER, "pcibr_", &ctlr_vhdl); + ASSERT(rc == GRAPH_SUCCESS); + + /* + * decode the nic, and hang its stuff off our + * connection point where other drivers can get + * at it. + */ +#ifdef LATER + nicinfo = BRIDGE_VERTEX_MFG_INFO(xconn_vhdl, (nic_data_t) & bridge->b_nic); +#endif + + /* + * Get the hint structure; if some NIC callback + * marked this vertex as "hands-off" then we + * just return here, before doing anything else. + */ + pcibr_hints = pcibr_hints_get(xconn_vhdl, 0); + + if (pcibr_hints && pcibr_hints->ph_hands_off) + return -1; /* generic operations disabled */ + + id = bridge->b_wid_id; + rev = XWIDGET_PART_REV_NUM(id); + + hwgraph_info_add_LBL(pcibr_vhdl, INFO_LBL_PCIBR_ASIC_REV, (arbitrary_info_t) rev); + + /* + * allocate soft state structure, fill in some + * fields, and hook it up to our vertex. + */ + NEW(pcibr_soft); + BZERO(pcibr_soft, sizeof *pcibr_soft); + pcibr_soft_set(pcibr_vhdl, pcibr_soft); + + pcibr_soft->bs_conn = xconn_vhdl; + pcibr_soft->bs_vhdl = pcibr_vhdl; + pcibr_soft->bs_base = bridge; + pcibr_soft->bs_rev_num = rev; + pcibr_soft->bs_intr_bits = pcibr_intr_bits; + if (is_xbridge(bridge)) { + pcibr_soft->bs_int_ate_size = XBRIDGE_INTERNAL_ATES; + pcibr_soft->bs_xbridge = 1; + } else { + pcibr_soft->bs_int_ate_size = BRIDGE_INTERNAL_ATES; + pcibr_soft->bs_xbridge = 0; + } + + pcibr_soft->bsi_err_intr = 0; + + /* Bridges up through REV C + * are unable to set the direct + * byteswappers to BYTE_STREAM. + */ + if (pcibr_soft->bs_rev_num <= BRIDGE_PART_REV_C) { + pcibr_soft->bs_pio_end_io = PCIIO_WORD_VALUES; + pcibr_soft->bs_pio_end_mem = PCIIO_WORD_VALUES; + } +#if PCIBR_SOFT_LIST + { + pcibr_list_p self; + + NEW(self); + self->bl_soft = pcibr_soft; + self->bl_vhdl = pcibr_vhdl; + self->bl_next = pcibr_list; + self->bl_next = swap_ptr((void **) &pcibr_list, (void *)self); + } +#endif + + /* + * get the name of this bridge vertex and keep the info. Use this + * only where it is really needed now: like error interrupts. + */ + s = dev_to_name(pcibr_vhdl, devnm, MAXDEVNAME); + pcibr_soft->bs_name = kmalloc(strlen(s) + 1, GFP_KERNEL); + strcpy(pcibr_soft->bs_name, s); + +#if SHOW_REVS || DEBUG +#if !DEBUG + if (kdebug) +#endif + printk("%sBridge ASIC: rev %s (code=0x%x) at %s\n", + is_xbridge(bridge) ? "X" : "", + (rev == BRIDGE_PART_REV_A) ? "A" : + (rev == BRIDGE_PART_REV_B) ? "B" : + (rev == BRIDGE_PART_REV_C) ? "C" : + (rev == BRIDGE_PART_REV_D) ? "D" : + (rev == XBRIDGE_PART_REV_A) ? "A" : + (rev == XBRIDGE_PART_REV_B) ? "B" : + "unknown", + rev, pcibr_soft->bs_name); +#endif + + info = xwidget_info_get(xconn_vhdl); + pcibr_soft->bs_xid = xwidget_info_id_get(info); + pcibr_soft->bs_master = xwidget_info_master_get(info); + pcibr_soft->bs_mxid = xwidget_info_masterid_get(info); + + /* + * Init bridge lock. + */ + spinlock_init(&pcibr_soft->bs_lock, "pcibr_loc"); + + /* + * If we have one, process the hints structure. + */ + if (pcibr_hints) { + rrb_fixed = pcibr_hints->ph_rrb_fixed; + + pcibr_soft->bs_rrb_fixed = rrb_fixed; + + if (pcibr_hints->ph_intr_bits) + pcibr_soft->bs_intr_bits = pcibr_hints->ph_intr_bits; + + for (slot = 0; slot < 8; ++slot) { + int hslot = pcibr_hints->ph_host_slot[slot] - 1; + + if (hslot < 0) { + pcibr_soft->bs_slot[slot].host_slot = slot; + } else { + pcibr_soft->bs_slot[slot].has_host = 1; + pcibr_soft->bs_slot[slot].host_slot = hslot; + } + } + } + /* + * set up initial values for state fields + */ + for (slot = 0; slot < 8; ++slot) { + pcibr_soft->bs_slot[slot].bss_devio.bssd_space = PCIIO_SPACE_NONE; + pcibr_soft->bs_slot[slot].bss_d64_base = PCIBR_D64_BASE_UNSET; + pcibr_soft->bs_slot[slot].bss_d32_base = PCIBR_D32_BASE_UNSET; + pcibr_soft->bs_slot[slot].bss_ext_ates_active = 0; + } + + for (ibit = 0; ibit < 8; ++ibit) { + pcibr_soft->bs_intr[ibit].bsi_xtalk_intr = 0; + pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_list = 0; + } + + /* + * connect up our error handler + */ + xwidget_error_register(xconn_vhdl, pcibr_error_handler, pcibr_soft); + + /* + * Initialize various Bridge registers. + */ + + /* + * On pre-Rev.D bridges, set the PCI_RETRY_CNT + * to zero to avoid dropping stores. (#475347) + */ + if (rev < BRIDGE_PART_REV_D) + bridge->b_bus_timeout &= ~BRIDGE_BUS_PCI_RETRY_MASK; + + /* + * Clear all pending interrupts. + */ + bridge->b_int_rst_stat = (BRIDGE_IRR_ALL_CLR); + + /* + * Until otherwise set up, + * assume all interrupts are + * from slot 7. + */ + bridge->b_int_device = (uint32_t) 0xffffffff; + + { + bridgereg_t dirmap; + paddr_t paddr; + iopaddr_t xbase; + xwidgetnum_t xport; + iopaddr_t offset; + int num_entries; + int entry; + cnodeid_t cnodeid; + nasid_t nasid; + char *node_val; + devfs_handle_t node_vhdl; + char vname[MAXDEVNAME]; + + /* Set the Bridge's 32-bit PCI to XTalk + * Direct Map register to the most useful + * value we can determine. Note that we + * must use a single xid for all of: + * direct-mapped 32-bit DMA accesses + * direct-mapped 64-bit DMA accesses + * DMA accesses through the PMU + * interrupts + * This is the only way to guarantee that + * completion interrupts will reach a CPU + * after all DMA data has reached memory. + * (Of course, there may be a few special + * drivers/controlers that explicitly manage + * this ordering problem.) + */ + + cnodeid = 0; /* default node id */ + /* + * Determine the base address node id to be used for all 32-bit + * Direct Mapping I/O. The default is node 0, but this can be changed + * via a DEVICE_ADMIN directive and the PCIBUS_DMATRANS_NODE + * attribute in the irix.sm config file. A device driver can obtain + * this node value via a call to pcibr_get_dmatrans_node(). + */ + node_val = device_admin_info_get(pcibr_vhdl, ADMIN_LBL_DMATRANS_NODE); + if (node_val != NULL) { + node_vhdl = hwgraph_path_to_vertex(node_val); + if (node_vhdl != GRAPH_VERTEX_NONE) { + cnodeid = nodevertex_to_cnodeid(node_vhdl); + } + if ((node_vhdl == GRAPH_VERTEX_NONE) || (cnodeid == CNODEID_NONE)) { + cnodeid = 0; + vertex_to_name(pcibr_vhdl, vname, sizeof(vname)); + PRINT_WARNING( "Invalid hwgraph node path specified:\n DEVICE_ADMIN: %s %s=%s\n", + vname, ADMIN_LBL_DMATRANS_NODE, node_val); + } + } + nasid = COMPACT_TO_NASID_NODEID(cnodeid); + paddr = NODE_OFFSET(nasid) + 0; + + /* currently, we just assume that if we ask + * for a DMA mapping to "zero" the XIO + * host will transmute this into a request + * for the lowest hunk of memory. + */ + xbase = xtalk_dmatrans_addr(xconn_vhdl, 0, + paddr, _PAGESZ, 0); + + if (xbase != XIO_NOWHERE) { + if (XIO_PACKED(xbase)) { + xport = XIO_PORT(xbase); + xbase = XIO_ADDR(xbase); + } else + xport = pcibr_soft->bs_mxid; + + offset = xbase & ((1ull << BRIDGE_DIRMAP_OFF_ADDRSHFT) - 1ull); + xbase >>= BRIDGE_DIRMAP_OFF_ADDRSHFT; + + dirmap = xport << BRIDGE_DIRMAP_W_ID_SHFT; + +#ifdef IRIX + dirmap |= BRIDGE_DIRMAP_RMF_64; +#endif + + if (xbase) + dirmap |= BRIDGE_DIRMAP_OFF & xbase; + else if (offset >= (512 << 20)) + dirmap |= BRIDGE_DIRMAP_ADD512; + + bridge->b_dir_map = dirmap; + } + /* + * Set bridge's idea of page size according to the system's + * idea of "IO page size". TBD: The idea of IO page size + * should really go away. + */ + /* + * ensure that we write and read without any interruption. + * The read following the write is required for the Bridge war + */ + spl_level = splhi(); +#if IOPGSIZE == 4096 + bridge->b_wid_control &= ~BRIDGE_CTRL_PAGE_SIZE; +#elif IOPGSIZE == 16384 + bridge->b_wid_control |= BRIDGE_CTRL_PAGE_SIZE; +#else + <<>>; +#endif + bridge->b_wid_control; /* inval addr bug war */ + splx(spl_level); + + /* Initialize internal mapping entries */ + for (entry = 0; entry < pcibr_soft->bs_int_ate_size; entry++) + bridge->b_int_ate_ram[entry].wr = 0; + + /* + * Determine if there's external mapping SSRAM on this + * bridge. Set up Bridge control register appropriately, + * inititlize SSRAM, and set software up to manage RAM + * entries as an allocatable resource. + * + * Currently, we just use the rm* routines to manage ATE + * allocation. We should probably replace this with a + * Best Fit allocator. + * + * For now, if we have external SSRAM, avoid using + * the internal ssram: we can't turn PREFETCH on + * when we use the internal SSRAM; and besides, + * this also guarantees that no allocation will + * straddle the internal/external line, so we + * can increment ATE write addresses rather than + * recomparing against BRIDGE_INTERNAL_ATES every + * time. + */ +#ifdef BRINGUP + /* + * 082799: for some reason pcibr_init_ext_ate_ram is causing + * a Data Bus Error. It should be zero anyway so just force it. + */ + num_entries = 0; +#else + num_entries = pcibr_init_ext_ate_ram(bridge); +#endif + + /* we always have 128 ATEs (512 for Xbridge) inside the chip + * even if disabled for debugging. + */ + pcibr_soft->bs_int_ate_map = rmallocmap(pcibr_soft->bs_int_ate_size); + pcibr_ate_free(pcibr_soft, 0, pcibr_soft->bs_int_ate_size); +#if PCIBR_ATE_DEBUG + printk("pcibr_attach: %d INTERNAL ATEs\n", pcibr_soft->bs_int_ate_size); +#endif + + if (num_entries > pcibr_soft->bs_int_ate_size) { +#if PCIBR_ATE_NOTBOTH /* for debug -- forces us to use external ates */ + printk("pcibr_attach: disabling internal ATEs.\n"); + pcibr_ate_alloc(pcibr_soft, pcibr_soft->bs_int_ate_size); +#endif + pcibr_soft->bs_ext_ate_map = rmallocmap(num_entries); + pcibr_ate_free(pcibr_soft, pcibr_soft->bs_int_ate_size, + num_entries - pcibr_soft->bs_int_ate_size); +#if PCIBR_ATE_DEBUG + printk("pcibr_attach: %d EXTERNAL ATEs\n", + num_entries - pcibr_soft->bs_int_ate_size); +#endif + } + } + + { + bridgereg_t dirmap; + iopaddr_t xbase; + + /* + * now figure the *real* xtalk base address + * that dirmap sends us to. + */ + dirmap = bridge->b_dir_map; + if (dirmap & BRIDGE_DIRMAP_OFF) + xbase = (iopaddr_t)(dirmap & BRIDGE_DIRMAP_OFF) + << BRIDGE_DIRMAP_OFF_ADDRSHFT; + else if (dirmap & BRIDGE_DIRMAP_ADD512) + xbase = 512 << 20; + else + xbase = 0; + + pcibr_soft->bs_dir_xbase = xbase; + + /* it is entirely possible that we may, at this + * point, have our dirmap pointing somewhere + * other than our "master" port. + */ + pcibr_soft->bs_dir_xport = + (dirmap & BRIDGE_DIRMAP_W_ID) >> BRIDGE_DIRMAP_W_ID_SHFT; + } + + /* pcibr sources an error interrupt; + * figure out where to send it. + * + * If any interrupts are enabled in bridge, + * then the prom set us up and our interrupt + * has already been reconnected in mlreset + * above. + * + * Need to set the D_INTR_ISERR flag + * in the dev_desc used for alocating the + * error interrupt, so our interrupt will + * be properly routed and prioritized. + * + * If our crosstalk provider wants to + * fix widget error interrupts to specific + * destinations, D_INTR_ISERR is how it + * knows to do this. + */ + + dev_desc = device_desc_dup(pcibr_vhdl); + device_desc_flags_set(dev_desc, + device_desc_flags_get(dev_desc) | D_INTR_ISERR); + device_desc_intr_name_set(dev_desc, "Bridge error"); + + xtalk_intr = xtalk_intr_alloc(xconn_vhdl, dev_desc, pcibr_vhdl); + ASSERT(xtalk_intr != NULL); + + device_desc_free(dev_desc); + + pcibr_soft->bsi_err_intr = xtalk_intr; + +#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) + /* + * On IP35 with XBridge, we do some extra checks in pcibr_setwidint + * in order to work around some addressing limitations. In order + * for that fire wall to work properly, we need to make sure we + * start from a known clean state. + */ + pcibr_clearwidint(bridge); +#endif + + printk("pribr_attach: FIXME Error Interrupt not registered\n"); + + xtalk_intr_connect(xtalk_intr, + (intr_func_t) pcibr_error_intr_handler, + (intr_arg_t) pcibr_soft, + (xtalk_intr_setfunc_t) pcibr_setwidint, + (void *) bridge, + (void *) 0); + + /* + * now we can start handling error interrupts; + * enable all of them. + * NOTE: some PCI ints may already be enabled. + */ + b_int_enable = bridge->b_int_enable | BRIDGE_ISR_ERRORS; + + + bridge->b_int_enable = b_int_enable; + bridge->b_int_mode = 0; /* do not send "clear interrupt" packets */ + + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ + + /* + * Depending on the rev of bridge, disable certain features. + * Easiest way seems to be to force the PCIBR_NOwhatever + * flag to be on for all DMA calls, which overrides any + * PCIBR_whatever flag or even the setting of whatever + * from the PCIIO_DMA_class flags (or even from the other + * PCIBR flags, since NO overrides YES). + */ + pcibr_soft->bs_dma_flags = 0; + + /* PREFETCH: + * Always completely disabled for REV.A; + * at "pcibr_prefetch_enable_rev", anyone + * asking for PCIIO_PREFETCH gets it. + * Between these two points, you have to ask + * for PCIBR_PREFETCH, which promises that + * your driver knows about known Bridge WARs. + */ + if (pcibr_soft->bs_rev_num < BRIDGE_PART_REV_B) + pcibr_soft->bs_dma_flags |= PCIBR_NOPREFETCH; + else if (pcibr_soft->bs_rev_num < + (BRIDGE_WIDGET_PART_NUM << 4 | pcibr_prefetch_enable_rev)) + pcibr_soft->bs_dma_flags |= PCIIO_NOPREFETCH; + + /* WRITE_GATHER: + * Disabled up to but not including the + * rev number in pcibr_wg_enable_rev. There + * is no "WAR range" as with prefetch. + */ + if (pcibr_soft->bs_rev_num < + (BRIDGE_WIDGET_PART_NUM << 4 | pcibr_wg_enable_rev)) + pcibr_soft->bs_dma_flags |= PCIBR_NOWRITE_GATHER; + + pciio_provider_register(pcibr_vhdl, &pcibr_provider); + pciio_provider_startup(pcibr_vhdl); + + pci_io_fb = 0x00000004; /* I/O FreeBlock Base */ + pci_io_fl = 0xFFFFFFFF; /* I/O FreeBlock Last */ + + pci_lo_fb = 0x00000010; /* Low Memory FreeBlock Base */ + pci_lo_fl = 0x001FFFFF; /* Low Memory FreeBlock Last */ + + pci_hi_fb = 0x00200000; /* High Memory FreeBlock Base */ + pci_hi_fl = 0x3FFFFFFF; /* High Memory FreeBlock Last */ + + + PCI_ADDR_SPACE_LIMITS_STORE(); + + /* build "no-slot" connection point + */ + pcibr_info = pcibr_device_info_new + (pcibr_soft, PCIIO_SLOT_NONE, PCIIO_FUNC_NONE, + PCIIO_VENDOR_ID_NONE, PCIIO_DEVICE_ID_NONE); + noslot_conn = pciio_device_info_register + (pcibr_vhdl, &pcibr_info->f_c); + + /* Remember the no slot connection point info for tearing it + * down during detach. + */ + pcibr_soft->bs_noslot_conn = noslot_conn; + pcibr_soft->bs_noslot_info = pcibr_info; +#if PCI_FBBE + fast_back_to_back_enable = 1; +#endif + +#if PCI_FBBE + if (fast_back_to_back_enable) { + /* + * All devices on the bus are capable of fast back to back, so + * we need to set the fast back to back bit in all devices on + * the bus that are capable of doing such accesses. + */ + } +#endif + +#ifdef IRIX + /* If the bridge has been reset then there is no need to reset + * the individual PCI slots. + */ + for (slot = 0; slot < 8; ++slot) + /* Reset all the slots */ + (void)pcibr_slot_reset(pcibr_vhdl,slot); +#endif + + for (slot = 0; slot < 8; ++slot) + /* Find out what is out there */ + (void)pcibr_slot_info_init(pcibr_vhdl,slot); + + for (slot = 0; slot < 8; ++slot) + /* Set up the address space for this slot in the pci land */ + (void)pcibr_slot_addr_space_init(pcibr_vhdl,slot); + + for (slot = 0; slot < 8; ++slot) + /* Setup the device register */ + (void)pcibr_slot_device_init(pcibr_vhdl, slot); + +#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) + for (slot = 0; slot < 8; ++slot) + /* Set up convenience links */ + if (is_xbridge(bridge)) + if (pcibr_soft->bs_slot[slot].bss_ninfo > 0) /* if occupied */ + pcibr_bus_cnvlink(pcibr_info->f_vertex, slot); +#endif + + for (slot = 0; slot < 8; ++slot) + /* Setup host/guest relations */ + (void)pcibr_slot_guest_info_init(pcibr_vhdl,slot); + + for (slot = 0; slot < 8; ++slot) + /* Initial RRB management */ + (void)pcibr_slot_initial_rrb_alloc(pcibr_vhdl,slot); + +#ifdef dagum + /* driver attach routines should be called out from generic linux code */ + for (slot = 0; slot < 8; ++slot) + /* Call the device attach */ + (void)pcibr_slot_call_device_attach(pcibr_vhdl,slot); +#endif /* dagum */ + +#ifdef LATER + if (strstr(nicinfo, XTALK_PCI_PART_NUM)) { + do_pcibr_rrb_autoalloc(pcibr_soft, 1, 8); +#if PCIBR_RRB_DEBUG + printf("\n\nFound XTALK_PCI (030-1275) at %v\n", xconn_vhdl); + + printf("pcibr_attach: %v Shoebox RRB MANAGEMENT: %d+%d free\n", + pcibr_vhdl, + pcibr_soft->bs_rrb_avail[0], + pcibr_soft->bs_rrb_avail[1]); + + for (slot = 0; slot < 8; ++slot) + printf("\t%d+%d+%d", + 0xFFF & pcibr_soft->bs_rrb_valid[slot], + 0xFFF & pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL], + pcibr_soft->bs_rrb_res[slot]); + + printf("\n"); +#endif + } +#else + printk("pcibr_attach: FIXME to call do_pcibr_rrb_autoalloc nicinfo 0x%p\n", nicinfo); +#endif + + if (aa) + async_attach_add_info(noslot_conn, aa); + + pciio_device_attach(noslot_conn); + + + /* + * Tear down pointer to async attach info -- async threads for + * bridge's descendants may be running but the bridge's work is done. + */ + if (aa) + async_attach_del_info(xconn_vhdl); + + return 0; +} +/* + * pcibr_detach: + * Detach the bridge device from the hwgraph after cleaning out all the + * underlying vertices. + */ +int +pcibr_detach(devfs_handle_t xconn) +{ + pciio_slot_t slot; + devfs_handle_t pcibr_vhdl; + pcibr_soft_t pcibr_soft; + bridge_t *bridge; + + /* Get the bridge vertex from its xtalk connection point */ + if (hwgraph_traverse(xconn, EDGE_LBL_PCI, &pcibr_vhdl) != GRAPH_SUCCESS) + return(1); + + pcibr_soft = pcibr_soft_get(pcibr_vhdl); + bridge = pcibr_soft->bs_base; + + /* Disable the interrupts from the bridge */ + bridge->b_int_enable = 0; + + /* Detach all the PCI devices talking to this bridge */ + for(slot = 0; slot < 8; slot++) { +#ifdef DEBUG + printk("pcibr_device_detach called for %p/%d\n", + pcibr_vhdl,slot); +#endif + pcibr_device_detach(pcibr_vhdl, slot); + } + + /* Unregister the no-slot connection point */ + pciio_device_info_unregister(pcibr_vhdl, + &(pcibr_soft->bs_noslot_info->f_c)); + + spinlock_destroy(&pcibr_soft->bs_lock); + kfree(pcibr_soft->bs_name); + + /* Error handler gets unregistered when the widget info is + * cleaned + */ + /* Free the soft ATE maps */ + if (pcibr_soft->bs_int_ate_map) + rmfreemap(pcibr_soft->bs_int_ate_map); + if (pcibr_soft->bs_ext_ate_map) + rmfreemap(pcibr_soft->bs_ext_ate_map); + + /* Disconnect the error interrupt and free the xtalk resources + * associated with it. + */ + xtalk_intr_disconnect(pcibr_soft->bsi_err_intr); + xtalk_intr_free(pcibr_soft->bsi_err_intr); + + /* Clear the software state maintained by the bridge driver for this + * bridge. + */ + DEL(pcibr_soft); + /* Remove the Bridge revision labelled info */ + (void)hwgraph_info_remove_LBL(pcibr_vhdl, INFO_LBL_PCIBR_ASIC_REV, NULL); + /* Remove the character device associated with this bridge */ + (void)hwgraph_edge_remove(pcibr_vhdl, EDGE_LBL_CONTROLLER, NULL); + /* Remove the PCI bridge vertex */ + (void)hwgraph_edge_remove(xconn, EDGE_LBL_PCI, NULL); + + return(0); +} + +int +pcibr_asic_rev(devfs_handle_t pconn_vhdl) +{ + devfs_handle_t pcibr_vhdl; + arbitrary_info_t ainfo; + + if (GRAPH_SUCCESS != + hwgraph_traverse(pconn_vhdl, EDGE_LBL_MASTER, &pcibr_vhdl)) + return -1; + + if (GRAPH_SUCCESS != + hwgraph_info_get_LBL(pcibr_vhdl, INFO_LBL_PCIBR_ASIC_REV, &ainfo)) + return -1; + + return (int) ainfo; +} + +int +pcibr_write_gather_flush(devfs_handle_t pconn_vhdl) +{ + pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + pciio_slot_t slot; + slot = pciio_info_slot_get(pciio_info); + pcibr_device_write_gather_flush(pcibr_soft, slot); + return 0; +} + +/* ===================================================================== + * PIO MANAGEMENT + */ + +LOCAL iopaddr_t +pcibr_addr_pci_to_xio(devfs_handle_t pconn_vhdl, + pciio_slot_t slot, + pciio_space_t space, + iopaddr_t pci_addr, + size_t req_size, + unsigned flags) +{ + pcibr_info_t pcibr_info = pcibr_info_get(pconn_vhdl); + pciio_info_t pciio_info = &pcibr_info->f_c; + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + bridge_t *bridge = pcibr_soft->bs_base; + + unsigned bar; /* which BASE reg on device is decoding */ + iopaddr_t xio_addr = XIO_NOWHERE; + + pciio_space_t wspace; /* which space device is decoding */ + iopaddr_t wbase; /* base of device decode on PCI */ + size_t wsize; /* size of device decode on PCI */ + + int try; /* DevIO(x) window scanning order control */ + int win; /* which DevIO(x) window is being used */ + pciio_space_t mspace; /* target space for devio(x) register */ + iopaddr_t mbase; /* base of devio(x) mapped area on PCI */ + size_t msize; /* size of devio(x) mapped area on PCI */ + size_t mmask; /* addr bits stored in Device(x) */ + + unsigned s; + + s = pcibr_lock(pcibr_soft); + + if (pcibr_soft->bs_slot[slot].has_host) { + slot = pcibr_soft->bs_slot[slot].host_slot; + pcibr_info = pcibr_soft->bs_slot[slot].bss_infos[0]; + } + if (space == PCIIO_SPACE_NONE) + goto done; + + if (space == PCIIO_SPACE_CFG) { + /* + * Usually, the first mapping + * established to a PCI device + * is to its config space. + * + * In any case, we definitely + * do NOT need to worry about + * PCI BASE registers, and + * MUST NOT attempt to point + * the DevIO(x) window at + * this access ... + */ + if (((flags & PCIIO_BYTE_STREAM) == 0) && + ((pci_addr + req_size) <= BRIDGE_TYPE0_CFG_FUNC_OFF)) + xio_addr = pci_addr + BRIDGE_TYPE0_CFG_DEV(slot); + + goto done; + } + if (space == PCIIO_SPACE_ROM) { + /* PIO to the Expansion Rom. + * Driver is responsible for + * enabling and disabling + * decodes properly. + */ + wbase = pcibr_info->f_rbase; + wsize = pcibr_info->f_rsize; + + /* + * While the driver should know better + * than to attempt to map more space + * than the device is decoding, he might + * do it; better to bail out here. + */ + if ((pci_addr + req_size) > wsize) + goto done; + + pci_addr += wbase; + space = PCIIO_SPACE_MEM; + } + /* + * reduce window mappings to raw + * space mappings (maybe allocating + * windows), and try for DevIO(x) + * usage (setting it if it is available). + */ + bar = space - PCIIO_SPACE_WIN0; + if (bar < 6) { + wspace = pcibr_info->f_window[bar].w_space; + if (wspace == PCIIO_SPACE_NONE) + goto done; + + /* get pci base and size */ + wbase = pcibr_info->f_window[bar].w_base; + wsize = pcibr_info->f_window[bar].w_size; + + /* + * While the driver should know better + * than to attempt to map more space + * than the device is decoding, he might + * do it; better to bail out here. + */ + if ((pci_addr + req_size) > wsize) + goto done; + + /* shift from window relative to + * decoded space relative. + */ + pci_addr += wbase; + space = wspace; + } else + bar = -1; + + /* Scan all the DevIO(x) windows twice looking for one + * that can satisfy our request. The first time through, + * only look at assigned windows; the second time, also + * look at PCIIO_SPACE_NONE windows. Arrange the order + * so we always look at our own window first. + * + * We will not attempt to satisfy a single request + * by concatinating multiple windows. + */ + for (try = 0; try < 16; ++try) { + bridgereg_t devreg; + unsigned offset; + + win = (try + slot) % 8; + + /* If this DevIO(x) mapping area can provide + * a mapping to this address, use it. + */ + msize = (win < 2) ? 0x200000 : 0x100000; + mmask = -msize; + if (space != PCIIO_SPACE_IO) + mmask &= 0x3FFFFFFF; + + offset = pci_addr & (msize - 1); + + /* If this window can't possibly handle that request, + * go on to the next window. + */ + if (((pci_addr & (msize - 1)) + req_size) > msize) + continue; + + devreg = pcibr_soft->bs_slot[win].bss_device; + + /* Is this window "nailed down"? + * If not, maybe we can use it. + * (only check this the second time through) + */ + mspace = pcibr_soft->bs_slot[win].bss_devio.bssd_space; + if ((try > 7) && (mspace == PCIIO_SPACE_NONE)) { + + /* If this is the primary DevIO(x) window + * for some other device, skip it. + */ + if ((win != slot) && + (PCIIO_VENDOR_ID_NONE != + pcibr_soft->bs_slot[win].bss_vendor_id)) + continue; + + /* It's a free window, and we fit in it. + * Set up Device(win) to our taste. + */ + mbase = pci_addr & mmask; + + /* check that we would really get from + * here to there. + */ + if ((mbase | offset) != pci_addr) + continue; + + devreg &= ~BRIDGE_DEV_OFF_MASK; + if (space != PCIIO_SPACE_IO) + devreg |= BRIDGE_DEV_DEV_IO_MEM; + else + devreg &= ~BRIDGE_DEV_DEV_IO_MEM; + devreg |= (mbase >> 20) & BRIDGE_DEV_OFF_MASK; + + /* default is WORD_VALUES. + * if you specify both, + * operation is undefined. + */ + if (flags & PCIIO_BYTE_STREAM) + devreg |= BRIDGE_DEV_DEV_SWAP; + else + devreg &= ~BRIDGE_DEV_DEV_SWAP; + + if (pcibr_soft->bs_slot[win].bss_device != devreg) { + bridge->b_device[win].reg = devreg; + pcibr_soft->bs_slot[win].bss_device = devreg; + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ + +#if DEBUG && PCI_DEBUG + printk("pcibr Device(%d): 0x%lx\n", win, bridge->b_device[win].reg); +#endif + } + pcibr_soft->bs_slot[win].bss_devio.bssd_space = space; + pcibr_soft->bs_slot[win].bss_devio.bssd_base = mbase; + xio_addr = BRIDGE_DEVIO(win) + (pci_addr - mbase); + +#if DEBUG && PCI_DEBUG + printk("%s LINE %d map to space %d space desc 0x%x[%lx..%lx] for slot %d allocates DevIO(%d) devreg 0x%x\n", + __FUNCTION__, __LINE__, space, space_desc, + pci_addr, pci_addr + req_size - 1, + slot, win, devreg); +#endif + + goto done; + } /* endif DevIO(x) not pointed */ + mbase = pcibr_soft->bs_slot[win].bss_devio.bssd_base; + + /* Now check for request incompat with DevIO(x) + */ + if ((mspace != space) || + (pci_addr < mbase) || + ((pci_addr + req_size) > (mbase + msize)) || + ((flags & PCIIO_BYTE_STREAM) && !(devreg & BRIDGE_DEV_DEV_SWAP)) || + (!(flags & PCIIO_BYTE_STREAM) && (devreg & BRIDGE_DEV_DEV_SWAP))) + continue; + + /* DevIO(x) window is pointed at PCI space + * that includes our target. Calculate the + * final XIO address, release the lock and + * return. + */ + xio_addr = BRIDGE_DEVIO(win) + (pci_addr - mbase); + +#if DEBUG && PCI_DEBUG + printk("%s LINE %d map to space %d [0x%p..0x%p] for slot %d uses DevIO(%d)\n", + __FUNCTION__, __LINE__, space, pci_addr, pci_addr + req_size - 1, slot, win); +#endif + goto done; + } + + switch (space) { + /* + * Accesses to device decode + * areas that do a not fit + * within the DevIO(x) space are + * modified to be accesses via + * the direct mapping areas. + * + * If necessary, drivers can + * explicitly ask for mappings + * into these address spaces, + * but this should never be needed. + */ + case PCIIO_SPACE_MEM: /* "mem space" */ + case PCIIO_SPACE_MEM32: /* "mem, use 32-bit-wide bus" */ + if ((pci_addr + BRIDGE_PCI_MEM32_BASE + req_size - 1) <= + BRIDGE_PCI_MEM32_LIMIT) + xio_addr = pci_addr + BRIDGE_PCI_MEM32_BASE; + break; + + case PCIIO_SPACE_MEM64: /* "mem, use 64-bit-wide bus" */ + if ((pci_addr + BRIDGE_PCI_MEM64_BASE + req_size - 1) <= + BRIDGE_PCI_MEM64_LIMIT) + xio_addr = pci_addr + BRIDGE_PCI_MEM64_BASE; + break; + + case PCIIO_SPACE_IO: /* "i/o space" */ + /* Bridge Hardware Bug WAR #482741: + * The 4G area that maps directly from + * XIO space to PCI I/O space is busted + * until Bridge Rev D. + */ + if ((pcibr_soft->bs_rev_num > BRIDGE_PART_REV_C) && + ((pci_addr + BRIDGE_PCI_IO_BASE + req_size - 1) <= + BRIDGE_PCI_IO_LIMIT)) + xio_addr = pci_addr + BRIDGE_PCI_IO_BASE; + break; + } + + /* Check that "Direct PIO" byteswapping matches, + * try to change it if it does not. + */ + if (xio_addr != XIO_NOWHERE) { + unsigned bst; /* nonzero to set bytestream */ + unsigned *bfp; /* addr of record of how swapper is set */ + unsigned swb; /* which control bit to mung */ + unsigned bfo; /* current swapper setting */ + unsigned bfn; /* desired swapper setting */ + + bfp = ((space == PCIIO_SPACE_IO) + ? (&pcibr_soft->bs_pio_end_io) + : (&pcibr_soft->bs_pio_end_mem)); + + bfo = *bfp; + + bst = flags & PCIIO_BYTE_STREAM; + + bfn = bst ? PCIIO_BYTE_STREAM : PCIIO_WORD_VALUES; + + if (bfn == bfo) { /* we already match. */ + ; + } else if (bfo != 0) { /* we have a conflict. */ +#if DEBUG && PCI_DEBUG + printk("pcibr_addr_pci_to_xio: swap conflict in space %d , was%s%s, want%s%s\n", + space, + bfo & PCIIO_BYTE_STREAM ? " BYTE_STREAM" : "", + bfo & PCIIO_WORD_VALUES ? " WORD_VALUES" : "", + bfn & PCIIO_BYTE_STREAM ? " BYTE_STREAM" : "", + bfn & PCIIO_WORD_VALUES ? " WORD_VALUES" : ""); +#endif + xio_addr = XIO_NOWHERE; + } else { /* OK to make the change. */ + bridgereg_t octl, nctl; + + swb = (space == PCIIO_SPACE_IO) ? BRIDGE_CTRL_IO_SWAP : BRIDGE_CTRL_MEM_SWAP; + octl = bridge->b_wid_control; + nctl = bst ? octl | swb : octl & ~swb; + + if (octl != nctl) /* make the change if any */ + bridge->b_wid_control = nctl; + + *bfp = bfn; /* record the assignment */ + +#if DEBUG && PCI_DEBUG + printk("pcibr_addr_pci_to_xio: swap for space %d set to%s%s\n", + space, + bfn & PCIIO_BYTE_STREAM ? " BYTE_STREAM" : "", + bfn & PCIIO_WORD_VALUES ? " WORD_VALUES" : ""); +#endif + } + } + done: + pcibr_unlock(pcibr_soft, s); + return xio_addr; +} + +/*ARGSUSED6 */ +pcibr_piomap_t +pcibr_piomap_alloc(devfs_handle_t pconn_vhdl, + device_desc_t dev_desc, + pciio_space_t space, + iopaddr_t pci_addr, + size_t req_size, + size_t req_size_max, + unsigned flags) +{ + pcibr_info_t pcibr_info = pcibr_info_get(pconn_vhdl); + pciio_info_t pciio_info = &pcibr_info->f_c; + pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn; + + pcibr_piomap_t *mapptr; + pcibr_piomap_t maplist; + pcibr_piomap_t pcibr_piomap; + iopaddr_t xio_addr; + xtalk_piomap_t xtalk_piomap; + unsigned s; + + /* Make sure that the req sizes are non-zero */ + if ((req_size < 1) || (req_size_max < 1)) + return NULL; + + /* + * Code to translate slot/space/addr + * into xio_addr is common between + * this routine and pcibr_piotrans_addr. + */ + xio_addr = pcibr_addr_pci_to_xio(pconn_vhdl, pciio_slot, space, pci_addr, req_size, flags); + + if (xio_addr == XIO_NOWHERE) + return NULL; + + /* Check the piomap list to see if there is already an allocated + * piomap entry but not in use. If so use that one. Otherwise + * allocate a new piomap entry and add it to the piomap list + */ + mapptr = &(pcibr_info->f_piomap); + + s = pcibr_lock(pcibr_soft); + for (pcibr_piomap = *mapptr; + pcibr_piomap != NULL; + pcibr_piomap = pcibr_piomap->bp_next) { + if (pcibr_piomap->bp_mapsz == 0) + break; + } + + if (pcibr_piomap) + mapptr = NULL; + else { + pcibr_unlock(pcibr_soft, s); + NEW(pcibr_piomap); + } + + pcibr_piomap->bp_dev = pconn_vhdl; + pcibr_piomap->bp_slot = pciio_slot; + pcibr_piomap->bp_flags = flags; + pcibr_piomap->bp_space = space; + pcibr_piomap->bp_pciaddr = pci_addr; + pcibr_piomap->bp_mapsz = req_size; + pcibr_piomap->bp_soft = pcibr_soft; + pcibr_piomap->bp_toc[0] = 0; + + if (mapptr) { + s = pcibr_lock(pcibr_soft); + maplist = *mapptr; + pcibr_piomap->bp_next = maplist; + *mapptr = pcibr_piomap; + } + pcibr_unlock(pcibr_soft, s); + + + if (pcibr_piomap) { + xtalk_piomap = + xtalk_piomap_alloc(xconn_vhdl, 0, + xio_addr, + req_size, req_size_max, + flags & PIOMAP_FLAGS); + if (xtalk_piomap) { + pcibr_piomap->bp_xtalk_addr = xio_addr; + pcibr_piomap->bp_xtalk_pio = xtalk_piomap; + } else { + pcibr_piomap->bp_mapsz = 0; + pcibr_piomap = 0; + } + } + return pcibr_piomap; +} + +/*ARGSUSED */ +void +pcibr_piomap_free(pcibr_piomap_t pcibr_piomap) +{ + xtalk_piomap_free(pcibr_piomap->bp_xtalk_pio); + pcibr_piomap->bp_xtalk_pio = 0; + pcibr_piomap->bp_mapsz = 0; +} + +/*ARGSUSED */ +caddr_t +pcibr_piomap_addr(pcibr_piomap_t pcibr_piomap, + iopaddr_t pci_addr, + size_t req_size) +{ + return xtalk_piomap_addr(pcibr_piomap->bp_xtalk_pio, + pcibr_piomap->bp_xtalk_addr + + pci_addr - pcibr_piomap->bp_pciaddr, + req_size); +} + +/*ARGSUSED */ +void +pcibr_piomap_done(pcibr_piomap_t pcibr_piomap) +{ + xtalk_piomap_done(pcibr_piomap->bp_xtalk_pio); +} + +/*ARGSUSED */ +caddr_t +pcibr_piotrans_addr(devfs_handle_t pconn_vhdl, + device_desc_t dev_desc, + pciio_space_t space, + iopaddr_t pci_addr, + size_t req_size, + unsigned flags) +{ + pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); + pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn; + + iopaddr_t xio_addr; + + xio_addr = pcibr_addr_pci_to_xio(pconn_vhdl, pciio_slot, space, pci_addr, req_size, flags); + + if (xio_addr == XIO_NOWHERE) + return NULL; + + return xtalk_piotrans_addr(xconn_vhdl, 0, xio_addr, req_size, flags & PIOMAP_FLAGS); +} + +/* + * PIO Space allocation and management. + * Allocate and Manage the PCI PIO space (mem and io space) + * This routine is pretty simplistic at this time, and + * does pretty trivial management of allocation and freeing.. + * The current scheme is prone for fragmentation.. + * Change the scheme to use bitmaps. + */ + +/*ARGSUSED */ +iopaddr_t +pcibr_piospace_alloc(devfs_handle_t pconn_vhdl, + device_desc_t dev_desc, + pciio_space_t space, + size_t req_size, + size_t alignment) +{ + pcibr_info_t pcibr_info = pcibr_info_get(pconn_vhdl); + pciio_info_t pciio_info = &pcibr_info->f_c; + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + + pciio_piospace_t piosp; + int s; + + iopaddr_t *pciaddr, *pcilast; + iopaddr_t start_addr; + size_t align_mask; + + /* + * Check for proper alignment + */ + ASSERT(alignment >= NBPP); + ASSERT((alignment & (alignment - 1)) == 0); + + align_mask = alignment - 1; + s = pcibr_lock(pcibr_soft); + + /* + * First look if a previously allocated chunk exists. + */ + if ((piosp = pcibr_info->f_piospace) != (pciio_piospace_t)0) { + /* + * Look through the list for a right sized free chunk. + */ + do { + if (piosp->free && + (piosp->space == space) && + (piosp->count >= req_size) && + !(piosp->start & align_mask)) { + piosp->free = 0; + pcibr_unlock(pcibr_soft, s); + return piosp->start; + } + piosp = piosp->next; + } while (piosp); + } + ASSERT(!piosp); + + switch (space) { + case PCIIO_SPACE_IO: + pciaddr = &pcibr_soft->bs_spinfo.pci_io_base; + pcilast = &pcibr_soft->bs_spinfo.pci_io_last; + break; + case PCIIO_SPACE_MEM: + case PCIIO_SPACE_MEM32: + pciaddr = &pcibr_soft->bs_spinfo.pci_mem_base; + pcilast = &pcibr_soft->bs_spinfo.pci_mem_last; + break; + default: + ASSERT(0); + pcibr_unlock(pcibr_soft, s); + return 0; + } + + start_addr = *pciaddr; + + /* + * Align start_addr. + */ + if (start_addr & align_mask) + start_addr = (start_addr + align_mask) & ~align_mask; + + if ((start_addr + req_size) > *pcilast) { + /* + * If too big a request, reject it. + */ + pcibr_unlock(pcibr_soft, s); + return 0; + } + *pciaddr = (start_addr + req_size); + + NEW(piosp); + piosp->free = 0; + piosp->space = space; + piosp->start = start_addr; + piosp->count = req_size; + piosp->next = pcibr_info->f_piospace; + pcibr_info->f_piospace = piosp; + + pcibr_unlock(pcibr_soft, s); + return start_addr; +} + +/*ARGSUSED */ +void +pcibr_piospace_free(devfs_handle_t pconn_vhdl, + pciio_space_t space, + iopaddr_t pciaddr, + size_t req_size) +{ + pcibr_info_t pcibr_info = pcibr_info_get(pconn_vhdl); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pcibr_info->f_mfast; + + pciio_piospace_t piosp; + int s; + char name[1024]; + + /* + * Look through the bridge data structures for the pciio_piospace_t + * structure corresponding to 'pciaddr' + */ + s = pcibr_lock(pcibr_soft); + piosp = pcibr_info->f_piospace; + while (piosp) { + /* + * Piospace free can only be for the complete + * chunk and not parts of it.. + */ + if (piosp->start == pciaddr) { + if (piosp->count == req_size) + break; + /* + * Improper size passed for freeing.. + * Print a message and break; + */ + hwgraph_vertex_name_get(pconn_vhdl, name, 1024); + PRINT_WARNING("pcibr_piospace_free: error"); + PRINT_WARNING("Device %s freeing size (0x%lx) different than allocated (0x%lx)", + name, req_size, piosp->count); + PRINT_WARNING("Freeing 0x%lx instead", piosp->count); + break; + } + piosp = piosp->next; + } + + if (!piosp) { + PRINT_WARNING( + "pcibr_piospace_free: Address 0x%lx size 0x%lx - No match\n", + pciaddr, req_size); + pcibr_unlock(pcibr_soft, s); + return; + } + piosp->free = 1; + pcibr_unlock(pcibr_soft, s); + return; +} + +/* ===================================================================== + * DMA MANAGEMENT + * + * The Bridge ASIC provides three methods of doing + * DMA: via a "direct map" register available in + * 32-bit PCI space (which selects a contiguous 2G + * address space on some other widget), via + * "direct" addressing via 64-bit PCI space (all + * destination information comes from the PCI + * address, including transfer attributes), and via + * a "mapped" region that allows a bunch of + * different small mappings to be established with + * the PMU. + * + * For efficiency, we most prefer to use the 32-bit + * direct mapping facility, since it requires no + * resource allocations. The advantage of using the + * PMU over the 64-bit direct is that single-cycle + * PCI addressing can be used; the advantage of + * using 64-bit direct over PMU addressing is that + * we do not have to allocate entries in the PMU. + */ + +/* + * Convert PCI-generic software flags and Bridge-specific software flags + * into Bridge-specific Direct Map attribute bits. + */ +LOCAL iopaddr_t +pcibr_flags_to_d64(unsigned flags, pcibr_soft_t pcibr_soft) +{ + iopaddr_t attributes = 0; + + /* Sanity check: Bridge only allows use of VCHAN1 via 64-bit addrs */ +#ifdef IRIX + ASSERT_ALWAYS(!(flags & PCIBR_VCHAN1) || (flags & PCIIO_DMA_A64)); +#endif + + /* Generic macro flags + */ + if (flags & PCIIO_DMA_DATA) { /* standard data channel */ + attributes &= ~PCI64_ATTR_BAR; /* no barrier bit */ + attributes |= PCI64_ATTR_PREF; /* prefetch on */ + } + if (flags & PCIIO_DMA_CMD) { /* standard command channel */ + attributes |= PCI64_ATTR_BAR; /* barrier bit on */ + attributes &= ~PCI64_ATTR_PREF; /* disable prefetch */ + } + /* Generic detail flags + */ + if (flags & PCIIO_PREFETCH) + attributes |= PCI64_ATTR_PREF; + if (flags & PCIIO_NOPREFETCH) + attributes &= ~PCI64_ATTR_PREF; + + /* the swap bit is in the address attributes for xbridge */ + if (pcibr_soft->bs_xbridge) { + if (flags & PCIIO_BYTE_STREAM) + attributes |= PCI64_ATTR_SWAP; + if (flags & PCIIO_WORD_VALUES) + attributes &= ~PCI64_ATTR_SWAP; + } + + /* Provider-specific flags + */ + if (flags & PCIBR_BARRIER) + attributes |= PCI64_ATTR_BAR; + if (flags & PCIBR_NOBARRIER) + attributes &= ~PCI64_ATTR_BAR; + + if (flags & PCIBR_PREFETCH) + attributes |= PCI64_ATTR_PREF; + if (flags & PCIBR_NOPREFETCH) + attributes &= ~PCI64_ATTR_PREF; + + if (flags & PCIBR_PRECISE) + attributes |= PCI64_ATTR_PREC; + if (flags & PCIBR_NOPRECISE) + attributes &= ~PCI64_ATTR_PREC; + + if (flags & PCIBR_VCHAN1) + attributes |= PCI64_ATTR_VIRTUAL; + if (flags & PCIBR_VCHAN0) + attributes &= ~PCI64_ATTR_VIRTUAL; + + return (attributes); +} + +/* + * Convert PCI-generic software flags and Bridge-specific software flags + * into Bridge-specific Address Translation Entry attribute bits. + */ +LOCAL bridge_ate_t +pcibr_flags_to_ate(unsigned flags) +{ + bridge_ate_t attributes; + + /* default if nothing specified: + * NOBARRIER + * NOPREFETCH + * NOPRECISE + * COHERENT + * Plus the valid bit + */ + attributes = ATE_CO | ATE_V; + + /* Generic macro flags + */ + if (flags & PCIIO_DMA_DATA) { /* standard data channel */ + attributes &= ~ATE_BAR; /* no barrier */ + attributes |= ATE_PREF; /* prefetch on */ + } + if (flags & PCIIO_DMA_CMD) { /* standard command channel */ + attributes |= ATE_BAR; /* barrier bit on */ + attributes &= ~ATE_PREF; /* disable prefetch */ + } + /* Generic detail flags + */ + if (flags & PCIIO_PREFETCH) + attributes |= ATE_PREF; + if (flags & PCIIO_NOPREFETCH) + attributes &= ~ATE_PREF; + + /* Provider-specific flags + */ + if (flags & PCIBR_BARRIER) + attributes |= ATE_BAR; + if (flags & PCIBR_NOBARRIER) + attributes &= ~ATE_BAR; + + if (flags & PCIBR_PREFETCH) + attributes |= ATE_PREF; + if (flags & PCIBR_NOPREFETCH) + attributes &= ~ATE_PREF; + + if (flags & PCIBR_PRECISE) + attributes |= ATE_PREC; + if (flags & PCIBR_NOPRECISE) + attributes &= ~ATE_PREC; + + return (attributes); +} + +/*ARGSUSED */ +pcibr_dmamap_t +pcibr_dmamap_alloc(devfs_handle_t pconn_vhdl, + device_desc_t dev_desc, + size_t req_size_max, + unsigned flags) +{ + pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn; + pciio_slot_t slot; + xwidgetnum_t xio_port; + + xtalk_dmamap_t xtalk_dmamap; + pcibr_dmamap_t pcibr_dmamap; + int ate_count; + int ate_index; + + /* merge in forced flags */ + flags |= pcibr_soft->bs_dma_flags; + + NEWf(pcibr_dmamap, flags); + if (!pcibr_dmamap) + return 0; + + xtalk_dmamap = xtalk_dmamap_alloc(xconn_vhdl, dev_desc, req_size_max, + flags & DMAMAP_FLAGS); + if (!xtalk_dmamap) { +#if PCIBR_ATE_DEBUG + printk("pcibr_attach: xtalk_dmamap_alloc failed\n"); +#endif + DEL(pcibr_dmamap); + return 0; + } + xio_port = pcibr_soft->bs_mxid; + slot = pciio_info_slot_get(pciio_info); + + pcibr_dmamap->bd_dev = pconn_vhdl; + pcibr_dmamap->bd_slot = slot; + pcibr_dmamap->bd_soft = pcibr_soft; + pcibr_dmamap->bd_xtalk = xtalk_dmamap; + pcibr_dmamap->bd_max_size = req_size_max; + pcibr_dmamap->bd_xio_port = xio_port; + + if (flags & PCIIO_DMA_A64) { + if (!pcibr_try_set_device(pcibr_soft, slot, flags, BRIDGE_DEV_D64_BITS)) { + iopaddr_t pci_addr; + int have_rrbs; + int min_rrbs; + + /* Device is capable of A64 operations, + * and the attributes of the DMA are + * consistant with any previous DMA + * mappings using shared resources. + */ + + pci_addr = pcibr_flags_to_d64(flags, pcibr_soft); + + pcibr_dmamap->bd_flags = flags; + pcibr_dmamap->bd_xio_addr = 0; + pcibr_dmamap->bd_pci_addr = pci_addr; + + /* Make sure we have an RRB (or two). + */ + if (!(pcibr_soft->bs_rrb_fixed & (1 << slot))) { + if (flags & PCIBR_VCHAN1) + slot += PCIBR_RRB_SLOT_VIRTUAL; + have_rrbs = pcibr_soft->bs_rrb_valid[slot]; + if (have_rrbs < 2) { + if (pci_addr & PCI64_ATTR_PREF) + min_rrbs = 2; + else + min_rrbs = 1; + if (have_rrbs < min_rrbs) + do_pcibr_rrb_autoalloc(pcibr_soft, slot, min_rrbs - have_rrbs); + } + } +#if PCIBR_ATE_DEBUG + printk("pcibr_dmamap_alloc: using direct64\n"); +#endif + return pcibr_dmamap; + } +#if PCIBR_ATE_DEBUG + printk("pcibr_dmamap_alloc: unable to use direct64\n"); +#endif + flags &= ~PCIIO_DMA_A64; + } + if (flags & PCIIO_FIXED) { + /* warning: mappings may fail later, + * if direct32 can't get to the address. + */ + if (!pcibr_try_set_device(pcibr_soft, slot, flags, BRIDGE_DEV_D32_BITS)) { + /* User desires DIRECT A32 operations, + * and the attributes of the DMA are + * consistant with any previous DMA + * mappings using shared resources. + * Mapping calls may fail if target + * is outside the direct32 range. + */ +#if PCIBR_ATE_DEBUG + printk("pcibr_dmamap_alloc: using direct32\n"); +#endif + pcibr_dmamap->bd_flags = flags; + pcibr_dmamap->bd_xio_addr = pcibr_soft->bs_dir_xbase; + pcibr_dmamap->bd_pci_addr = PCI32_DIRECT_BASE; + return pcibr_dmamap; + } +#if PCIBR_ATE_DEBUG + printk("pcibr_dmamap_alloc: unable to use direct32\n"); +#endif + /* If the user demands FIXED and we can't + * give it to him, fail. + */ + xtalk_dmamap_free(xtalk_dmamap); + DEL(pcibr_dmamap); + return 0; + } + /* + * Allocate Address Translation Entries from the mapping RAM. + * Unless the PCIBR_NO_ATE_ROUNDUP flag is specified, + * the maximum number of ATEs is based on the worst-case + * scenario, where the requested target is in the + * last byte of an ATE; thus, mapping IOPGSIZE+2 + * does end up requiring three ATEs. + */ + if (!(flags & PCIBR_NO_ATE_ROUNDUP)) { + ate_count = IOPG((IOPGSIZE - 1) /* worst case start offset */ + +req_size_max /* max mapping bytes */ + - 1) + 1; /* round UP */ + } else { /* assume requested target is page aligned */ + ate_count = IOPG(req_size_max /* max mapping bytes */ + - 1) + 1; /* round UP */ + } + + ate_index = pcibr_ate_alloc(pcibr_soft, ate_count); + + if (ate_index != -1) { + if (!pcibr_try_set_device(pcibr_soft, slot, flags, BRIDGE_DEV_PMU_BITS)) { + bridge_ate_t ate_proto; + int have_rrbs; + int min_rrbs; + +#if PCIBR_ATE_DEBUG + printk("pcibr_dmamap_alloc: using PMU\n"); +#endif + + ate_proto = pcibr_flags_to_ate(flags); + + pcibr_dmamap->bd_flags = flags; + pcibr_dmamap->bd_pci_addr = + PCI32_MAPPED_BASE + IOPGSIZE * ate_index; + /* + * for xbridge the byte-swap bit == bit 29 of pci address + */ + if (pcibr_soft->bs_xbridge) { + if (flags & PCIIO_BYTE_STREAM) + ATE_SWAP_ON(pcibr_dmamap->bd_pci_addr); + /* + * If swap was set in bss_device in pcibr_endian_set() + * we need to change the address bit. + */ + if (pcibr_soft->bs_slot[slot].bss_device & + BRIDGE_DEV_SWAP_PMU) + ATE_SWAP_ON(pcibr_dmamap->bd_pci_addr); + if (flags & PCIIO_WORD_VALUES) + ATE_SWAP_OFF(pcibr_dmamap->bd_pci_addr); + } + pcibr_dmamap->bd_xio_addr = 0; + pcibr_dmamap->bd_ate_ptr = pcibr_ate_addr(pcibr_soft, ate_index); + pcibr_dmamap->bd_ate_index = ate_index; + pcibr_dmamap->bd_ate_count = ate_count; + pcibr_dmamap->bd_ate_proto = ate_proto; + + /* Make sure we have an RRB (or two). + */ + if (!(pcibr_soft->bs_rrb_fixed & (1 << slot))) { + have_rrbs = pcibr_soft->bs_rrb_valid[slot]; + if (have_rrbs < 2) { + if (ate_proto & ATE_PREF) + min_rrbs = 2; + else + min_rrbs = 1; + if (have_rrbs < min_rrbs) + do_pcibr_rrb_autoalloc(pcibr_soft, slot, min_rrbs - have_rrbs); + } + } + if (ate_index >= pcibr_soft->bs_int_ate_size && + !pcibr_soft->bs_xbridge) { + bridge_t *bridge = pcibr_soft->bs_base; + volatile unsigned *cmd_regp; + unsigned cmd_reg; + unsigned s; + + pcibr_dmamap->bd_flags |= PCIBR_DMAMAP_SSRAM; + + s = pcibr_lock(pcibr_soft); + cmd_regp = &(bridge-> + b_type0_cfg_dev[slot]. + l[PCI_CFG_COMMAND / 4]); + cmd_reg = *cmd_regp; + pcibr_soft->bs_slot[slot].bss_cmd_pointer = cmd_regp; + pcibr_soft->bs_slot[slot].bss_cmd_shadow = cmd_reg; + pcibr_unlock(pcibr_soft, s); + } + return pcibr_dmamap; + } +#if PCIBR_ATE_DEBUG + printk("pcibr_dmamap_alloc: unable to use PMU\n"); +#endif + pcibr_ate_free(pcibr_soft, ate_index, ate_count); + } + /* total failure: sorry, you just can't + * get from here to there that way. + */ +#if PCIBR_ATE_DEBUG + printk("pcibr_dmamap_alloc: complete failure.\n"); +#endif + xtalk_dmamap_free(xtalk_dmamap); + DEL(pcibr_dmamap); + return 0; +} + +/*ARGSUSED */ +void +pcibr_dmamap_free(pcibr_dmamap_t pcibr_dmamap) +{ + pcibr_soft_t pcibr_soft = pcibr_dmamap->bd_soft; + pciio_slot_t slot = pcibr_dmamap->bd_slot; + +#ifdef IRIX + unsigned flags = pcibr_dmamap->bd_flags; +#endif + + /* Make sure that bss_ext_ates_active + * is properly kept up to date. + */ +#ifdef IRIX + if (PCIBR_DMAMAP_BUSY & flags) + if (PCIBR_DMAMAP_SSRAM & flags) + atomicAddInt(&(pcibr_soft-> + bs_slot[slot]. + bss_ext_ates_active), -1); +#endif + + xtalk_dmamap_free(pcibr_dmamap->bd_xtalk); + + if (pcibr_dmamap->bd_flags & PCIIO_DMA_A64) { + pcibr_release_device(pcibr_soft, slot, BRIDGE_DEV_D64_BITS); + } + if (pcibr_dmamap->bd_ate_count) { + pcibr_ate_free(pcibr_dmamap->bd_soft, + pcibr_dmamap->bd_ate_index, + pcibr_dmamap->bd_ate_count); + pcibr_release_device(pcibr_soft, slot, BRIDGE_DEV_PMU_BITS); + } + DEL(pcibr_dmamap); +} + +/* + * Setup an Address Translation Entry as specified. Use either the Bridge + * internal maps or the external map RAM, as appropriate. + */ +LOCAL bridge_ate_p +pcibr_ate_addr(pcibr_soft_t pcibr_soft, + int ate_index) +{ + bridge_t *bridge = pcibr_soft->bs_base; + + return (ate_index < pcibr_soft->bs_int_ate_size) + ? &(bridge->b_int_ate_ram[ate_index].wr) + : &(bridge->b_ext_ate_ram[ate_index]); +} + +/* + * pcibr_addr_xio_to_pci: given a PIO range, hand + * back the corresponding base PCI MEM address; + * this is used to short-circuit DMA requests that + * loop back onto this PCI bus. + */ +LOCAL iopaddr_t +pcibr_addr_xio_to_pci(pcibr_soft_t soft, + iopaddr_t xio_addr, + size_t req_size) +{ + iopaddr_t xio_lim = xio_addr + req_size - 1; + iopaddr_t pci_addr; + pciio_slot_t slot; + + if ((xio_addr >= BRIDGE_PCI_MEM32_BASE) && + (xio_lim <= BRIDGE_PCI_MEM32_LIMIT)) { + pci_addr = xio_addr - BRIDGE_PCI_MEM32_BASE; + return pci_addr; + } + if ((xio_addr >= BRIDGE_PCI_MEM64_BASE) && + (xio_lim <= BRIDGE_PCI_MEM64_LIMIT)) { + pci_addr = xio_addr - BRIDGE_PCI_MEM64_BASE; + return pci_addr; + } + for (slot = 0; slot < 8; ++slot) + if ((xio_addr >= BRIDGE_DEVIO(slot)) && + (xio_lim < BRIDGE_DEVIO(slot + 1))) { + bridgereg_t dev; + + dev = soft->bs_slot[slot].bss_device; + pci_addr = dev & BRIDGE_DEV_OFF_MASK; + pci_addr <<= BRIDGE_DEV_OFF_ADDR_SHFT; + pci_addr += xio_addr - BRIDGE_DEVIO(slot); + return (dev & BRIDGE_DEV_DEV_IO_MEM) ? pci_addr : PCI_NOWHERE; + } + return 0; +} + +/* We are starting to get more complexity + * surrounding writing ATEs, so pull + * the writing code into this new function. + * XXX mail ranga@engr for IP27 prom! + */ + +#if PCIBR_FREEZE_TIME +#define ATE_FREEZE() s = ate_freeze(pcibr_dmamap, &freeze_time, cmd_regs) +#else +#define ATE_FREEZE() s = ate_freeze(pcibr_dmamap, cmd_regs) +#endif + +LOCAL unsigned +ate_freeze(pcibr_dmamap_t pcibr_dmamap, +#if PCIBR_FREEZE_TIME + unsigned *freeze_time_ptr, +#endif + unsigned *cmd_regs) +{ + pcibr_soft_t pcibr_soft = pcibr_dmamap->bd_soft; +#ifdef IRIX + int dma_slot = pcibr_dmamap->bd_slot; +#endif + int ext_ates = pcibr_dmamap->bd_flags & PCIBR_DMAMAP_SSRAM; + int slot; + + unsigned s; + unsigned cmd_reg; + volatile unsigned *cmd_lwa; + unsigned cmd_lwd; + + if (!ext_ates) + return 0; + + /* Bridge Hardware Bug WAR #484930: + * Bridge can't handle updating External ATEs + * while DMA is occuring that uses External ATEs, + * even if the particular ATEs involved are disjoint. + */ + + /* need to prevent anyone else from + * unfreezing the grant while we + * are working; also need to prevent + * this thread from being interrupted + * to keep PCI grant freeze time + * at an absolute minimum. + */ + s = pcibr_lock(pcibr_soft); + +#ifdef IRIX + /* just in case pcibr_dmamap_done was not called */ + if (pcibr_dmamap->bd_flags & PCIBR_DMAMAP_BUSY) { + pcibr_dmamap->bd_flags &= ~PCIBR_DMAMAP_BUSY; + if (pcibr_dmamap->bd_flags & PCIBR_DMAMAP_SSRAM) + atomicAddInt(&(pcibr_soft-> + bs_slot[dma_slot]. + bss_ext_ates_active), -1); + xtalk_dmamap_done(pcibr_dmamap->bd_xtalk); + } +#endif +#if PCIBR_FREEZE_TIME + *freeze_time_ptr = get_timestamp(); +#endif + + cmd_lwa = 0; + for (slot = 0; slot < 8; ++slot) + if (pcibr_soft-> + bs_slot[slot]. + bss_ext_ates_active) { + + cmd_reg = pcibr_soft-> + bs_slot[slot]. + bss_cmd_shadow; + if (cmd_reg & PCI_CMD_BUS_MASTER) { + cmd_lwa = pcibr_soft-> + bs_slot[slot]. + bss_cmd_pointer; + cmd_lwd = cmd_reg ^ PCI_CMD_BUS_MASTER; + cmd_lwa[0] = cmd_lwd; + } + cmd_regs[slot] = cmd_reg; + } else + cmd_regs[slot] = 0; + + if (cmd_lwa) { + bridge_t *bridge = pcibr_soft->bs_base; + + /* Read the last master bit that has been cleared. This PIO read + * on the PCI bus is to ensure the completion of any DMAs that + * are due to bus requests issued by PCI devices before the + * clearing of master bits. + */ + cmd_lwa[0]; + + /* Flush all the write buffers in the bridge */ + for (slot = 0; slot < 8; ++slot) + if (pcibr_soft-> + bs_slot[slot]. + bss_ext_ates_active) { + /* Flush the write buffer associated with this + * PCI device which might be using dma map RAM. + */ + bridge->b_wr_req_buf[slot].reg; + } + } + return s; +} + +#define ATE_WRITE() ate_write(ate_ptr, ate_count, ate) + +LOCAL void +ate_write(bridge_ate_p ate_ptr, + int ate_count, + bridge_ate_t ate) +{ + while (ate_count-- > 0) { + *ate_ptr++ = ate; + ate += IOPGSIZE; + } +} + + +#if PCIBR_FREEZE_TIME +#define ATE_THAW() ate_thaw(pcibr_dmamap, ate_index, ate, ate_total, freeze_time, cmd_regs, s) +#else +#define ATE_THAW() ate_thaw(pcibr_dmamap, ate_index, cmd_regs, s) +#endif + +LOCAL void +ate_thaw(pcibr_dmamap_t pcibr_dmamap, + int ate_index, +#if PCIBR_FREEZE_TIME + bridge_ate_t ate, + int ate_total, + unsigned freeze_time_start, +#endif + unsigned *cmd_regs, + unsigned s) +{ + pcibr_soft_t pcibr_soft = pcibr_dmamap->bd_soft; +#ifdef IRIX + int dma_slot = pcibr_dmamap->bd_slot; +#endif + int slot; + bridge_t *bridge = pcibr_soft->bs_base; + int ext_ates = pcibr_dmamap->bd_flags & PCIBR_DMAMAP_SSRAM; + + unsigned cmd_reg; + +#if PCIBR_FREEZE_TIME + unsigned freeze_time; + static unsigned max_freeze_time = 0; + static unsigned max_ate_total; +#endif + + if (!ext_ates) + return; + + /* restore cmd regs */ + for (slot = 0; slot < 8; ++slot) + if ((cmd_reg = cmd_regs[slot]) & PCI_CMD_BUS_MASTER) + bridge->b_type0_cfg_dev[slot].l[PCI_CFG_COMMAND / 4] = cmd_reg; + + pcibr_dmamap->bd_flags |= PCIBR_DMAMAP_BUSY; +#ifdef IRIX + atomicAddInt(&(pcibr_soft-> + bs_slot[dma_slot]. + bss_ext_ates_active), 1); +#endif + +#if PCIBR_FREEZE_TIME + freeze_time = get_timestamp() - freeze_time_start; + + if ((max_freeze_time < freeze_time) || + (max_ate_total < ate_total)) { + if (max_freeze_time < freeze_time) + max_freeze_time = freeze_time; + if (max_ate_total < ate_total) + max_ate_total = ate_total; + pcibr_unlock(pcibr_soft, s); + printk("%s: pci freeze time %d usec for %d ATEs\n" + "\tfirst ate: %R\n", + pcibr_soft->bs_name, + freeze_time * 1000 / 1250, + ate_total, + ate, ate_bits); + } else +#endif + pcibr_unlock(pcibr_soft, s); +} + +/*ARGSUSED */ +iopaddr_t +pcibr_dmamap_addr(pcibr_dmamap_t pcibr_dmamap, + paddr_t paddr, + size_t req_size) +{ + pcibr_soft_t pcibr_soft; + iopaddr_t xio_addr; + xwidgetnum_t xio_port; + iopaddr_t pci_addr; + unsigned flags; + + ASSERT(pcibr_dmamap != NULL); + ASSERT(req_size > 0); + ASSERT(req_size <= pcibr_dmamap->bd_max_size); + + pcibr_soft = pcibr_dmamap->bd_soft; + + flags = pcibr_dmamap->bd_flags; + + xio_addr = xtalk_dmamap_addr(pcibr_dmamap->bd_xtalk, paddr, req_size); + if (XIO_PACKED(xio_addr)) { + xio_port = XIO_PORT(xio_addr); + xio_addr = XIO_ADDR(xio_addr); + } else + xio_port = pcibr_dmamap->bd_xio_port; + + /* If this DMA is to an addres that + * refers back to this Bridge chip, + * reduce it back to the correct + * PCI MEM address. + */ + if (xio_port == pcibr_soft->bs_xid) { + pci_addr = pcibr_addr_xio_to_pci(pcibr_soft, xio_addr, req_size); + } else if (flags & PCIIO_DMA_A64) { + /* A64 DMA: + * always use 64-bit direct mapping, + * which always works. + * Device(x) was set up during + * dmamap allocation. + */ + + /* attributes are already bundled up into bd_pci_addr. + */ + pci_addr = pcibr_dmamap->bd_pci_addr + | ((uint64_t) xio_port << PCI64_ATTR_TARG_SHFT) + | xio_addr; + + /* Bridge Hardware WAR #482836: + * If the transfer is not cache aligned + * and the Bridge Rev is <= B, force + * prefetch to be off. + */ + if (flags & PCIBR_NOPREFETCH) + pci_addr &= ~PCI64_ATTR_PREF; + +#if DEBUG && PCIBR_DMA_DEBUG + printk("pcibr_dmamap_addr (direct64):\n" + "\twanted paddr [0x%x..0x%x]\n" + "\tXIO port 0x%x offset 0x%x\n" + "\treturning PCI 0x%x\n", + paddr, paddr + req_size - 1, + xio_port, xio_addr, pci_addr); +#endif + } else if (flags & PCIIO_FIXED) { + /* A32 direct DMA: + * always use 32-bit direct mapping, + * which may fail. + * Device(x) was set up during + * dmamap allocation. + */ + + if (xio_port != pcibr_soft->bs_dir_xport) + pci_addr = 0; /* wrong DIDN */ + else if (xio_addr < pcibr_dmamap->bd_xio_addr) + pci_addr = 0; /* out of range */ + else if ((xio_addr + req_size) > + (pcibr_dmamap->bd_xio_addr + BRIDGE_DMA_DIRECT_SIZE)) + pci_addr = 0; /* out of range */ + else + pci_addr = pcibr_dmamap->bd_pci_addr + + xio_addr - pcibr_dmamap->bd_xio_addr; + +#if DEBUG && PCIBR_DMA_DEBUG + printk("pcibr_dmamap_addr (direct32):\n" + "\twanted paddr [0x%x..0x%x]\n" + "\tXIO port 0x%x offset 0x%x\n" + "\treturning PCI 0x%x\n", + paddr, paddr + req_size - 1, + xio_port, xio_addr, pci_addr); +#endif + } else { + bridge_t *bridge = pcibr_soft->bs_base; + iopaddr_t offset = IOPGOFF(xio_addr); + bridge_ate_t ate_proto = pcibr_dmamap->bd_ate_proto; + int ate_count = IOPG(offset + req_size - 1) + 1; + + int ate_index = pcibr_dmamap->bd_ate_index; + unsigned cmd_regs[8]; + unsigned s; + +#if PCIBR_FREEZE_TIME + int ate_total = ate_count; + unsigned freeze_time; +#endif + +#if PCIBR_ATE_DEBUG + bridge_ate_t ate_cmp; + bridge_ate_p ate_cptr; + unsigned ate_lo, ate_hi; + int ate_bad = 0; + int ate_rbc = 0; +#endif + bridge_ate_p ate_ptr = pcibr_dmamap->bd_ate_ptr; + bridge_ate_t ate; + + /* Bridge Hardware WAR #482836: + * If the transfer is not cache aligned + * and the Bridge Rev is <= B, force + * prefetch to be off. + */ + if (flags & PCIBR_NOPREFETCH) + ate_proto &= ~ATE_PREF; + + ate = ate_proto + | (xio_port << ATE_TIDSHIFT) + | (xio_addr - offset); + + pci_addr = pcibr_dmamap->bd_pci_addr + offset; + + /* Fill in our mapping registers + * with the appropriate xtalk data, + * and hand back the PCI address. + */ + + ASSERT(ate_count > 0); + if (ate_count <= pcibr_dmamap->bd_ate_count) { + ATE_FREEZE(); + ATE_WRITE(); + ATE_THAW(); + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ + } else { + /* The number of ATE's required is greater than the number + * allocated for this map. One way this can happen is if + * pcibr_dmamap_alloc() was called with the PCIBR_NO_ATE_ROUNDUP + * flag, and then when that map is used (right now), the + * target address tells us we really did need to roundup. + * The other possibility is that the map is just plain too + * small to handle the requested target area. + */ +#if PCIBR_ATE_DEBUG + PRINT_WARNING( "pcibr_dmamap_addr :\n" + "\twanted paddr [0x%x..0x%x]\n" + "\tate_count 0x%x bd_ate_count 0x%x\n" + "\tATE's required > number allocated\n", + paddr, paddr + req_size - 1, + ate_count, pcibr_dmamap->bd_ate_count); +#endif + pci_addr = 0; + } + + } + return pci_addr; +} + +/*ARGSUSED */ +alenlist_t +pcibr_dmamap_list(pcibr_dmamap_t pcibr_dmamap, + alenlist_t palenlist, + unsigned flags) +{ + pcibr_soft_t pcibr_soft; +#ifdef IRIX + bridge_t *bridge; +#else + bridge_t *bridge=NULL; +#endif + + unsigned al_flags = (flags & PCIIO_NOSLEEP) ? AL_NOSLEEP : 0; + int inplace = flags & PCIIO_INPLACE; + + alenlist_t pciio_alenlist = 0; + alenlist_t xtalk_alenlist; + size_t length; + iopaddr_t offset; + unsigned direct64; +#ifdef IRIX + int ate_index; + int ate_count; + int ate_total = 0; + bridge_ate_p ate_ptr; + bridge_ate_t ate_proto; +#else + int ate_index = 0; + int ate_count = 0; + int ate_total = 0; + bridge_ate_p ate_ptr = (bridge_ate_p)0; + bridge_ate_t ate_proto = (bridge_ate_t)0; +#endif + bridge_ate_t ate_prev; + bridge_ate_t ate; + alenaddr_t xio_addr; + xwidgetnum_t xio_port; + iopaddr_t pci_addr; + alenaddr_t new_addr; + + unsigned cmd_regs[8]; + unsigned s = 0; + +#if PCIBR_FREEZE_TIME + unsigned freeze_time; +#endif + int ate_freeze_done = 0; /* To pair ATE_THAW + * with an ATE_FREEZE + */ + + pcibr_soft = pcibr_dmamap->bd_soft; + + xtalk_alenlist = xtalk_dmamap_list(pcibr_dmamap->bd_xtalk, palenlist, + flags & DMAMAP_FLAGS); + if (!xtalk_alenlist) + goto fail; + + alenlist_cursor_init(xtalk_alenlist, 0, NULL); + + if (inplace) { + pciio_alenlist = xtalk_alenlist; + } else { + pciio_alenlist = alenlist_create(al_flags); + if (!pciio_alenlist) + goto fail; + } + + direct64 = pcibr_dmamap->bd_flags & PCIIO_DMA_A64; + if (!direct64) { + bridge = pcibr_soft->bs_base; + ate_ptr = pcibr_dmamap->bd_ate_ptr; + ate_index = pcibr_dmamap->bd_ate_index; + ate_proto = pcibr_dmamap->bd_ate_proto; + ATE_FREEZE(); + ate_freeze_done = 1; /* Remember that we need to do an ATE_THAW */ + } + pci_addr = pcibr_dmamap->bd_pci_addr; + + ate_prev = 0; /* matches no valid ATEs */ + while (ALENLIST_SUCCESS == + alenlist_get(xtalk_alenlist, NULL, 0, + &xio_addr, &length, al_flags)) { + if (XIO_PACKED(xio_addr)) { + xio_port = XIO_PORT(xio_addr); + xio_addr = XIO_ADDR(xio_addr); + } else + xio_port = pcibr_dmamap->bd_xio_port; + + if (xio_port == pcibr_soft->bs_xid) { + new_addr = pcibr_addr_xio_to_pci(pcibr_soft, xio_addr, length); + if (new_addr == PCI_NOWHERE) + goto fail; + } else if (direct64) { + new_addr = pci_addr | xio_addr + | ((uint64_t) xio_port << PCI64_ATTR_TARG_SHFT); + + /* Bridge Hardware WAR #482836: + * If the transfer is not cache aligned + * and the Bridge Rev is <= B, force + * prefetch to be off. + */ + if (flags & PCIBR_NOPREFETCH) + new_addr &= ~PCI64_ATTR_PREF; + + } else { + /* calculate the ate value for + * the first address. If it + * matches the previous + * ATE written (ie. we had + * multiple blocks in the + * same IOPG), then back up + * and reuse that ATE. + * + * We are NOT going to + * aggressively try to + * reuse any other ATEs. + */ + offset = IOPGOFF(xio_addr); + ate = ate_proto + | (xio_port << ATE_TIDSHIFT) + | (xio_addr - offset); + if (ate == ate_prev) { +#if PCIBR_ATE_DEBUG + printk("pcibr_dmamap_list: ATE share\n"); +#endif + ate_ptr--; + ate_index--; + pci_addr -= IOPGSIZE; + } + new_addr = pci_addr + offset; + + /* Fill in the hardware ATEs + * that contain this block. + */ + ate_count = IOPG(offset + length - 1) + 1; + ate_total += ate_count; + + /* Ensure that this map contains enough ATE's */ + if (ate_total > pcibr_dmamap->bd_ate_count) { +#if PCIBR_ATE_DEBUG + PRINT_WARNING( "pcibr_dmamap_list :\n" + "\twanted xio_addr [0x%x..0x%x]\n" + "\tate_total 0x%x bd_ate_count 0x%x\n" + "\tATE's required > number allocated\n", + xio_addr, xio_addr + length - 1, + ate_total, pcibr_dmamap->bd_ate_count); +#endif + goto fail; + } + + ATE_WRITE(); + + ate_index += ate_count; + ate_ptr += ate_count; + + ate_count <<= IOPFNSHIFT; + ate += ate_count; + pci_addr += ate_count; + } + + /* write the PCI DMA address + * out to the scatter-gather list. + */ + if (inplace) { + if (ALENLIST_SUCCESS != + alenlist_replace(pciio_alenlist, NULL, + &new_addr, &length, al_flags)) + goto fail; + } else { + if (ALENLIST_SUCCESS != + alenlist_append(pciio_alenlist, + new_addr, length, al_flags)) + goto fail; + } + } + if (!inplace) + alenlist_done(xtalk_alenlist); + + /* Reset the internal cursor of the alenlist to be returned back + * to the caller. + */ + alenlist_cursor_init(pciio_alenlist, 0, NULL); + + + /* In case an ATE_FREEZE was done do the ATE_THAW to unroll all the + * changes that ATE_FREEZE has done to implement the external SSRAM + * bug workaround. + */ + if (ate_freeze_done) { + ATE_THAW(); + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ + } + return pciio_alenlist; + + fail: + /* There are various points of failure after doing an ATE_FREEZE + * We need to do an ATE_THAW. Otherwise the ATEs are locked forever. + * The decision to do an ATE_THAW needs to be based on whether a + * an ATE_FREEZE was done before. + */ + if (ate_freeze_done) { + ATE_THAW(); + bridge->b_wid_tflush; + } + if (pciio_alenlist && !inplace) + alenlist_destroy(pciio_alenlist); + return 0; +} + +/*ARGSUSED */ +void +pcibr_dmamap_done(pcibr_dmamap_t pcibr_dmamap) +{ + /* + * We could go through and invalidate ATEs here; + * for performance reasons, we don't. + * We also don't enforce the strict alternation + * between _addr/_list and _done, but Hub does. + */ + +#ifdef IRIX + if (pcibr_dmamap->bd_flags & PCIBR_DMAMAP_BUSY) { + pcibr_dmamap->bd_flags &= ~PCIBR_DMAMAP_BUSY; + + if (pcibr_dmamap->bd_flags & PCIBR_DMAMAP_SSRAM) + atomicAddInt(&(pcibr_dmamap->bd_soft-> + bs_slot[pcibr_dmamap->bd_slot]. + bss_ext_ates_active), -1); + } +#endif + + xtalk_dmamap_done(pcibr_dmamap->bd_xtalk); +} + + +/* + * For each bridge, the DIR_OFF value in the Direct Mapping Register + * determines the PCI to Crosstalk memory mapping to be used for all + * 32-bit Direct Mapping memory accesses. This mapping can be to any + * node in the system. This function will return that compact node id. + */ + +/*ARGSUSED */ +cnodeid_t +pcibr_get_dmatrans_node(devfs_handle_t pconn_vhdl) +{ + + pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + + return(NASID_TO_COMPACT_NODEID(NASID_GET(pcibr_soft->bs_dir_xbase))); +} + +/*ARGSUSED */ +iopaddr_t +pcibr_dmatrans_addr(devfs_handle_t pconn_vhdl, + device_desc_t dev_desc, + paddr_t paddr, + size_t req_size, + unsigned flags) +{ + pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn; + pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info); + pcibr_soft_slot_t slotp = &pcibr_soft->bs_slot[pciio_slot]; + + xwidgetnum_t xio_port; + iopaddr_t xio_addr; + iopaddr_t pci_addr; + + int have_rrbs; + int min_rrbs; + + /* merge in forced flags */ + flags |= pcibr_soft->bs_dma_flags; + + xio_addr = xtalk_dmatrans_addr(xconn_vhdl, 0, paddr, req_size, + flags & DMAMAP_FLAGS); + + if (!xio_addr) { +#if PCIBR_DMA_DEBUG + printk("pcibr_dmatrans_addr:\n" + "\tpciio connection point %v\n" + "\txtalk connection point %v\n" + "\twanted paddr [0x%x..0x%x]\n" + "\txtalk_dmatrans_addr returned 0x%x\n", + pconn_vhdl, xconn_vhdl, + paddr, paddr + req_size - 1, + xio_addr); +#endif + return 0; + } + /* + * find which XIO port this goes to. + */ + if (XIO_PACKED(xio_addr)) { + if (xio_addr == XIO_NOWHERE) { +#if PCIBR_DMA_DEBUG + printk("pcibr_dmatrans_addr:\n" + "\tpciio connection point %v\n" + "\txtalk connection point %v\n" + "\twanted paddr [0x%x..0x%x]\n" + "\txtalk_dmatrans_addr returned 0x%x\n", + pconn_vhdl, xconn_vhdl, + paddr, paddr + req_size - 1, + xio_addr); +#endif + return 0; + } + xio_port = XIO_PORT(xio_addr); + xio_addr = XIO_ADDR(xio_addr); + + } else + xio_port = pcibr_soft->bs_mxid; + + /* + * If this DMA comes back to us, + * return the PCI MEM address on + * which it would land, or NULL + * if the target is something + * on bridge other than PCI MEM. + */ + if (xio_port == pcibr_soft->bs_xid) { + pci_addr = pcibr_addr_xio_to_pci(pcibr_soft, xio_addr, req_size); + return pci_addr; + } + /* If the caller can use A64, try to + * satisfy the request with the 64-bit + * direct map. This can fail if the + * configuration bits in Device(x) + * conflict with our flags. + */ + + if (flags & PCIIO_DMA_A64) { + pci_addr = slotp->bss_d64_base; + if (!(flags & PCIBR_VCHAN1)) + flags |= PCIBR_VCHAN0; + if ((pci_addr != PCIBR_D64_BASE_UNSET) && + (flags == slotp->bss_d64_flags)) { + + pci_addr |= xio_addr + | ((uint64_t) xio_port << PCI64_ATTR_TARG_SHFT); + +#if DEBUG && PCIBR_DMA_DEBUG +#if HWG_PERF_CHECK + if (xio_addr != 0x20000000) +#endif + printk("pcibr_dmatrans_addr: [reuse]\n" + "\tpciio connection point %v\n" + "\txtalk connection point %v\n" + "\twanted paddr [0x%x..0x%x]\n" + "\txtalk_dmatrans_addr returned 0x%x\n" + "\tdirect 64bit address is 0x%x\n", + pconn_vhdl, xconn_vhdl, + paddr, paddr + req_size - 1, + xio_addr, pci_addr); +#endif + return (pci_addr); + } + if (!pcibr_try_set_device(pcibr_soft, pciio_slot, flags, BRIDGE_DEV_D64_BITS)) { + pci_addr = pcibr_flags_to_d64(flags, pcibr_soft); + slotp->bss_d64_flags = flags; + slotp->bss_d64_base = pci_addr; + pci_addr |= xio_addr + | ((uint64_t) xio_port << PCI64_ATTR_TARG_SHFT); + + /* Make sure we have an RRB (or two). + */ + if (!(pcibr_soft->bs_rrb_fixed & (1 << pciio_slot))) { + if (flags & PCIBR_VCHAN1) + pciio_slot += PCIBR_RRB_SLOT_VIRTUAL; + have_rrbs = pcibr_soft->bs_rrb_valid[pciio_slot]; + if (have_rrbs < 2) { + if (pci_addr & PCI64_ATTR_PREF) + min_rrbs = 2; + else + min_rrbs = 1; + if (have_rrbs < min_rrbs) + do_pcibr_rrb_autoalloc(pcibr_soft, pciio_slot, min_rrbs - have_rrbs); + } + } +#if PCIBR_DMA_DEBUG +#if HWG_PERF_CHECK + if (xio_addr != 0x20000000) +#endif + printk("pcibr_dmatrans_addr:\n" + "\tpciio connection point %v\n" + "\txtalk connection point %v\n" + "\twanted paddr [0x%x..0x%x]\n" + "\txtalk_dmatrans_addr returned 0x%x\n" + "\tdirect 64bit address is 0x%x\n" + "\tnew flags: 0x%x\n", + pconn_vhdl, xconn_vhdl, + paddr, paddr + req_size - 1, + xio_addr, pci_addr, (uint64_t) flags); +#endif + return (pci_addr); + } + /* our flags conflict with Device(x). + */ + flags = flags + & ~PCIIO_DMA_A64 + & ~PCIBR_VCHAN0 + ; + +#if PCIBR_DMA_DEBUG + printk("pcibr_dmatrans_addr:\n" + "\tpciio connection point %v\n" + "\txtalk connection point %v\n" + "\twanted paddr [0x%x..0x%x]\n" + "\txtalk_dmatrans_addr returned 0x%x\n" + "\tUnable to set Device(x) bits for Direct-64\n", + pconn_vhdl, xconn_vhdl, + paddr, paddr + req_size - 1, + xio_addr); +#endif + } + /* Try to satisfy the request with the 32-bit direct + * map. This can fail if the configuration bits in + * Device(x) conflict with our flags, or if the + * target address is outside where DIR_OFF points. + */ + { + size_t map_size = 1ULL << 31; + iopaddr_t xio_base = pcibr_soft->bs_dir_xbase; + iopaddr_t offset = xio_addr - xio_base; + iopaddr_t endoff = req_size + offset; + + if ((req_size > map_size) || + (xio_addr < xio_base) || + (xio_port != pcibr_soft->bs_dir_xport) || + (endoff > map_size)) { +#if PCIBR_DMA_DEBUG + printk("pcibr_dmatrans_addr:\n" + "\tpciio connection point %v\n" + "\txtalk connection point %v\n" + "\twanted paddr [0x%x..0x%x]\n" + "\txtalk_dmatrans_addr returned 0x%x\n" + "\txio region outside direct32 target\n", + pconn_vhdl, xconn_vhdl, + paddr, paddr + req_size - 1, + xio_addr); +#endif + } else { + pci_addr = slotp->bss_d32_base; + if ((pci_addr != PCIBR_D32_BASE_UNSET) && + (flags == slotp->bss_d32_flags)) { + + pci_addr |= offset; + +#if DEBUG && PCIBR_DMA_DEBUG + printk("pcibr_dmatrans_addr: [reuse]\n" + "\tpciio connection point %v\n" + "\txtalk connection point %v\n" + "\twanted paddr [0x%x..0x%x]\n" + "\txtalk_dmatrans_addr returned 0x%x\n" + "\tmapped via direct32 offset 0x%x\n" + "\twill DMA via pci addr 0x%x\n", + pconn_vhdl, xconn_vhdl, + paddr, paddr + req_size - 1, + xio_addr, offset, pci_addr); +#endif + return (pci_addr); + } + if (!pcibr_try_set_device(pcibr_soft, pciio_slot, flags, BRIDGE_DEV_D32_BITS)) { + + pci_addr = PCI32_DIRECT_BASE; + slotp->bss_d32_flags = flags; + slotp->bss_d32_base = pci_addr; + pci_addr |= offset; + + /* Make sure we have an RRB (or two). + */ + if (!(pcibr_soft->bs_rrb_fixed & (1 << pciio_slot))) { + have_rrbs = pcibr_soft->bs_rrb_valid[pciio_slot]; + if (have_rrbs < 2) { + if (slotp->bss_device & BRIDGE_DEV_PREF) + min_rrbs = 2; + else + min_rrbs = 1; + if (have_rrbs < min_rrbs) + do_pcibr_rrb_autoalloc(pcibr_soft, pciio_slot, min_rrbs - have_rrbs); + } + } +#if PCIBR_DMA_DEBUG +#if HWG_PERF_CHECK + if (xio_addr != 0x20000000) +#endif + printk("pcibr_dmatrans_addr:\n" + "\tpciio connection point %v\n" + "\txtalk connection point %v\n" + "\twanted paddr [0x%x..0x%x]\n" + "\txtalk_dmatrans_addr returned 0x%x\n" + "\tmapped via direct32 offset 0x%x\n" + "\twill DMA via pci addr 0x%x\n" + "\tnew flags: 0x%x\n", + pconn_vhdl, xconn_vhdl, + paddr, paddr + req_size - 1, + xio_addr, offset, pci_addr, (uint64_t) flags); +#endif + return (pci_addr); + } + /* our flags conflict with Device(x). + */ +#if PCIBR_DMA_DEBUG + printk("pcibr_dmatrans_addr:\n" + "\tpciio connection point %v\n" + "\txtalk connection point %v\n" + "\twanted paddr [0x%x..0x%x]\n" + "\txtalk_dmatrans_addr returned 0x%x\n" + "\tUnable to set Device(x) bits for Direct-32\n", + pconn_vhdl, xconn_vhdl, + paddr, paddr + req_size - 1, + xio_addr); +#endif + } + } + +#if PCIBR_DMA_DEBUG + printk("pcibr_dmatrans_addr:\n" + "\tpciio connection point %v\n" + "\txtalk connection point %v\n" + "\twanted paddr [0x%x..0x%x]\n" + "\txtalk_dmatrans_addr returned 0x%x\n" + "\tno acceptable PCI address found or constructable\n", + pconn_vhdl, xconn_vhdl, + paddr, paddr + req_size - 1, + xio_addr); +#endif + + return 0; +} + +/*ARGSUSED */ +alenlist_t +pcibr_dmatrans_list(devfs_handle_t pconn_vhdl, + device_desc_t dev_desc, + alenlist_t palenlist, + unsigned flags) +{ + pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn; + pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info); + pcibr_soft_slot_t slotp = &pcibr_soft->bs_slot[pciio_slot]; + xwidgetnum_t xio_port; + + alenlist_t pciio_alenlist = 0; + alenlist_t xtalk_alenlist = 0; + + int inplace; + unsigned direct64; + unsigned al_flags; + + iopaddr_t xio_base; + alenaddr_t xio_addr; + size_t xio_size; + + size_t map_size; + iopaddr_t pci_base; + alenaddr_t pci_addr; + + unsigned relbits = 0; + + /* merge in forced flags */ + flags |= pcibr_soft->bs_dma_flags; + + inplace = flags & PCIIO_INPLACE; + direct64 = flags & PCIIO_DMA_A64; + al_flags = (flags & PCIIO_NOSLEEP) ? AL_NOSLEEP : 0; + + if (direct64) { + map_size = 1ull << 48; + xio_base = 0; + pci_base = slotp->bss_d64_base; + if ((pci_base != PCIBR_D64_BASE_UNSET) && + (flags == slotp->bss_d64_flags)) { + /* reuse previous base info */ + } else if (pcibr_try_set_device(pcibr_soft, pciio_slot, flags, BRIDGE_DEV_D64_BITS) < 0) { + /* DMA configuration conflict */ + goto fail; + } else { + relbits = BRIDGE_DEV_D64_BITS; + pci_base = + pcibr_flags_to_d64(flags, pcibr_soft); + } + } else { + xio_base = pcibr_soft->bs_dir_xbase; + map_size = 1ull << 31; + pci_base = slotp->bss_d32_base; + if ((pci_base != PCIBR_D32_BASE_UNSET) && + (flags == slotp->bss_d32_flags)) { + /* reuse previous base info */ + } else if (pcibr_try_set_device(pcibr_soft, pciio_slot, flags, BRIDGE_DEV_D32_BITS) < 0) { + /* DMA configuration conflict */ + goto fail; + } else { + relbits = BRIDGE_DEV_D32_BITS; + pci_base = PCI32_DIRECT_BASE; + } + } + + xtalk_alenlist = xtalk_dmatrans_list(xconn_vhdl, 0, palenlist, + flags & DMAMAP_FLAGS); + if (!xtalk_alenlist) + goto fail; + + alenlist_cursor_init(xtalk_alenlist, 0, NULL); + + if (inplace) { + pciio_alenlist = xtalk_alenlist; + } else { + pciio_alenlist = alenlist_create(al_flags); + if (!pciio_alenlist) + goto fail; + } + + while (ALENLIST_SUCCESS == + alenlist_get(xtalk_alenlist, NULL, 0, + &xio_addr, &xio_size, al_flags)) { + + /* + * find which XIO port this goes to. + */ + if (XIO_PACKED(xio_addr)) { + if (xio_addr == XIO_NOWHERE) { +#if PCIBR_DMA_DEBUG + printk("pcibr_dmatrans_addr:\n" + "\tpciio connection point %v\n" + "\txtalk connection point %v\n" + "\twanted paddr [0x%x..0x%x]\n" + "\txtalk_dmatrans_addr returned 0x%x\n", + pconn_vhdl, xconn_vhdl, + paddr, paddr + req_size - 1, + xio_addr); +#endif + return 0; + } + xio_port = XIO_PORT(xio_addr); + xio_addr = XIO_ADDR(xio_addr); + } else + xio_port = pcibr_soft->bs_mxid; + + /* + * If this DMA comes back to us, + * return the PCI MEM address on + * which it would land, or NULL + * if the target is something + * on bridge other than PCI MEM. + */ + if (xio_port == pcibr_soft->bs_xid) { + pci_addr = pcibr_addr_xio_to_pci(pcibr_soft, xio_addr, xio_size); +#ifdef IRIX + if (pci_addr == NULL) +#else + if ( (pci_addr == (alenaddr_t)NULL) ) +#endif + goto fail; + } else if (direct64) { + ASSERT(xio_port != 0); + pci_addr = pci_base | xio_addr + | ((uint64_t) xio_port << PCI64_ATTR_TARG_SHFT); + } else { + iopaddr_t offset = xio_addr - xio_base; + iopaddr_t endoff = xio_size + offset; + + if ((xio_size > map_size) || + (xio_addr < xio_base) || + (xio_port != pcibr_soft->bs_dir_xport) || + (endoff > map_size)) + goto fail; + + pci_addr = pci_base + (xio_addr - xio_base); + } + + /* write the PCI DMA address + * out to the scatter-gather list. + */ + if (inplace) { + if (ALENLIST_SUCCESS != + alenlist_replace(pciio_alenlist, NULL, + &pci_addr, &xio_size, al_flags)) + goto fail; + } else { + if (ALENLIST_SUCCESS != + alenlist_append(pciio_alenlist, + pci_addr, xio_size, al_flags)) + goto fail; + } + } + +#ifdef IRIX + if (relbits) +#else + if (relbits) { +#endif + if (direct64) { + slotp->bss_d64_flags = flags; + slotp->bss_d64_base = pci_base; + } else { + slotp->bss_d32_flags = flags; + slotp->bss_d32_base = pci_base; + } +#ifndef IRIX + } +#endif + if (!inplace) + alenlist_done(xtalk_alenlist); + + /* Reset the internal cursor of the alenlist to be returned back + * to the caller. + */ + alenlist_cursor_init(pciio_alenlist, 0, NULL); + return pciio_alenlist; + + fail: + if (relbits) + pcibr_release_device(pcibr_soft, pciio_slot, relbits); + if (pciio_alenlist && !inplace) + alenlist_destroy(pciio_alenlist); + return 0; +} + +void +pcibr_dmamap_drain(pcibr_dmamap_t map) +{ + xtalk_dmamap_drain(map->bd_xtalk); +} + +void +pcibr_dmaaddr_drain(devfs_handle_t pconn_vhdl, + paddr_t paddr, + size_t bytes) +{ + pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn; + + xtalk_dmaaddr_drain(xconn_vhdl, paddr, bytes); +} + +void +pcibr_dmalist_drain(devfs_handle_t pconn_vhdl, + alenlist_t list) +{ + pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn; + + xtalk_dmalist_drain(xconn_vhdl, list); +} + +/* + * Get the starting PCIbus address out of the given DMA map. + * This function is supposed to be used by a close friend of PCI bridge + * since it relies on the fact that the starting address of the map is fixed at + * the allocation time in the current implementation of PCI bridge. + */ +iopaddr_t +pcibr_dmamap_pciaddr_get(pcibr_dmamap_t pcibr_dmamap) +{ + return (pcibr_dmamap->bd_pci_addr); +} + +/* ===================================================================== + * INTERRUPT MANAGEMENT + */ + +static unsigned +pcibr_intr_bits(pciio_info_t info, + pciio_intr_line_t lines) +{ + pciio_slot_t slot = pciio_info_slot_get(info); + unsigned bbits = 0; + + /* + * Currently favored mapping from PCI + * slot number and INTA/B/C/D to Bridge + * PCI Interrupt Bit Number: + * + * SLOT A B C D + * 0 0 4 0 4 + * 1 1 5 1 5 + * 2 2 6 2 6 + * 3 3 7 3 7 + * 4 4 0 4 0 + * 5 5 1 5 1 + * 6 6 2 6 2 + * 7 7 3 7 3 + */ + + if (slot < 8) { + if (lines & (PCIIO_INTR_LINE_A| PCIIO_INTR_LINE_C)) + bbits |= 1 << slot; + if (lines & (PCIIO_INTR_LINE_B| PCIIO_INTR_LINE_D)) + bbits |= 1 << (slot ^ 4); + } + return bbits; +} + +#ifdef IRIX +/* Wrapper for pcibr interrupt threads. */ +static void +pcibr_intrd(pcibr_intr_t intr) +{ + /* Called on each restart */ + ASSERT(cpuid() == intr->bi_mustruncpu); + +#ifdef ITHREAD_LATENCY + xthread_update_latstats(intr->bi_tinfo->thd_latstats); +#endif /* ITHREAD_LATENCY */ + + ASSERT(intr->bi_func != NULL); + intr->bi_func(intr->bi_arg); /* Invoke the interrupt handler */ + + ipsema(&intr->bi_tinfo.thd_isync); /* Sleep 'till next interrupt */ + /* NOTREACHED */ +} + + +static void +pcibr_intrd_start(pcibr_intr_t intr) +{ + ASSERT(intr->bi_mustruncpu >= 0); + setmustrun(intr->bi_mustruncpu); + + xthread_set_func(KT_TO_XT(curthreadp), (xt_func_t *)pcibr_intrd, (void *)intr); + atomicSetInt(&intr->bi_tinfo.thd_flags, THD_INIT); + ipsema(&intr->bi_tinfo.thd_isync); /* Comes out in pcibr_intrd */ + /* NOTREACHED */ +} + + +static void +pcibr_thread_setup(pcibr_intr_t intr, int bridge_levels, ilvl_t intr_swlevel) +{ + char thread_name[32]; + + sprintf(thread_name, "pcibr_intrd[0x%x]", bridge_levels); + + /* XXX need to adjust priority whenever an interrupt is connected */ + atomicSetInt(&intr->bi_tinfo.thd_flags, THD_ISTHREAD | THD_REG); + xthread_setup(thread_name, intr_swlevel, &intr->bi_tinfo, + (xt_func_t *)pcibr_intrd_start, + (void *)intr); +} +#endif /* IRIX */ + + + +/*ARGSUSED */ +pcibr_intr_t +pcibr_intr_alloc(devfs_handle_t pconn_vhdl, + device_desc_t dev_desc, + pciio_intr_line_t lines, + devfs_handle_t owner_dev) +{ + pcibr_info_t pcibr_info = pcibr_info_get(pconn_vhdl); + pciio_slot_t pciio_slot = pcibr_info->f_slot; + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pcibr_info->f_mfast; + devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn; + bridge_t *bridge = pcibr_soft->bs_base; + int is_threaded; + int thread_swlevel; + + xtalk_intr_t *xtalk_intr_p; + pcibr_intr_t *pcibr_intr_p; + pcibr_intr_list_t *intr_list_p; + pcibr_intr_wrap_t *intr_wrap_p; + + unsigned pcibr_int_bits; + unsigned pcibr_int_bit; + xtalk_intr_t xtalk_intr = (xtalk_intr_t)0; + hub_intr_t hub_intr; + pcibr_intr_t pcibr_intr; + pcibr_intr_list_t intr_entry; + pcibr_intr_list_t intr_list; + pcibr_intr_wrap_t intr_wrap; + bridgereg_t int_dev; + +#if DEBUG && INTR_DEBUG + printk("%v: pcibr_intr_alloc\n" + "%v:%s%s%s%s%s\n", + owner_dev, pconn_vhdl, + !(lines & 15) ? " No INTs?" : "", + lines & 1 ? " INTA" : "", + lines & 2 ? " INTB" : "", + lines & 4 ? " INTC" : "", + lines & 8 ? " INTD" : ""); +#endif + + NEW(pcibr_intr); + if (!pcibr_intr) + return NULL; + + if (dev_desc) { + is_threaded = !(device_desc_flags_get(dev_desc) & D_INTR_NOTHREAD); + if (is_threaded) + thread_swlevel = device_desc_intr_swlevel_get(dev_desc); + } else { + extern int default_intr_pri; + + is_threaded = 1; /* PCI interrupts are threaded, by default */ + thread_swlevel = default_intr_pri; + } + + pcibr_intr->bi_dev = pconn_vhdl; + pcibr_intr->bi_lines = lines; + pcibr_intr->bi_soft = pcibr_soft; + pcibr_intr->bi_ibits = 0; /* bits will be added below */ + pcibr_intr->bi_func = 0; /* unset until connect */ + pcibr_intr->bi_arg = 0; /* unset until connect */ + pcibr_intr->bi_flags = is_threaded ? 0 : PCIIO_INTR_NOTHREAD; + pcibr_intr->bi_mustruncpu = CPU_NONE; + + pcibr_int_bits = pcibr_soft->bs_intr_bits((pciio_info_t)pcibr_info, lines); + + + /* + * For each PCI interrupt line requested, figure + * out which Bridge PCI Interrupt Line it maps + * to, and make sure there are xtalk resources + * allocated for it. + */ +#if DEBUG && INTR_DEBUG + printk("pcibr_int_bits: 0x%X\n", pcibr_int_bits); +#endif + for (pcibr_int_bit = 0; pcibr_int_bit < 8; pcibr_int_bit ++) { + if (pcibr_int_bits & (1 << pcibr_int_bit)) { + xtalk_intr_p = &pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr; + + xtalk_intr = *xtalk_intr_p; + + if (xtalk_intr == NULL) { + /* + * This xtalk_intr_alloc is constrained for two reasons: + * 1) Normal interrupts and error interrupts need to be delivered + * through a single xtalk target widget so that there aren't any + * ordering problems with DMA, completion interrupts, and error + * interrupts. (Use of xconn_vhdl forces this.) + * + * 2) On IP35, addressing constraints on IP35 and Bridge force + * us to use a single PI number for all interrupts from a + * single Bridge. (IP35-specific code forces this, and we + * verify in pcibr_setwidint.) + */ + xtalk_intr = xtalk_intr_alloc(xconn_vhdl, dev_desc, owner_dev); +#if DEBUG && INTR_DEBUG + printk("%v: xtalk_intr=0x%X\n", xconn_vhdl, xtalk_intr); +#endif + + /* both an assert and a runtime check on this: + * we need to check in non-DEBUG kernels, and + * the ASSERT gets us more information when + * we use DEBUG kernels. + */ + ASSERT(xtalk_intr != NULL); + if (xtalk_intr == NULL) { + /* it is quite possible that our + * xtalk_intr_alloc failed because + * someone else got there first, + * and we can find their results + * in xtalk_intr_p. + */ + if (!*xtalk_intr_p) { +#ifdef SUPPORT_PRINTING_V_FORMAT + PRINT_ALERT( + "pcibr_intr_alloc %v: unable to get xtalk interrupt resources", + xconn_vhdl); +#endif + /* yes, we leak resources here. */ + return 0; + } + } else if (compare_and_swap_ptr((void **) xtalk_intr_p, NULL, xtalk_intr)) { + /* + * now tell the bridge which slot is + * using this interrupt line. + */ + int_dev = bridge->b_int_device; + int_dev &= ~BRIDGE_INT_DEV_MASK(pcibr_int_bit); + int_dev |= pciio_slot << BRIDGE_INT_DEV_SHFT(pcibr_int_bit); + bridge->b_int_device = int_dev; /* XXXMP */ + +#if DEBUG && INTR_DEBUG + printk("%v: bridge intr bit %d clears my wrb\n", + pconn_vhdl, pcibr_int_bit); +#endif + } else { + /* someone else got one allocated first; + * free the one we just created, and + * retrieve the one they allocated. + */ + xtalk_intr_free(xtalk_intr); + xtalk_intr = *xtalk_intr_p; +#if PARANOID + /* once xtalk_intr is set, we never clear it, + * so if the CAS fails above, this condition + * can "never happen" ... + */ + if (!xtalk_intr) { + PRINT_ALERT( + "pcibr_intr_alloc %v: unable to set xtalk interrupt resources", + xconn_vhdl); + /* yes, we leak resources here. */ + return 0; + } +#endif + } + } + + /* + * For threaded drivers, set the interrupt thread to run wherever + * the interrupt is targeted. + */ +#ifdef notyet + if (is_threaded) { + cpuid_t old_mustrun = pcibr_intr->bi_mustruncpu; + pcibr_intr->bi_mustruncpu = cpuvertex_to_cpuid(xtalk_intr_cpu_get(xtalk_intr)); + ASSERT(pcibr_intr->bi_mustruncpu >= 0); + + /* + * This is possible, but very unlikely: It means that 2 (or more) interrupts + * originating on a single Bridge and used by a single device were unable to + * find sufficient xtalk interrupt resources that would allow them all to be + * handled by the same CPU. If someone tries to target lots of interrupts to + * a single CPU, we might hit this case. Things should still operate correctly, + * but it's a sub-optimal configuration. + */ + if ((old_mustrun != CPU_NONE) && (old_mustrun != pcibr_intr->bi_mustruncpu)) { +#ifdef SUPPORT_PRINTING_V_FORMAT + PRINT_WARNING( "Conflict on where to schedule interrupts for %v\n", pconn_vhdl); +#endif + PRINT_WARNING( "(on cpu %d or on cpu %d)\n", old_mustrun, pcibr_intr->bi_mustruncpu); + } + } +#endif + + pcibr_intr->bi_ibits |= 1 << pcibr_int_bit; + + NEW(intr_entry); + intr_entry->il_next = NULL; + intr_entry->il_intr = pcibr_intr; + intr_entry->il_wrbf = &(bridge->b_wr_req_buf[pciio_slot].reg); + + intr_list_p = &pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_list; + if (compare_and_swap_ptr((void **) intr_list_p, NULL, intr_entry)) { + /* we are the first interrupt on this bridge bit. + */ +#if DEBUG && INTR_DEBUG + printk("%v INT 0x%x (bridge bit %d) allocated [FIRST]\n", + pconn_vhdl, pcibr_int_bits, pcibr_int_bit); +#endif + continue; + } + intr_list = *intr_list_p; + pcibr_intr_p = &intr_list->il_intr; + if (compare_and_swap_ptr((void **) pcibr_intr_p, NULL, pcibr_intr)) { + /* first entry on list was erased, + * and we replaced it, so we + * don't need our intr_entry. + */ + DEL(intr_entry); +#if DEBUG && INTR_DEBUG + printk("%v INT 0x%x (bridge bit %d) replaces erased first\n", + pconn_vhdl, pcibr_int_bits, pcibr_int_bit); +#endif + continue; + } + intr_list_p = &intr_list->il_next; + if (compare_and_swap_ptr((void **) intr_list_p, NULL, intr_entry)) { + /* we are the new second interrupt on this bit. + * switch to local wrapper. + */ +#if DEBUG && INTR_DEBUG + printk("%v INT 0x%x (bridge bit %d) is new SECOND\n", + pconn_vhdl, pcibr_int_bits, pcibr_int_bit); +#endif + NEW(intr_wrap); + intr_wrap->iw_soft = pcibr_soft; + intr_wrap->iw_stat = &(bridge->b_int_status); + intr_wrap->iw_intr = 1 << pcibr_int_bit; + intr_wrap->iw_list = intr_list; + intr_wrap_p = &pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap; + if (!compare_and_swap_ptr((void **) intr_wrap_p, NULL, intr_wrap)) { + /* someone else set up the wrapper. + */ + DEL(intr_wrap); + continue; +#if DEBUG && INTR_DEBUG + } else { + printk("%v bridge bit %d wrapper state created\n", + pconn_vhdl, pcibr_int_bit); +#endif + } + continue; + } + while (1) { + pcibr_intr_p = &intr_list->il_intr; + if (compare_and_swap_ptr((void **) pcibr_intr_p, NULL, pcibr_intr)) { + /* an entry on list was erased, + * and we replaced it, so we + * don't need our intr_entry. + */ + DEL(intr_entry); +#if DEBUG && INTR_DEBUG + printk("%v INT 0x%x (bridge bit %d) replaces erased Nth\n", + pconn_vhdl, pcibr_int_bits, pcibr_int_bit); +#endif + break; + } + intr_list_p = &intr_list->il_next; + if (compare_and_swap_ptr((void **) intr_list_p, NULL, intr_entry)) { + /* entry appended to share list + */ +#if DEBUG && INTR_DEBUG + printk("%v INT 0x%x (bridge bit %d) is new Nth\n", + pconn_vhdl, pcibr_int_bits, pcibr_int_bit); +#endif + break; + } + /* step to next record in chain + */ + intr_list = *intr_list_p; + } + } + } + +#ifdef IRIX + if (is_threaded) { + /* Set pcibr_intr->bi_tinfo */ + pcibr_thread_setup(pcibr_intr, pcibr_int_bits, thread_swlevel); + ASSERT(!(pcibr_intr->bi_flags & PCIIO_INTR_CONNECTED)); + } +#endif + +#if DEBUG && INTR_DEBUG + printk("%v pcibr_intr_alloc complete\n", pconn_vhdl); +#endif + hub_intr = (hub_intr_t)xtalk_intr; + pcibr_intr->bi_irq = hub_intr->i_bit; + pcibr_intr->bi_cpu = hub_intr->i_cpuid; + return pcibr_intr; +} + +/*ARGSUSED */ +void +pcibr_intr_free(pcibr_intr_t pcibr_intr) +{ + unsigned pcibr_int_bits = pcibr_intr->bi_ibits; + pcibr_soft_t pcibr_soft = pcibr_intr->bi_soft; + unsigned pcibr_int_bit; + pcibr_intr_list_t intr_list; + pcibr_intr_wrap_t intr_wrap; + xtalk_intr_t *xtalk_intrp; + + for (pcibr_int_bit = 0; pcibr_int_bit < 8; pcibr_int_bit++) { + if (pcibr_int_bits & (1 << pcibr_int_bit)) { + for (intr_list = + pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_list; + intr_list != NULL; + intr_list = intr_list->il_next) + if (compare_and_swap_ptr((void **) &intr_list->il_intr, + pcibr_intr, + NULL)) { +#if DEBUG && INTR_DEBUG + printk("%s: cleared a handler from bit %d\n", + pcibr_soft->bs_name, pcibr_int_bit); +#endif + } + /* If this interrupt line is not being shared between multiple + * devices release the xtalk interrupt resources. + */ + intr_wrap = + pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap; + xtalk_intrp = &pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr; + if ((intr_wrap == NULL) && (*xtalk_intrp)) { + + bridge_t *bridge = pcibr_soft->bs_base; + bridgereg_t int_dev; + + xtalk_intr_free(*xtalk_intrp); + *xtalk_intrp = 0; + + /* Clear the PCI device interrupt to bridge interrupt pin + * mapping. + */ + int_dev = bridge->b_int_device; + int_dev &= ~BRIDGE_INT_DEV_MASK(pcibr_int_bit); + bridge->b_int_device = int_dev; + + } + } + } + DEL(pcibr_intr); +} + +LOCAL void +pcibr_setpciint(xtalk_intr_t xtalk_intr) +{ + iopaddr_t addr = xtalk_intr_addr_get(xtalk_intr); + xtalk_intr_vector_t vect = xtalk_intr_vector_get(xtalk_intr); + bridgereg_t *int_addr = (bridgereg_t *) + xtalk_intr_sfarg_get(xtalk_intr); + + *int_addr = ((BRIDGE_INT_ADDR_HOST & (addr >> 30)) | + (BRIDGE_INT_ADDR_FLD & vect)); +} + +/*ARGSUSED */ +int +pcibr_intr_connect(pcibr_intr_t pcibr_intr, + intr_func_t intr_func, + intr_arg_t intr_arg, + void *thread) +{ + pcibr_soft_t pcibr_soft = pcibr_intr->bi_soft; + bridge_t *bridge = pcibr_soft->bs_base; + unsigned pcibr_int_bits = pcibr_intr->bi_ibits; + unsigned pcibr_int_bit; + bridgereg_t b_int_enable; + unsigned s; + + if (pcibr_intr == NULL) + return -1; + +#if DEBUG && INTR_DEBUG + printk("%v: pcibr_intr_connect 0x%X(0x%X)\n", + pcibr_intr->bi_dev, intr_func, intr_arg); +#endif + + pcibr_intr->bi_func = intr_func; + pcibr_intr->bi_arg = intr_arg; + *((volatile unsigned *)&pcibr_intr->bi_flags) |= PCIIO_INTR_CONNECTED; + + /* + * For each PCI interrupt line requested, figure + * out which Bridge PCI Interrupt Line it maps + * to, and make sure there are xtalk resources + * allocated for it. + */ + for (pcibr_int_bit = 0; pcibr_int_bit < 8; pcibr_int_bit++) + if (pcibr_int_bits & (1 << pcibr_int_bit)) { + pcibr_intr_wrap_t intr_wrap; + xtalk_intr_t xtalk_intr; + int *setptr; + + xtalk_intr = pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr; + + /* if we have no wrap structure, + * tell xtalk to deliver the interrupt + * directly to the client. + */ + intr_wrap = pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap; + if (intr_wrap == NULL) { + xtalk_intr_connect(xtalk_intr, + (intr_func_t) intr_func, + (intr_arg_t) intr_arg, + (xtalk_intr_setfunc_t) pcibr_setpciint, + (void *) &(bridge->b_int_addr[pcibr_int_bit].addr), + thread); +#if DEBUG && INTR_DEBUG + printk("%v bridge bit %d routed by xtalk\n", + pcibr_intr->bi_dev, pcibr_int_bit); +#endif + continue; + } + + setptr = &pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_wrap_set; + if (*setptr) + continue; + + + /* We have a wrap structure, so we're sharing a Bridge interrupt level */ + + xtalk_intr_disconnect(xtalk_intr); /* Disconnect old interrupt */ + + /* + If the existing xtalk_intr was allocated without the NOTHREAD flag, + we need to allocate a new one that's NOTHREAD, and connect to the + new one. pcibr_intr_list_func expects to run at interrupt level + rather than in a thread. With today's devices, this can't happen, + so let's punt on writing the code till we need it (probably never). + Instead, just ASSERT that we're a NOTHREAD xtalk_intr. + */ +#ifdef IRIX + ASSERT_ALWAYS(!(pcibr_intr->bi_flags & PCIIO_INTR_NOTHREAD) || + xtalk_intr_flags_get(xtalk_intr) & XTALK_INTR_NOTHREAD); +#endif + + /* Use the wrapper dispatch function to handle shared Bridge interrupts */ + xtalk_intr_connect(xtalk_intr, + pcibr_intr_list_func, + (intr_arg_t) intr_wrap, + (xtalk_intr_setfunc_t) pcibr_setpciint, + (void *) &(bridge->b_int_addr[pcibr_int_bit].addr), + 0); + *setptr = 1; + +#if DEBUG && INTR_DEBUG + printk("%v bridge bit %d wrapper connected\n", + pcibr_intr->bi_dev, pcibr_int_bit); +#endif + } + s = pcibr_lock(pcibr_soft); + b_int_enable = bridge->b_int_enable; + b_int_enable |= pcibr_int_bits; + bridge->b_int_enable = b_int_enable; + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ + pcibr_unlock(pcibr_soft, s); + + return 0; +} + +/*ARGSUSED */ +void +pcibr_intr_disconnect(pcibr_intr_t pcibr_intr) +{ + pcibr_soft_t pcibr_soft = pcibr_intr->bi_soft; + bridge_t *bridge = pcibr_soft->bs_base; + unsigned pcibr_int_bits = pcibr_intr->bi_ibits; + unsigned pcibr_int_bit; + pcibr_intr_wrap_t intr_wrap; + bridgereg_t b_int_enable; + unsigned s; + + /* Stop calling the function. Now. + */ + *((volatile unsigned *)&pcibr_intr->bi_flags) &= ~PCIIO_INTR_CONNECTED; + pcibr_intr->bi_func = 0; + pcibr_intr->bi_arg = 0; + /* + * For each PCI interrupt line requested, figure + * out which Bridge PCI Interrupt Line it maps + * to, and disconnect the interrupt. + */ + + /* don't disable interrupts for lines that + * are shared between devices. + */ + for (pcibr_int_bit = 0; pcibr_int_bit < 8; pcibr_int_bit++) + if ((pcibr_int_bits & (1 << pcibr_int_bit)) && + (pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_wrap_set)) + pcibr_int_bits &= ~(1 << pcibr_int_bit); + if (!pcibr_int_bits) + return; + + s = pcibr_lock(pcibr_soft); + b_int_enable = bridge->b_int_enable; + b_int_enable &= ~pcibr_int_bits; + bridge->b_int_enable = b_int_enable; + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ + pcibr_unlock(pcibr_soft, s); + + for (pcibr_int_bit = 0; pcibr_int_bit < 8; pcibr_int_bit++) + if (pcibr_int_bits & (1 << pcibr_int_bit)) { + /* if we have set up the share wrapper, + * do not disconnect it. + */ + if (pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_wrap_set) + continue; + + xtalk_intr_disconnect(pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr); + + /* if we have a share wrapper state, + * connect us up; this closes the hole + * where the connection of the wrapper + * was in progress as we disconnected. + */ + intr_wrap = pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap; + if (intr_wrap == NULL) + continue; + + + xtalk_intr_connect(pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr, + pcibr_intr_list_func, + (intr_arg_t) intr_wrap, + (xtalk_intr_setfunc_t) pcibr_setpciint, + (void *) &(bridge->b_int_addr[pcibr_int_bit].addr), + 0); + } +} + +/*ARGSUSED */ +devfs_handle_t +pcibr_intr_cpu_get(pcibr_intr_t pcibr_intr) +{ + pcibr_soft_t pcibr_soft = pcibr_intr->bi_soft; + unsigned pcibr_int_bits = pcibr_intr->bi_ibits; + unsigned pcibr_int_bit; + + for (pcibr_int_bit = 0; pcibr_int_bit < 8; pcibr_int_bit++) + if (pcibr_int_bits & (1 << pcibr_int_bit)) + return xtalk_intr_cpu_get(pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr); + return 0; +} + +/* ===================================================================== + * INTERRUPT HANDLING + */ +LOCAL void +pcibr_clearwidint(bridge_t *bridge) +{ + bridge->b_wid_int_upper = 0; + bridge->b_wid_int_lower = 0; +} + + +LOCAL void +pcibr_setwidint(xtalk_intr_t intr) +{ + xwidgetnum_t targ = xtalk_intr_target_get(intr); + iopaddr_t addr = xtalk_intr_addr_get(intr); + xtalk_intr_vector_t vect = xtalk_intr_vector_get(intr); + widgetreg_t NEW_b_wid_int_upper, NEW_b_wid_int_lower; + widgetreg_t OLD_b_wid_int_upper, OLD_b_wid_int_lower; + + bridge_t *bridge = (bridge_t *)xtalk_intr_sfarg_get(intr); + + NEW_b_wid_int_upper = ( (0x000F0000 & (targ << 16)) | + XTALK_ADDR_TO_UPPER(addr)); + NEW_b_wid_int_lower = XTALK_ADDR_TO_LOWER(addr); + + OLD_b_wid_int_upper = bridge->b_wid_int_upper; + OLD_b_wid_int_lower = bridge->b_wid_int_lower; + +#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) + /* Verify that all interrupts from this Bridge are using a single PI */ + if ((OLD_b_wid_int_upper != 0) && (OLD_b_wid_int_lower != 0)) { + /* + * Once set, these registers shouldn't change; they should + * be set multiple times with the same values. + * + * If we're attempting to change these registers, it means + * that our heuristics for allocating interrupts in a way + * appropriate for IP35 have failed, and the admin needs to + * explicitly direct some interrupts (or we need to make the + * heuristics more clever). + * + * In practice, we hope this doesn't happen very often, if + * at all. + */ + if ((OLD_b_wid_int_upper != NEW_b_wid_int_upper) || + (OLD_b_wid_int_lower != NEW_b_wid_int_lower)) { + PRINT_WARNING("Interrupt allocation is too complex.\n"); + PRINT_WARNING("Use explicit administrative interrupt targetting.\n"); + PRINT_WARNING("bridge=0x%lx targ=0x%x\n", (unsigned long)bridge, targ); + PRINT_WARNING("NEW=0x%x/0x%x OLD=0x%x/0x%x\n", + NEW_b_wid_int_upper, NEW_b_wid_int_lower, + OLD_b_wid_int_upper, OLD_b_wid_int_lower); + PRINT_PANIC("PCI Bridge interrupt targetting error\n"); + } + } +#endif /* CONFIG_SGI_IP35 */ + + bridge->b_wid_int_upper = NEW_b_wid_int_upper; + bridge->b_wid_int_lower = NEW_b_wid_int_lower; + bridge->b_int_host_err = vect; +} + +/* + * pcibr_intr_preset: called during mlreset time + * if the platform specific code needs to route + * one of the Bridge's xtalk interrupts before the + * xtalk infrastructure is available. + */ +void +pcibr_xintr_preset(void *which_widget, + int which_widget_intr, + xwidgetnum_t targ, + iopaddr_t addr, + xtalk_intr_vector_t vect) +{ + bridge_t *bridge = (bridge_t *) which_widget; + + if (which_widget_intr == -1) { + /* bridge widget error interrupt */ + bridge->b_wid_int_upper = ( (0x000F0000 & (targ << 16)) | + XTALK_ADDR_TO_UPPER(addr)); + bridge->b_wid_int_lower = XTALK_ADDR_TO_LOWER(addr); + bridge->b_int_host_err = vect; + + /* turn on all interrupts except + * the PCI interrupt requests, + * at least at heart. + */ + bridge->b_int_enable |= ~BRIDGE_IMR_INT_MSK; + + } else { + /* routing a pci device interrupt. + * targ and low 38 bits of addr must + * be the same as the already set + * value for the widget error interrupt. + */ + bridge->b_int_addr[which_widget_intr].addr = + ((BRIDGE_INT_ADDR_HOST & (addr >> 30)) | + (BRIDGE_INT_ADDR_FLD & vect)); + /* + * now bridge can let it through; + * NB: still should be blocked at + * xtalk provider end, until the service + * function is set. + */ + bridge->b_int_enable |= 1 << vect; + } + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ +} + +void +pcibr_intr_list_func(intr_arg_t arg) +{ + pcibr_intr_wrap_t wrap = (pcibr_intr_wrap_t) arg; + reg_p statp = wrap->iw_stat; + bridgereg_t mask = wrap->iw_intr; + reg_p wrbf; + pcibr_intr_list_t list; + pcibr_intr_t intr; + intr_func_t func; + int clearit; + int thread_count = 0; + + /* + * Loop until either + * 1) All interrupts have been removed by direct-called interrupt handlers OR + * 2) We've woken up at least one interrupt thread that will presumably clear + * Bridge interrupt bits + */ + + while ((!thread_count) && (mask & *statp)) { + clearit = 1; + for (list = wrap->iw_list; + list != NULL; + list = list->il_next) { + if ((intr = list->il_intr) && + (intr->bi_flags & PCIIO_INTR_CONNECTED)) { + int is_threaded; + + ASSERT(intr->bi_func); + + /* + * This device may have initiated write + * requests since the bridge last saw + * an edge on this interrupt input; flushing + * the buffer here should help but may not + * be sufficient if we get more requests after + * the flush, followed by the card deciding + * it wants service, before the interrupt + * handler checks to see if things need + * to be done. + * + * There is a similar race condition if + * an interrupt handler loops around and + * notices further service is requred. + * Perhaps we need to have an explicit + * call that interrupt handlers need to + * do between noticing that DMA to memory + * has completed, but before observing the + * contents of memory? + */ +#ifdef IRIX + if (wrbf = list->il_wrbf) +#else + if ((wrbf = list->il_wrbf)) +#endif + (void) *wrbf; /* write request buffer flush */ + + is_threaded = !(intr->bi_flags & PCIIO_INTR_NOTHREAD); + + if (is_threaded) { + thread_count++; +#ifdef IRIX + icvsema(&intr->bi_tinfo.thd_isync, intr->bi_tinfo.thd_pri, + NULL, NULL, NULL); +#endif + } else { + /* Non-threaded. Call the interrupt handler at interrupt level */ + func = intr->bi_func; + func(intr->bi_arg); + } + + clearit = 0; + } + } + + /* If there were no handlers, + * disable the interrupt and return. + * It will get enabled again after + * a handler is connected. + * If we don't do this, we would + * sit here and spin through the + * list forever. + */ + if (clearit) { + pcibr_soft_t pcibr_soft = wrap->iw_soft; + bridge_t *bridge = pcibr_soft->bs_base; + bridgereg_t b_int_enable; + unsigned s; + + s = pcibr_lock(pcibr_soft); + b_int_enable = bridge->b_int_enable; + b_int_enable &= ~mask; + bridge->b_int_enable = b_int_enable; + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ + pcibr_unlock(pcibr_soft, s); + return; + } + } +} + +/* ===================================================================== + * ERROR HANDLING + */ + +#ifdef DEBUG +#ifdef ERROR_DEBUG +#define BRIDGE_PIOERR_TIMEOUT 100 /* Timeout with ERROR_DEBUG defined */ +#else +#define BRIDGE_PIOERR_TIMEOUT 40 /* Timeout in debug mode */ +#endif +#else +#define BRIDGE_PIOERR_TIMEOUT 1 /* Timeout in non-debug mode */ +#endif + +LOCAL void +print_bridge_errcmd(uint32_t cmdword, char *errtype) +{ +#ifdef SUPPORT_PRINTING_R_FORMAT + PRINT_WARNING( + " Bridge %s error command word register %R", + errtype, cmdword, xio_cmd_bits); +#else + PRINT_WARNING( + " Bridge %s error command word register 0x%x", + errtype, cmdword); +#endif +} + +LOCAL char *pcibr_isr_errs[] = +{ + "", "", "", "", "", "", "", "", + "08: GIO non-contiguous byte enable in crosstalk packet", + "09: PCI to Crosstalk read request timeout", + "10: PCI retry operation count exhausted.", + "11: PCI bus device select timeout", + "12: PCI device reported parity error", + "13: PCI Address/Cmd parity error ", + "14: PCI Bridge detected parity error", + "15: PCI abort condition", + "16: SSRAM parity error", + "17: LLP Transmitter Retry count wrapped", + "18: LLP Transmitter side required Retry", + "19: LLP Receiver retry count wrapped", + "20: LLP Receiver check bit error", + "21: LLP Receiver sequence number error", + "22: Request packet overflow", + "23: Request operation not supported by bridge", + "24: Request packet has invalid address for bridge widget", + "25: Incoming request xtalk command word error bit set or invalid sideband", + "26: Incoming response xtalk command word error bit set or invalid sideband", + "27: Framing error, request cmd data size does not match actual", + "28: Framing error, response cmd data size does not match actual", + "29: Unexpected response arrived", + "30: Access to SSRAM beyond device limits", + "31: Multiple errors occurred", +}; + +/* + * PCI Bridge Error interrupt handling. + * This routine gets invoked from system interrupt dispatcher + * and is responsible for invoking appropriate error handler, + * depending on the type of error. + * This IS a duplicate of bridge_errintr defined specfic to IP30. + * There are some minor differences in terms of the return value and + * parameters passed. One of these two should be removed at some point + * of time. + */ +/*ARGSUSED */ +void +pcibr_error_dump(pcibr_soft_t pcibr_soft) +{ + bridge_t *bridge = pcibr_soft->bs_base; + bridgereg_t int_status; + int i; + + int_status = (bridge->b_int_status & ~BRIDGE_ISR_INT_MSK); + + PRINT_ALERT( "%s PCI BRIDGE ERROR: int_status is 0x%X", + pcibr_soft->bs_name, int_status); + + for (i = PCIBR_ISR_ERR_START; i < PCIBR_ISR_MAX_ERRS; i++) { + if (int_status & (1 << i)) { + PRINT_WARNING( "%s", pcibr_isr_errs[i]); + } + } + + if (int_status & BRIDGE_ISR_XTALK_ERROR) { + print_bridge_errcmd(bridge->b_wid_err_cmdword, ""); + + PRINT_WARNING(" Bridge error address 0x%lx", + (((uint64_t) bridge->b_wid_err_upper << 32) | + bridge->b_wid_err_lower)); + + print_bridge_errcmd(bridge->b_wid_aux_err, "Aux"); + + if (int_status & (BRIDGE_ISR_BAD_XRESP_PKT | BRIDGE_ISR_RESP_XTLK_ERR)) { + PRINT_WARNING(" Bridge response buffer: dev-num %d buff-num %d addr 0x%lx\n", + ((bridge->b_wid_resp_upper >> 20) & 0x3), + ((bridge->b_wid_resp_upper >> 16) & 0xF), + (((uint64_t) (bridge->b_wid_resp_upper & 0xFFFF) << 32) | + bridge->b_wid_resp_lower)); + } + } + if (int_status & BRIDGE_ISR_SSRAM_PERR) + PRINT_WARNING(" Bridge SSRAM parity error register 0x%x", + bridge->b_ram_perr); + + if (int_status & BRIDGE_ISR_PCIBUS_ERROR) { + PRINT_WARNING(" PCI/GIO error upper address register 0x%x", + bridge->b_pci_err_upper); + + PRINT_WARNING(" PCI/GIO error lower address register 0x%x", + bridge->b_pci_err_lower); + } + if (int_status & BRIDGE_ISR_ERROR_FATAL) { + cmn_err_tag(14, (int)CE_PANIC, "PCI Bridge Error interrupt killed the system"); + /*NOTREACHED */ + } else { + PRINT_ALERT( "Non-fatal Error in Bridge.."); + } +} + +#define PCIBR_ERRINTR_GROUP(error) \ + (( error & (BRIDGE_IRR_PCI_GRP|BRIDGE_IRR_GIO_GRP) + +uint32_t +pcibr_errintr_group(uint32_t error) +{ + uint32_t group = BRIDGE_IRR_MULTI_CLR; + + if (error & BRIDGE_IRR_PCI_GRP) + group |= BRIDGE_IRR_PCI_GRP_CLR; + if (error & BRIDGE_IRR_SSRAM_GRP) + group |= BRIDGE_IRR_SSRAM_GRP_CLR; + if (error & BRIDGE_IRR_LLP_GRP) + group |= BRIDGE_IRR_LLP_GRP_CLR; + if (error & BRIDGE_IRR_REQ_DSP_GRP) + group |= BRIDGE_IRR_REQ_DSP_GRP_CLR; + if (error & BRIDGE_IRR_RESP_BUF_GRP) + group |= BRIDGE_IRR_RESP_BUF_GRP_CLR; + if (error & BRIDGE_IRR_CRP_GRP) + group |= BRIDGE_IRR_CRP_GRP_CLR; + + return group; + +} + + +/* pcibr_pioerr_check(): + * Check to see if this pcibr has a PCI PIO + * TIMEOUT error; if so, clear it and bump + * the timeout-count on any piomaps that + * could cover the address. + */ +static void +pcibr_pioerr_check(pcibr_soft_t soft) +{ + bridge_t *bridge; + bridgereg_t b_int_status; + bridgereg_t b_pci_err_lower; + bridgereg_t b_pci_err_upper; + iopaddr_t pci_addr; + pciio_slot_t slot; + pcibr_piomap_t map; + iopaddr_t base; + size_t size; + unsigned win; + int func; + + bridge = soft->bs_base; + b_int_status = bridge->b_int_status; + if (b_int_status & BRIDGE_ISR_PCIBUS_PIOERR) { + b_pci_err_lower = bridge->b_pci_err_lower; + b_pci_err_upper = bridge->b_pci_err_upper; + b_int_status = bridge->b_int_status; + if (b_int_status & BRIDGE_ISR_PCIBUS_PIOERR) { + bridge->b_int_rst_stat = (BRIDGE_IRR_PCI_GRP_CLR| + BRIDGE_IRR_MULTI_CLR); + + pci_addr = b_pci_err_upper & BRIDGE_ERRUPPR_ADDRMASK; + pci_addr = (pci_addr << 32) | b_pci_err_lower; + + slot = 8; + while (slot-- > 0) { + int nfunc = soft->bs_slot[slot].bss_ninfo; + pcibr_info_h pcibr_infoh = soft->bs_slot[slot].bss_infos; + + for (func = 0; func < nfunc; func++) { + pcibr_info_t pcibr_info = pcibr_infoh[func]; + + if (!pcibr_info) + continue; + + for (map = pcibr_info->f_piomap; + map != NULL; map = map->bp_next) { + base = map->bp_pciaddr; + size = map->bp_mapsz; + win = map->bp_space - PCIIO_SPACE_WIN(0); + if (win < 6) + base += + soft->bs_slot[slot].bss_window[win].bssw_base; + else if (map->bp_space == PCIIO_SPACE_ROM) + base += pcibr_info->f_rbase; +#ifdef IRIX + if ((pci_addr >= base) && (pci_addr < (base + size))) + atomicAddInt(map->bp_toc, 1); +#endif + } + } + } + } + } +} + +/* + * PCI Bridge Error interrupt handler. + * This gets invoked, whenever a PCI bridge sends an error interrupt. + * Primarily this servers two purposes. + * - If an error can be handled (typically a PIO read/write + * error, we try to do it silently. + * - If an error cannot be handled, we die violently. + * Interrupt due to PIO errors: + * - Bridge sends an interrupt, whenever a PCI operation + * done by the bridge as the master fails. Operations could + * be either a PIO read or a PIO write. + * PIO Read operation also triggers a bus error, and it's + * We primarily ignore this interrupt in that context.. + * For PIO write errors, this is the only indication. + * and we have to handle with the info from here. + * + * So, there is no way to distinguish if an interrupt is + * due to read or write error!. + */ + + +LOCAL void +pcibr_error_intr_handler(intr_arg_t arg) +{ + pcibr_soft_t pcibr_soft; + bridge_t *bridge; + bridgereg_t int_status; + bridgereg_t err_status; + int i; + +#if defined(SN0_HWDEBUG) + extern int la_trigger_nasid1; + extern int la_trigger_nasid2; + extern long la_trigger_val; +#endif + + /* REFERENCED */ + bridgereg_t disable_errintr_mask = 0; +#ifdef IRIX + int rv; +#else + int rv = 0; +#endif + int error_code = IOECODE_DMA | IOECODE_READ; + ioerror_mode_t mode = MODE_DEVERROR; + ioerror_t ioe; + +#if defined(SN0_HWDEBUG) + /* + * trigger points for logic analyzer. Used to debug the DMA timeout + * note that 0xcafe is added to the trigger values to avoid false + * triggers when la_trigger_val shows up in a cacheline as data + */ + if (la_trigger_nasid1 != -1) + REMOTE_HUB_PI_S(la_trigger_nasid1, 0, PI_CPU_NUM, la_trigger_val + 0xcafe); + if (la_trigger_nasid2 != -1) + REMOTE_HUB_PI_S(la_trigger_nasid2, 0, PI_CPU_NUM, la_trigger_val + 0xcafe); +#endif + +#if PCIBR_SOFT_LIST + /* IP27 seems to be handing us junk. + */ + { + pcibr_list_p entry; + + entry = pcibr_list; + while (1) { + if (entry == NULL) { + printk("pcibr_error_intr_handler:\n" + "\tparameter (0x%p) is not a pcibr_soft!", + arg); + PRINT_PANIC("Invalid parameter to pcibr_error_intr_handler"); + } + if ((intr_arg_t) entry->bl_soft == arg) + break; + entry = entry->bl_next; + } + } +#endif + pcibr_soft = (pcibr_soft_t) arg; + bridge = pcibr_soft->bs_base; + + /* + * pcibr_error_intr_handler gets invoked whenever bridge encounters + * an error situation, and the interrupt for that error is enabled. + * This routine decides if the error is fatal or not, and takes + * action accordingly. + * + * In one case there is a need for special action. + * In case of PIO read/write timeouts due to user level, we do + * get an error interrupt. In this case, way to handle would + * be to start a timeout. If the error was due to "read", bus + * error handling code takes care of it. If error is due to write, + * it's handled at timeout + */ + + /* int_status is which bits we have to clear; + * err_status is the bits we haven't handled yet. + */ + + int_status = bridge->b_int_status & ~BRIDGE_ISR_INT_MSK; + err_status = int_status & ~BRIDGE_ISR_MULTI_ERR; + + if (!(int_status & ~BRIDGE_ISR_INT_MSK)) { + /* + * No error bit set!!. + */ + return; + } + /* If we have a PCIBUS_PIOERR, + * hand it to the logger but otherwise + * ignore the event. + */ + if (int_status & BRIDGE_ISR_PCIBUS_PIOERR) { + pcibr_pioerr_check(pcibr_soft); + err_status &= ~BRIDGE_ISR_PCIBUS_PIOERR; + int_status &= ~BRIDGE_ISR_PCIBUS_PIOERR; + } + + + if (err_status) { + struct bs_errintr_stat_s *bs_estat = pcibr_soft->bs_errintr_stat; + + for (i = PCIBR_ISR_ERR_START; i < PCIBR_ISR_MAX_ERRS; i++, bs_estat++) { + if (err_status & (1 << i)) { + uint32_t errrate = 0; + uint32_t errcount = 0; + uint32_t errinterval = 0, current_tick = 0; + int panic_on_llp_tx_retry = 0; + int is_llp_tx_retry_intr = 0; + + bs_estat->bs_errcount_total++; + +#ifdef IRIX + current_tick = lbolt; +#else + current_tick = 0; +#endif + errinterval = (current_tick - bs_estat->bs_lasterr_timestamp); + errcount = (bs_estat->bs_errcount_total - + bs_estat->bs_lasterr_snapshot); + + is_llp_tx_retry_intr = (BRIDGE_ISR_LLP_TX_RETRY == (1 << i)); + + /* On a non-zero error rate (which is equivalent to + * to 100 errors /sec at least) for the LLP transmitter + * retry interrupt we need to panic the system + * to prevent potential data corruption . + * NOTE : errcount is being compared to PCIBR_ERRTIME_THRESHOLD + * to make sure that we are not seing cases like x error + * interrupts per y ticks for very low x ,y (x > y ) which + * makes error rate be > 100 /sec. + */ + + /* Check for the divide by zero condition while + * calculating the error rates. + */ + + if (errinterval) { + errrate = errcount / errinterval; + /* If able to calculate error rate + * on a LLP transmitter retry interrupt check + * if the error rate is nonzero and we have seen + * a certain minimum number of errors. + */ + if (is_llp_tx_retry_intr && + errrate && + (errcount >= PCIBR_ERRTIME_THRESHOLD)) { + panic_on_llp_tx_retry = 1; + } + } else { + errrate = 0; + /* Since we are not able to calculate the + * error rate check if we exceeded a certain + * minimum number of errors for LLP transmitter + * retries. Note that this can only happen + * within the first tick after the last snapshot. + */ + if (is_llp_tx_retry_intr && + (errcount >= PCIBR_ERRINTR_DISABLE_LEVEL)) { + panic_on_llp_tx_retry = 1; + } + } + if (panic_on_llp_tx_retry) { + static uint32_t last_printed_rate; + + if (errrate > last_printed_rate) { + last_printed_rate = errrate; + /* Print the warning only if the error rate + * for the transmitter retry interrupt + * exceeded the previously printed rate. + */ + PRINT_WARNING( + "%s: %s, Excessive error interrupts : %d/tick\n", + pcibr_soft->bs_name, + pcibr_isr_errs[i], + errrate); + + } + /* + * Update snapshot, and time + */ + bs_estat->bs_lasterr_timestamp = current_tick; + bs_estat->bs_lasterr_snapshot = + bs_estat->bs_errcount_total; + + } + /* + * If the error rate is high enough, print the error rate. + */ + if (errinterval > PCIBR_ERRTIME_THRESHOLD) { + + if (errrate > PCIBR_ERRRATE_THRESHOLD) { + PRINT_NOTICE( "%s: %s, Error rate %d/tick", + pcibr_soft->bs_name, + pcibr_isr_errs[i], + errrate); + /* + * Update snapshot, and time + */ + bs_estat->bs_lasterr_timestamp = current_tick; + bs_estat->bs_lasterr_snapshot = + bs_estat->bs_errcount_total; + } + } + if (bs_estat->bs_errcount_total > PCIBR_ERRINTR_DISABLE_LEVEL) { + /* + * We have seen a fairly large number of errors of + * this type. Let's disable the interrupt. But flash + * a message about the interrupt being disabled. + */ + PRINT_NOTICE( + "%s Disabling error interrupt type %s. Error count %d", + pcibr_soft->bs_name, + pcibr_isr_errs[i], + bs_estat->bs_errcount_total); + disable_errintr_mask |= (1 << i); + } + } + } + } + + if (disable_errintr_mask) { + /* + * Disable some high frequency errors as they + * could eat up too much cpu time. + */ + bridge->b_int_enable &= ~disable_errintr_mask; + } + /* + * If we leave the PROM cacheable, T5 might + * try to do a cache line sized writeback to it, + * which will cause a BRIDGE_ISR_INVLD_ADDR. + */ + if ((err_status & BRIDGE_ISR_INVLD_ADDR) && + (0x00000000 == bridge->b_wid_err_upper) && + (0x00C00000 == (0xFFC00000 & bridge->b_wid_err_lower)) && + (0x00402000 == (0x00F07F00 & bridge->b_wid_err_cmdword))) { + err_status &= ~BRIDGE_ISR_INVLD_ADDR; + } +#if defined (PCIBR_LLP_CONTROL_WAR) + /* + * The bridge bug, where the llp_config or control registers + * need to be read back after being written, affects an MP + * system since there could be small windows between writing + * the register and reading it back on one cpu while another + * cpu is fielding an interrupt. If we run into this scenario, + * workaround the problem by ignoring the error. (bug 454474) + * pcibr_llp_control_war_cnt keeps an approximate number of + * times we saw this problem on a system. + */ + + if ((err_status & BRIDGE_ISR_INVLD_ADDR) && + ((((uint64_t) bridge->b_wid_err_upper << 32) | (bridge->b_wid_err_lower)) + == (BRIDGE_INT_RST_STAT & 0xff0))) { +#ifdef IRIX + if (kdebug) + PRINT_NOTICE( "%s bridge: ignoring llp/control address interrupt", + pcibr_soft->bs_name); +#endif + pcibr_llp_control_war_cnt++; + err_status &= ~BRIDGE_ISR_INVLD_ADDR; + } +#endif /* PCIBR_LLP_CONTROL_WAR */ + + /* Check if this is the RESP_XTALK_ERROR interrupt. + * This can happen due to a failed DMA READ operation. + */ + if (err_status & BRIDGE_ISR_RESP_XTLK_ERR) { + /* Phase 1 : Look at the error state in the bridge and further + * down in the device layers. + */ +#if defined(CONFIG_SGI_IO_ERROR_HANDLING) + (void)error_state_set(pcibr_soft->bs_conn, ERROR_STATE_LOOKUP); +#endif + IOERROR_SETVALUE(&ioe, widgetnum, pcibr_soft->bs_xid); + (void)pcibr_error_handler((error_handler_arg_t)pcibr_soft, + error_code, + mode, + &ioe); + /* Phase 2 : Perform the action agreed upon in phase 1. + */ +#if defined(CONFIG_SGI_IO_ERROR_HANDLING) + (void)error_state_set(pcibr_soft->bs_conn, ERROR_STATE_ACTION); +#endif + rv = pcibr_error_handler((error_handler_arg_t)pcibr_soft, + error_code, + mode, + &ioe); + } + if (rv != IOERROR_HANDLED) { +#ifdef DEBUG + if (err_status & BRIDGE_ISR_ERROR_DUMP) + pcibr_error_dump(pcibr_soft); +#else + if (err_status & BRIDGE_ISR_ERROR_FATAL) { + printk("BRIDGE ERR STATUS 0x%x\n", err_status); + pcibr_error_dump(pcibr_soft); + } +#endif + } + /* + * We can't return without re-enabling the interrupt, since + * it would cause problems for devices like IOC3 (Lost + * interrupts ?.). So, just cleanup the interrupt, and + * use saved values later.. + */ + bridge->b_int_rst_stat = pcibr_errintr_group(int_status); +} + +/* + * pcibr_addr_toslot + * Given the 'pciaddr' find out which slot this address is + * allocated to, and return the slot number. + * While we have the info handy, construct the + * function number, space code and offset as well. + * + * NOTE: if this routine is called, we don't know whether + * the address is in CFG, MEM, or I/O space. We have to guess. + * This will be the case on PIO stores, where the only way + * we have of getting the address is to check the Bridge, which + * stores the PCI address but not the space and not the xtalk + * address (from which we could get it). + */ +LOCAL int +pcibr_addr_toslot(pcibr_soft_t pcibr_soft, + iopaddr_t pciaddr, + pciio_space_t *spacep, + iopaddr_t *offsetp, + pciio_function_t *funcp) +{ +#ifdef IRIX + int s, f, w; +#else + int s, f=0, w; +#endif + iopaddr_t base; + size_t size; + pciio_piospace_t piosp; + + /* + * Check if the address is in config space + */ + + if ((pciaddr >= BRIDGE_CONFIG_BASE) && (pciaddr < BRIDGE_CONFIG_END)) { + + if (pciaddr >= BRIDGE_CONFIG1_BASE) + pciaddr -= BRIDGE_CONFIG1_BASE; + else + pciaddr -= BRIDGE_CONFIG_BASE; + + s = pciaddr / BRIDGE_CONFIG_SLOT_SIZE; + pciaddr %= BRIDGE_CONFIG_SLOT_SIZE; + + if (funcp) { + f = pciaddr / 0x100; + pciaddr %= 0x100; + } + if (spacep) + *spacep = PCIIO_SPACE_CFG; + if (offsetp) + *offsetp = pciaddr; + if (funcp) + *funcp = f; + + return s; + } + for (s = 0; s < 8; s++) { + int nf = pcibr_soft->bs_slot[s].bss_ninfo; + pcibr_info_h pcibr_infoh = pcibr_soft->bs_slot[s].bss_infos; + + for (f = 0; f < nf; f++) { + pcibr_info_t pcibr_info = pcibr_infoh[f]; + + if (!pcibr_info) + continue; + for (w = 0; w < 6; w++) { + if (pcibr_info->f_window[w].w_space + == PCIIO_SPACE_NONE) { + continue; + } + base = pcibr_info->f_window[w].w_base; + size = pcibr_info->f_window[w].w_size; + + if ((pciaddr >= base) && (pciaddr < (base + size))) { + if (spacep) + *spacep = PCIIO_SPACE_WIN(w); + if (offsetp) + *offsetp = pciaddr - base; + if (funcp) + *funcp = f; + return s; + } /* endif match */ + } /* next window */ + } /* next func */ + } /* next slot */ + + /* + * Check if the address was allocated as part of the + * pcibr_piospace_alloc calls. + */ + for (s = 0; s < 8; s++) { + int nf = pcibr_soft->bs_slot[s].bss_ninfo; + pcibr_info_h pcibr_infoh = pcibr_soft->bs_slot[s].bss_infos; + + for (f = 0; f < nf; f++) { + pcibr_info_t pcibr_info = pcibr_infoh[f]; + + if (!pcibr_info) + continue; + piosp = pcibr_info->f_piospace; + while (piosp) { + if ((piosp->start <= pciaddr) && + ((piosp->count + piosp->start) > pciaddr)) { + if (spacep) + *spacep = piosp->space; + if (offsetp) + *offsetp = pciaddr - piosp->start; + return s; + } /* endif match */ + piosp = piosp->next; + } /* next piosp */ + } /* next func */ + } /* next slot */ + + /* + * Some other random address on the PCI bus ... + * we have no way of knowing whether this was + * a MEM or I/O access; so, for now, we just + * assume that the low 1G is MEM, the next + * 3G is I/O, and anything above the 4G limit + * is obviously MEM. + */ + + if (spacep) + *spacep = ((pciaddr < (1ul << 30)) ? PCIIO_SPACE_MEM : + (pciaddr < (4ul << 30)) ? PCIIO_SPACE_IO : + PCIIO_SPACE_MEM); + if (offsetp) + *offsetp = pciaddr; + + return PCIIO_SLOT_NONE; + +} + +LOCAL void +pcibr_error_cleanup(pcibr_soft_t pcibr_soft, int error_code) +{ + bridge_t *bridge = pcibr_soft->bs_base; + + ASSERT(error_code & IOECODE_PIO); + error_code = error_code; + + bridge->b_int_rst_stat = + (BRIDGE_IRR_PCI_GRP_CLR | BRIDGE_IRR_MULTI_CLR); + (void) bridge->b_wid_tflush; /* flushbus */ +} + +/* + * pcibr_error_extract + * Given the 'pcibr vertex handle' find out which slot + * the bridge status error address (from pcibr_soft info + * hanging off the vertex) + * allocated to, and return the slot number. + * While we have the info handy, construct the + * space code and offset as well. + * + * NOTE: if this routine is called, we don't know whether + * the address is in CFG, MEM, or I/O space. We have to guess. + * This will be the case on PIO stores, where the only way + * we have of getting the address is to check the Bridge, which + * stores the PCI address but not the space and not the xtalk + * address (from which we could get it). + * + * XXX- this interface has no way to return the function + * number on a multifunction card, even though that data + * is available. + */ + +pciio_slot_t +pcibr_error_extract(devfs_handle_t pcibr_vhdl, + pciio_space_t *spacep, + iopaddr_t *offsetp) +{ + pcibr_soft_t pcibr_soft = 0; + iopaddr_t bserr_addr; + bridge_t *bridge; + pciio_slot_t slot = PCIIO_SLOT_NONE; + arbitrary_info_t rev; + + /* Do a sanity check as to whether we really got a + * bridge vertex handle. + */ + if (hwgraph_info_get_LBL(pcibr_vhdl, INFO_LBL_PCIBR_ASIC_REV, &rev) != + GRAPH_SUCCESS) + return(slot); + + pcibr_soft = pcibr_soft_get(pcibr_vhdl); + if (pcibr_soft) { + bridge = pcibr_soft->bs_base; + bserr_addr = + bridge->b_pci_err_lower | + ((uint64_t) (bridge->b_pci_err_upper & + BRIDGE_ERRUPPR_ADDRMASK) << 32); + + slot = pcibr_addr_toslot(pcibr_soft, bserr_addr, + spacep, offsetp, NULL); + } + return slot; +} + +/*ARGSUSED */ +void +pcibr_device_disable(pcibr_soft_t pcibr_soft, int devnum) +{ + /* + * XXX + * Device failed to handle error. Take steps to + * disable this device ? HOW TO DO IT ? + * + * If there are any Read response buffers associated + * with this device, it's time to get them back!! + * + * We can disassociate any interrupt level associated + * with this device, and disable that interrupt level + * + * For now it's just a place holder + */ +} + +/* + * pcibr_pioerror + * Handle PIO error that happened at the bridge pointed by pcibr_soft. + * + * Queries the Bus interface attached to see if the device driver + * mapping the device-number that caused error can handle the + * situation. If so, it will clean up any error, and return + * indicating the error was handled. If the device driver is unable + * to handle the error, it expects the bus-interface to disable that + * device, and takes any steps needed here to take away any resources + * associated with this device. + */ + +#define BEM_ADD_STR(s) printk("%s", (s)) +#ifdef SUPPORT_SGI_CMN_ERR_STUFF +#define BEM_ADD_VAR(v) printk("\t%20s: 0x%x\n", #v, (v)) +#define BEM_ADD_REG(r) printk("\t%20s: %R\n", #r, (r), r ## _desc) + +#define BEM_ADD_NSPC(n,s) printk("\t%20s: %R\n", n, s, space_desc) +#else +#define BEM_ADD_VAR(v) +#define BEM_ADD_REG(r) +#define BEM_ADD_NSPC(n,s) +#endif +#define BEM_ADD_SPC(s) BEM_ADD_NSPC(#s, s) + +/* BEM_ADD_IOE doesn't dump the whole ioerror, it just + * decodes the PCI specific portions -- we count on our + * callers to dump the raw IOE data. + */ +#ifdef colin +#define BEM_ADD_IOE(ioe) \ + do { \ + if (IOERROR_FIELDVALID(ioe, busspace)) { \ + unsigned spc; \ + unsigned win; \ + \ + spc = IOERROR_GETVALUE(ioe, busspace); \ + win = spc - PCIIO_SPACE_WIN(0); \ + \ + switch (spc) { \ + case PCIIO_SPACE_CFG: \ + printk("\tPCI Slot %d Func %d CFG space Offset 0x%x\n", \ + pciio_widgetdev_slot_get(IOERROR_GETVALUE(ioe, widgetdev)), \ + pciio_widgetdev_func_get(IOERROR_GETVALUE(ioe, widgetdev)), \ + IOERROR_GETVALUE(ioe, busaddr)); \ + break; \ + case PCIIO_SPACE_IO: \ + printk("\tPCI I/O space Offset 0x%x\n", \ + IOERROR_GETVALUE(ioe, busaddr)); \ + break; \ + case PCIIO_SPACE_MEM: \ + case PCIIO_SPACE_MEM32: \ + case PCIIO_SPACE_MEM64: \ + printk("\tPCI MEM space Offset 0x%x\n", \ + IOERROR_GETVALUE(ioe, busaddr)); \ + break; \ + default: \ + if (win < 6) { \ + printk("\tPCI Slot %d Func %d Window %d Offset 0x%x\n",\ + pciio_widgetdev_slot_get(IOERROR_GETVALUE(ioe, widgetdev)), \ + pciio_widgetdev_func_get(IOERROR_GETVALUE(ioe, widgetdev)), \ + win, \ + IOERROR_GETVALUE(ioe, busaddr)); \ + } \ + break; \ + } \ + } \ + } while (0) +#else +#define BEM_ADD_IOE(ioe) +#endif + +/*ARGSUSED */ +LOCAL int +pcibr_pioerror( + pcibr_soft_t pcibr_soft, + int error_code, + ioerror_mode_t mode, + ioerror_t *ioe) +{ + int retval = IOERROR_HANDLED; + + devfs_handle_t pcibr_vhdl = pcibr_soft->bs_vhdl; + bridge_t *bridge = pcibr_soft->bs_base; + + bridgereg_t bridge_int_status; + bridgereg_t bridge_pci_err_lower; + bridgereg_t bridge_pci_err_upper; + bridgereg_t bridge_pci_err_addr; + + iopaddr_t bad_xaddr; + + pciio_space_t raw_space; /* raw PCI space */ + iopaddr_t raw_paddr; /* raw PCI address */ + + pciio_space_t space; /* final PCI space */ + pciio_slot_t slot; /* final PCI slot, if appropriate */ + pciio_function_t func; /* final PCI func, if appropriate */ + iopaddr_t offset; /* final PCI offset */ + + int cs, cw, cf; + pciio_space_t wx; + iopaddr_t wb; + size_t ws; + iopaddr_t wl; + + + /* + * We expect to have an "xtalkaddr" coming in, + * and need to construct the slot/space/offset. + */ + +#ifdef colin + bad_xaddr = IOERROR_GETVALUE(ioe, xtalkaddr); +#else + bad_xaddr = -1; +#endif + + slot = PCIIO_SLOT_NONE; + func = PCIIO_FUNC_NONE; + raw_space = PCIIO_SPACE_NONE; + raw_paddr = 0; + + if ((bad_xaddr >= BRIDGE_TYPE0_CFG_DEV0) && + (bad_xaddr < BRIDGE_TYPE1_CFG)) { + raw_paddr = bad_xaddr - BRIDGE_TYPE0_CFG_DEV0; + slot = raw_paddr / BRIDGE_TYPE0_CFG_SLOT_OFF; + raw_paddr = raw_paddr % BRIDGE_TYPE0_CFG_SLOT_OFF; + raw_space = PCIIO_SPACE_CFG; + } + if ((bad_xaddr >= BRIDGE_TYPE1_CFG) && + (bad_xaddr < (BRIDGE_TYPE1_CFG + 0x1000))) { + /* Type 1 config space: + * slot and function numbers not known. + * Perhaps we can read them back? + */ + raw_paddr = bad_xaddr - BRIDGE_TYPE1_CFG; + raw_space = PCIIO_SPACE_CFG; + } + if ((bad_xaddr >= BRIDGE_DEVIO0) && + (bad_xaddr < BRIDGE_DEVIO(BRIDGE_DEV_CNT))) { + int x; + + raw_paddr = bad_xaddr - BRIDGE_DEVIO0; + x = raw_paddr / BRIDGE_DEVIO_OFF; + raw_paddr %= BRIDGE_DEVIO_OFF; + /* first two devio windows are double-sized */ + if ((x == 1) || (x == 3)) + raw_paddr += BRIDGE_DEVIO_OFF; + if (x > 0) + x--; + if (x > 1) + x--; + /* x is which devio reg; no guarantee + * pci slot x will be responding. + * still need to figure out who decodes + * space/offset on the bus. + */ + raw_space = pcibr_soft->bs_slot[x].bss_devio.bssd_space; + if (raw_space == PCIIO_SPACE_NONE) { + /* Someone got an error because they + * accessed the PCI bus via a DevIO(x) + * window that pcibr has not yet assigned + * to any specific PCI address. It is + * quite possible that the Device(x) + * register has been changed since they + * made their access, but we will give it + * our best decode shot. + */ + raw_space = pcibr_soft->bs_slot[x].bss_device + & BRIDGE_DEV_DEV_IO_MEM + ? PCIIO_SPACE_MEM + : PCIIO_SPACE_IO; + raw_paddr += + (pcibr_soft->bs_slot[x].bss_device & + BRIDGE_DEV_OFF_MASK) << + BRIDGE_DEV_OFF_ADDR_SHFT; + } else + raw_paddr += pcibr_soft->bs_slot[x].bss_devio.bssd_base; + } + if ((bad_xaddr >= BRIDGE_PCI_MEM32_BASE) && + (bad_xaddr <= BRIDGE_PCI_MEM32_LIMIT)) { + raw_space = PCIIO_SPACE_MEM32; + raw_paddr = bad_xaddr - BRIDGE_PCI_MEM32_BASE; + } + if ((bad_xaddr >= BRIDGE_PCI_MEM64_BASE) && + (bad_xaddr <= BRIDGE_PCI_MEM64_LIMIT)) { + raw_space = PCIIO_SPACE_MEM64; + raw_paddr = bad_xaddr - BRIDGE_PCI_MEM64_BASE; + } + if ((bad_xaddr >= BRIDGE_PCI_IO_BASE) && + (bad_xaddr <= BRIDGE_PCI_IO_LIMIT)) { + raw_space = PCIIO_SPACE_IO; + raw_paddr = bad_xaddr - BRIDGE_PCI_IO_BASE; + } + space = raw_space; + offset = raw_paddr; + + if ((slot == PCIIO_SLOT_NONE) && (space != PCIIO_SPACE_NONE)) { + /* we've got a space/offset but not which + * pci slot decodes it. Check through our + * notions of which devices decode where. + * + * Yes, this "duplicates" some logic in + * pcibr_addr_toslot; the difference is, + * this code knows which space we are in, + * and can really really tell what is + * going on (no guessing). + */ + + for (cs = 0; (cs < 8) && (slot == PCIIO_SLOT_NONE); cs++) { + int nf = pcibr_soft->bs_slot[cs].bss_ninfo; + pcibr_info_h pcibr_infoh = pcibr_soft->bs_slot[cs].bss_infos; + + for (cf = 0; (cf < nf) && (slot == PCIIO_SLOT_NONE); cf++) { + pcibr_info_t pcibr_info = pcibr_infoh[cf]; + + if (!pcibr_info) + continue; + for (cw = 0; (cw < 6) && (slot == PCIIO_SLOT_NONE); ++cw) { + if (((wx = pcibr_info->f_window[cw].w_space) != PCIIO_SPACE_NONE) && + ((wb = pcibr_info->f_window[cw].w_base) != 0) && + ((ws = pcibr_info->f_window[cw].w_size) != 0) && + ((wl = wb + ws) > wb) && + ((wb <= offset) && (wl > offset))) { + /* MEM, MEM32 and MEM64 need to + * compare as equal ... + */ + if ((wx == space) || + (((wx == PCIIO_SPACE_MEM) || + (wx == PCIIO_SPACE_MEM32) || + (wx == PCIIO_SPACE_MEM64)) && + ((space == PCIIO_SPACE_MEM) || + (space == PCIIO_SPACE_MEM32) || + (space == PCIIO_SPACE_MEM64)))) { + slot = cs; + func = cf; + space = PCIIO_SPACE_WIN(cw); + offset -= wb; + } /* endif window space match */ + } /* endif window valid and addr match */ + } /* next window unless slot set */ + } /* next func unless slot set */ + } /* next slot unless slot set */ + /* XXX- if slot is still -1, no PCI devices are + * decoding here using their standard PCI BASE + * registers. This would be a really good place + * to cross-coordinate with the pciio PCI + * address space allocation routines, to find + * out if this address is "allocated" by any of + * our subsidiary devices. + */ + } + /* Scan all piomap records on this PCI bus to update + * the TimeOut Counters on all matching maps. If we + * don't already know the slot number, take it from + * the first matching piomap. Note that we have to + * compare maps against raw_space and raw_paddr + * since space and offset could already be + * window-relative. + * + * There is a chance that one CPU could update + * through this path, and another CPU could also + * update due to an interrupt. Closing this hole + * would only result in the possibility of some + * errors never getting logged at all, and since the + * use for bp_toc is as a logical test rather than a + * strict count, the excess counts are not a + * problem. + */ + for (cs = 0; cs < 8; ++cs) { + int nf = pcibr_soft->bs_slot[cs].bss_ninfo; + pcibr_info_h pcibr_infoh = pcibr_soft->bs_slot[cs].bss_infos; + + for (cf = 0; cf < nf; cf++) { + pcibr_info_t pcibr_info = pcibr_infoh[cf]; + pcibr_piomap_t map; + + if (!pcibr_info) + continue; + + for (map = pcibr_info->f_piomap; + map != NULL; map = map->bp_next) { + wx = map->bp_space; + wb = map->bp_pciaddr; + ws = map->bp_mapsz; + cw = wx - PCIIO_SPACE_WIN(0); + if (cw < 6) { + wb += pcibr_soft->bs_slot[cs].bss_window[cw].bssw_base; + wx = pcibr_soft->bs_slot[cs].bss_window[cw].bssw_space; + } + if (wx == PCIIO_SPACE_ROM) { + wb += pcibr_info->f_rbase; + wx = PCIIO_SPACE_MEM; + } + if ((wx == PCIIO_SPACE_MEM32) || + (wx == PCIIO_SPACE_MEM64)) + wx = PCIIO_SPACE_MEM; + wl = wb + ws; + if ((wx == raw_space) && (raw_paddr >= wb) && (raw_paddr < wl)) { +#ifdef IRIX + atomicAddInt(map->bp_toc, 1); +#endif + if (slot == PCIIO_SLOT_NONE) { + slot = cs; + space = map->bp_space; + if (cw < 6) + offset -= pcibr_soft->bs_slot[cs].bss_window[cw].bssw_base; + } + } + } + } + } + + if (space != PCIIO_SPACE_NONE) { + if (slot != PCIIO_SLOT_NONE) { +#ifdef IRIX + if (func != PCIIO_FUNC_NONE) + IOERROR_SETVALUE(ioe, widgetdev, + pciio_widgetdev_create(slot,func)); + else + IOERROR_SETVALUE(ioe, widgetdev, + pciio_widgetdev_create(slot,0)); +#else + if (func != PCIIO_FUNC_NONE) { + IOERROR_SETVALUE(ioe, widgetdev, + pciio_widgetdev_create(slot,func)); + } else { + IOERROR_SETVALUE(ioe, widgetdev, + pciio_widgetdev_create(slot,0)); + } +#endif + } + + IOERROR_SETVALUE(ioe, busspace, space); + IOERROR_SETVALUE(ioe, busaddr, offset); + } + if (mode == MODE_DEVPROBE) { + /* + * During probing, we don't really care what the + * error is. Clean up the error in Bridge, notify + * subsidiary devices, and return success. + */ + pcibr_error_cleanup(pcibr_soft, error_code); + + /* if appropriate, give the error handler for this slot + * a shot at this probe access as well. + */ + return (slot == PCIIO_SLOT_NONE) ? IOERROR_HANDLED : + pciio_error_handler(pcibr_vhdl, error_code, mode, ioe); + } + /* + * If we don't know what "PCI SPACE" the access + * was targeting, we may have problems at the + * Bridge itself. Don't touch any bridge registers, + * and do complain loudly. + */ + + if (space == PCIIO_SPACE_NONE) { + printk("XIO Bus Error at %s\n" + "\taccess to XIO bus offset 0x%lx\n" + "\tdoes not correspond to any PCI address\n", + pcibr_soft->bs_name, bad_xaddr); + + /* caller will dump contents of ioe struct */ + return IOERROR_XTALKLEVEL; + } + /* + * Read the PCI Bridge error log registers. + */ + bridge_int_status = bridge->b_int_status; + bridge_pci_err_upper = bridge->b_pci_err_upper; + bridge_pci_err_lower = bridge->b_pci_err_lower; + + bridge_pci_err_addr = + bridge_pci_err_lower + | (((iopaddr_t) bridge_pci_err_upper + & BRIDGE_ERRUPPR_ADDRMASK) << 32); + + /* + * Actual PCI Error handling situation. + * Typically happens when a user level process accesses + * PCI space, and it causes some error. + * + * Due to PCI Bridge implementation, we get two indication + * for a read error: an interrupt and a Bus error. + * We like to handle read error in the bus error context. + * But the interrupt comes and goes before bus error + * could make much progress. (NOTE: interrupd does + * come in _after_ bus error processing starts. But it's + * completed by the time bus error code reaches PCI PIO + * error handling. + * Similarly write error results in just an interrupt, + * and error handling has to be done at interrupt level. + * There is no way to distinguish at interrupt time, if an + * error interrupt is due to read/write error.. + */ + + /* We know the xtalk addr, the raw pci bus space, + * the raw pci bus address, the decoded pci bus + * space, the offset within that space, and the + * decoded pci slot (which may be "PCIIO_SLOT_NONE" if no slot + * is known to be involved). + */ + + /* + * Hand the error off to the handler registered + * for the slot that should have decoded the error, + * or to generic PCI handling (if pciio decides that + * such is appropriate). + */ + retval = pciio_error_handler(pcibr_vhdl, error_code, mode, ioe); + + if (retval != IOERROR_HANDLED) { + + /* Generate a generic message for IOERROR_UNHANDLED + * since the subsidiary handlers were silent, and + * did no recovery. + */ + if (retval == IOERROR_UNHANDLED) { + retval = IOERROR_PANIC; + + /* we may or may not want to print some of this, + * depending on debug level and which error code. + */ + + PRINT_ALERT( + "PIO Error on PCI Bus %s", + pcibr_soft->bs_name); + /* this decodes part of the ioe; our caller + * will dump the raw details in DEBUG and + * kdebug kernels. + */ + BEM_ADD_IOE(ioe); + } +#if defined(FORCE_ERRORS) + if (0) { +#elif !DEBUG + if (kdebug) { +#endif + /* + * dump raw data from bridge + */ + + BEM_ADD_STR("DEBUG DATA -- raw info from Bridge ASIC:\n"); + BEM_ADD_REG(bridge_int_status); + BEM_ADD_VAR(bridge_pci_err_upper); + BEM_ADD_VAR(bridge_pci_err_lower); + BEM_ADD_VAR(bridge_pci_err_addr); + BEM_ADD_SPC(raw_space); + BEM_ADD_VAR(raw_paddr); + if (IOERROR_FIELDVALID(ioe, widgetdev)) { + +#ifdef colin + slot = pciio_widgetdev_slot_get(IOERROR_GETVALUE(ioe, + widgetdev)); + func = pciio_widgetdev_func_get(IOERROR_GETVALUE(ioe, + widgetdev)); +#else + slot = -1; + func = -1; +#endif + if (slot < 8) { +#ifdef SUPPORT_SGI_CMN_ERR_STUFF + bridgereg_t device = bridge->b_device[slot].reg; +#endif + + BEM_ADD_VAR(slot); + BEM_ADD_VAR(func); + BEM_ADD_REG(device); + } + } +#if !DEBUG || defined(FORCE_ERRORS) + } +#endif + + /* + * Since error could not be handled at lower level, + * error data logged has not been cleared. + * Clean up errors, and + * re-enable bridge to interrupt on error conditions. + * NOTE: Wheather we get the interrupt on PCI_ABORT or not is + * dependent on INT_ENABLE register. This write just makes sure + * that if the interrupt was enabled, we do get the interrupt. + * + * CAUTION: Resetting bit BRIDGE_IRR_PCI_GRP_CLR, acknowledges + * a group of interrupts. If while handling this error, + * some other error has occured, that would be + * implicitly cleared by this write. + * Need a way to ensure we don't inadvertently clear some + * other errors. + */ +#ifdef IRIX + if (IOERROR_FIELDVALID(ioe, widgetdev)) + pcibr_device_disable(pcibr_soft, + pciio_widgetdev_slot_get( + IOERROR_GETVALUE(ioe, widgetdev))); +#endif + + if (mode == MODE_DEVUSERERROR) + pcibr_error_cleanup(pcibr_soft, error_code); + } + return retval; +} + +/* + * bridge_dmaerror + * Some error was identified in a DMA transaction. + * This routine will identify the that caused the error, + * and try to invoke the appropriate bus service to handle this. + */ + +#define BRIDGE_DMA_READ_ERROR (BRIDGE_ISR_RESP_XTLK_ERR|BRIDGE_ISR_XREAD_REQ_TIMEOUT) + +int +pcibr_dmard_error( + pcibr_soft_t pcibr_soft, + int error_code, + ioerror_mode_t mode, + ioerror_t *ioe) +{ + devfs_handle_t pcibr_vhdl = pcibr_soft->bs_vhdl; + bridge_t *bridge = pcibr_soft->bs_base; + bridgereg_t bus_lowaddr, bus_uppraddr; + int retval = 0; + int bufnum; + + /* + * In case of DMA errors, bridge should have logged the + * address that caused the error. + * Look up the address, in the bridge error registers, and + * take appropriate action + */ +#ifdef colin + ASSERT(IOERROR_GETVALUE(ioe, widgetnum) == pcibr_soft->bs_xid); + ASSERT(bridge); +#endif + + /* + * read error log registers + */ + bus_lowaddr = bridge->b_wid_resp_lower; + bus_uppraddr = bridge->b_wid_resp_upper; + + bufnum = BRIDGE_RESP_ERRUPPR_BUFNUM(bus_uppraddr); + IOERROR_SETVALUE(ioe, widgetdev, + pciio_widgetdev_create( + BRIDGE_RESP_ERRUPPR_DEVICE(bus_uppraddr), + 0)); + IOERROR_SETVALUE(ioe, busaddr, + (bus_lowaddr | + ((iopaddr_t) + (bus_uppraddr & + BRIDGE_ERRUPPR_ADDRMASK) << 32))); + + /* + * need to ensure that the xtalk adress in ioe + * maps to PCI error address read from bridge. + * How to convert PCI address back to Xtalk address ? + * (better idea: convert XTalk address to PCI address + * and then do the compare!) + */ + + retval = pciio_error_handler(pcibr_vhdl, error_code, mode, ioe); + if (retval != IOERROR_HANDLED) +#ifdef colin + pcibr_device_disable(pcibr_soft, + pciio_widgetdev_slot_get( + IOERROR_GETVALUE(ioe,widgetdev))); +#else + pcibr_device_disable(pcibr_soft, + pciio_widgetdev_slot_get(-1)); +#endif + + /* + * Re-enable bridge to interrupt on BRIDGE_IRR_RESP_BUF_GRP_CLR + * NOTE: Wheather we get the interrupt on BRIDGE_IRR_RESP_BUF_GRP_CLR or + * not is dependent on INT_ENABLE register. This write just makes sure + * that if the interrupt was enabled, we do get the interrupt. + */ + bridge->b_int_rst_stat = BRIDGE_IRR_RESP_BUF_GRP_CLR; + + /* + * Also, release the "bufnum" back to buffer pool that could be re-used. + * This is done by "disabling" the buffer for a moment, then restoring + * the original assignment. + */ + + { + reg_p regp; + bridgereg_t regv; + bridgereg_t mask; + + regp = (bufnum & 1) + ? &bridge->b_odd_resp + : &bridge->b_even_resp; + + mask = 0xF << ((bufnum >> 1) * 4); + + regv = *regp; + *regp = regv & ~mask; + *regp = regv; + } + + return retval; +} + +/* + * pcibr_dmawr_error: + * Handle a dma write error caused by a device attached to this bridge. + * + * ioe has the widgetnum, widgetdev, and memaddr fields updated + * But we don't know the PCI address that corresponds to "memaddr" + * nor do we know which device driver is generating this address. + * + * There is no easy way to find out the PCI address(es) that map + * to a specific system memory address. Bus handling code is also + * of not much help, since they don't keep track of the DMA mapping + * that have been handed out. + * So it's a dead-end at this time. + * + * If translation is available, we could invoke the error handling + * interface of the device driver. + */ +/*ARGSUSED */ +int +pcibr_dmawr_error( + pcibr_soft_t pcibr_soft, + int error_code, + ioerror_mode_t mode, + ioerror_t *ioe) +{ + devfs_handle_t pcibr_vhdl = pcibr_soft->bs_vhdl; + int retval; + + retval = pciio_error_handler(pcibr_vhdl, error_code, mode, ioe); + +#ifdef IRIX + if (retval != IOERROR_HANDLED) { + pcibr_device_disable(pcibr_soft, + pciio_widgetdev_slot_get( + IOERROR_GETVALUE(ioe, widgetdev))); + + } +#endif + return retval; +} + +/* + * Bridge error handler. + * Interface to handle all errors that involve bridge in some way. + * + * This normally gets called from xtalk error handler. + * ioe has different set of fields set depending on the error that + * was encountered. So, we have a bit field indicating which of the + * fields are valid. + * + * NOTE: This routine could be operating in interrupt context. So, + * don't try to sleep here (till interrupt threads work!!) + */ +LOCAL int +pcibr_error_handler( + error_handler_arg_t einfo, + int error_code, + ioerror_mode_t mode, + ioerror_t *ioe) +{ + pcibr_soft_t pcibr_soft; + int retval = IOERROR_BADERRORCODE; + devfs_handle_t xconn_vhdl,pcibr_vhdl; +#if defined(CONFIG_SGI_IO_ERROR_HANDLING) + error_state_t e_state; +#endif + pcibr_soft = (pcibr_soft_t) einfo; + + xconn_vhdl = pcibr_soft->bs_conn; + pcibr_vhdl = pcibr_soft->bs_vhdl; + +#if defined(CONFIG_SGI_IO_ERROR_HANDLING) + e_state = error_state_get(xconn_vhdl); + + if (error_state_set(pcibr_vhdl, e_state) == + ERROR_RETURN_CODE_CANNOT_SET_STATE) + return(IOERROR_UNHANDLED); +#endif + + /* If we are in the action handling phase clean out the error state + * on the xswitch. + */ +#if defined(CONFIG_SGI_IO_ERROR_HANDLING) + if (e_state == ERROR_STATE_ACTION) + (void)error_state_set(xconn_vhdl, ERROR_STATE_NONE); +#endif + +#if DEBUG && ERROR_DEBUG + printk("%s: pcibr_error_handler\n", pcibr_soft->bs_name); +#endif + + ASSERT(pcibr_soft != NULL); + + if (error_code & IOECODE_PIO) + retval = pcibr_pioerror(pcibr_soft, error_code, mode, ioe); + + if (error_code & IOECODE_DMA) { + if (error_code & IOECODE_READ) { + /* + * DMA read error occurs when a device attached to the bridge + * tries to read some data from system memory, and this + * either results in a timeout or access error. + * First case is indicated by the bit "XREAD_REQ_TOUT" + * and second case by "RESP_XTALK_ERROR" bit in bridge error + * interrupt status register. + * + * pcibr_error_intr_handler would get invoked first, and it has + * the responsibility of calling pcibr_error_handler with + * suitable parameters. + */ + + retval = pcibr_dmard_error(pcibr_soft, error_code, MODE_DEVERROR, ioe); + } + if (error_code & IOECODE_WRITE) { + /* + * A device attached to this bridge has been generating + * bad DMA writes. Find out the device attached, and + * slap on it's wrist. + */ + + retval = pcibr_dmawr_error(pcibr_soft, error_code, MODE_DEVERROR, ioe); + } + } + return retval; + +} + +/* + * Reenable a device after handling the error. + * This is called by the lower layers when they wish to be reenabled + * after an error. + * Note that each layer would be calling the previous layer to reenable + * first, before going ahead with their own re-enabling. + */ + +int +pcibr_error_devenable(devfs_handle_t pconn_vhdl, int error_code) +{ + pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); + pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + + ASSERT(error_code & IOECODE_PIO); + + /* If the error is not known to be a write, + * we have to call devenable. + * write errors are isolated to the bridge. + */ + if (!(error_code & IOECODE_WRITE)) { + devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn; + int rc; + + rc = xtalk_error_devenable(xconn_vhdl, pciio_slot, error_code); + if (rc != IOERROR_HANDLED) + return rc; + } + pcibr_error_cleanup(pcibr_soft, error_code); + return IOERROR_HANDLED; +} + +/* ===================================================================== + * CONFIGURATION MANAGEMENT + */ +/*ARGSUSED */ +void +pcibr_provider_startup(devfs_handle_t pcibr) +{ +} + +/*ARGSUSED */ +void +pcibr_provider_shutdown(devfs_handle_t pcibr) +{ +} + +int +pcibr_reset(devfs_handle_t conn) +{ + pciio_info_t pciio_info = pciio_info_get(conn); + pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + bridge_t *bridge = pcibr_soft->bs_base; + bridgereg_t ctlreg; + unsigned cfgctl[8]; + unsigned s; + int f, nf; + pcibr_info_h pcibr_infoh; + pcibr_info_t pcibr_info; + int win; + + if (pcibr_soft->bs_slot[pciio_slot].has_host) { + pciio_slot = pcibr_soft->bs_slot[pciio_slot].host_slot; + pcibr_info = pcibr_soft->bs_slot[pciio_slot].bss_infos[0]; + } + if (pciio_slot < 4) { + s = pcibr_lock(pcibr_soft); + nf = pcibr_soft->bs_slot[pciio_slot].bss_ninfo; + pcibr_infoh = pcibr_soft->bs_slot[pciio_slot].bss_infos; + for (f = 0; f < nf; ++f) + if (pcibr_infoh[f]) + cfgctl[f] = bridge->b_type0_cfg_dev[pciio_slot].f[f].l[PCI_CFG_COMMAND / 4]; + + ctlreg = bridge->b_wid_control; + bridge->b_wid_control = ctlreg | BRIDGE_CTRL_RST(pciio_slot); + /* XXX delay? */ + bridge->b_wid_control = ctlreg; + /* XXX delay? */ + + for (f = 0; f < nf; ++f) +#ifdef IRIX + if (pcibr_info = pcibr_infoh[f]) +#else + if ((pcibr_info = pcibr_infoh[f])) +#endif + for (win = 0; win < 6; ++win) + if (pcibr_info->f_window[win].w_base != 0) + bridge->b_type0_cfg_dev[pciio_slot].f[f].l[PCI_CFG_BASE_ADDR(win) / 4] = + pcibr_info->f_window[win].w_base; + for (f = 0; f < nf; ++f) + if (pcibr_infoh[f]) + bridge->b_type0_cfg_dev[pciio_slot].f[f].l[PCI_CFG_COMMAND / 4] = cfgctl[f]; + pcibr_unlock(pcibr_soft, s); + + return 0; + } +#ifdef SUPPORT_PRINTING_V_FORMAT + PRINT_WARNING( "%v: pcibr_reset unimplemented for slot %d\n", + conn, pciio_slot); +#endif + return -1; +} + +pciio_endian_t +pcibr_endian_set(devfs_handle_t pconn_vhdl, + pciio_endian_t device_end, + pciio_endian_t desired_end) +{ + pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); + pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + bridgereg_t devreg; + unsigned s; + + /* + * Bridge supports hardware swapping; so we can always + * arrange for the caller's desired endianness. + */ + + s = pcibr_lock(pcibr_soft); + devreg = pcibr_soft->bs_slot[pciio_slot].bss_device; + if (device_end != desired_end) + devreg |= BRIDGE_DEV_SWAP_BITS; + else + devreg &= ~BRIDGE_DEV_SWAP_BITS; + + /* NOTE- if we ever put SWAP bits + * onto the disabled list, we will + * have to change the logic here. + */ + if (pcibr_soft->bs_slot[pciio_slot].bss_device != devreg) { + bridge_t *bridge = pcibr_soft->bs_base; + + bridge->b_device[pciio_slot].reg = devreg; + pcibr_soft->bs_slot[pciio_slot].bss_device = devreg; + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ + } + pcibr_unlock(pcibr_soft, s); + +#if DEBUG && PCIBR_DEV_DEBUG + printk("pcibr Device(%d): 0x%p\n", pciio_slot, bridge->b_device[pciio_slot].reg); +#endif + + return desired_end; +} + +/* This (re)sets the GBR and REALTIME bits and also keeps track of how + * many sets are outstanding. Reset succeeds only if the number of outstanding + * sets == 1. + */ +int +pcibr_priority_bits_set(pcibr_soft_t pcibr_soft, + pciio_slot_t pciio_slot, + pciio_priority_t device_prio) +{ + int s; + int *counter; + bridgereg_t rtbits = 0; + bridgereg_t devreg; + int rc = PRIO_SUCCESS; + + /* in dual-slot configurations, the host and the + * guest have separate DMA resources, so they + * have separate requirements for priority bits. + */ + + counter = &(pcibr_soft->bs_slot[pciio_slot].bss_pri_uctr); + + /* + * Bridge supports PCI notions of LOW and HIGH priority + * arbitration rings via a "REAL_TIME" bit in the per-device + * Bridge register. The "GBR" bit controls access to the GBR + * ring on the xbow. These two bits are (re)set together. + * + * XXX- Bug in Rev B Bridge Si: + * Symptom: Prefetcher starts operating incorrectly. This happens + * due to corruption of the address storage ram in the prefetcher + * when a non-real time pci request is pulled and a real-time one is + * put in it's place. Workaround: Use only a single arbitration ring + * on pci bus. GBR and RR can still be uniquely used per + * device. NETLIST MERGE DONE, WILL BE FIXED IN REV C. + */ + + if (pcibr_soft->bs_rev_num != BRIDGE_PART_REV_B) + rtbits |= BRIDGE_DEV_RT; + + /* NOTE- if we ever put DEV_RT or DEV_GBR on + * the disabled list, we will have to take + * it into account here. + */ + + s = pcibr_lock(pcibr_soft); + devreg = pcibr_soft->bs_slot[pciio_slot].bss_device; + if (device_prio == PCI_PRIO_HIGH) { +#ifdef IRIX + if (++*counter == 1) +#else + if ((++*counter == 1)) { +#endif + if (rtbits) + devreg |= rtbits; + else + rc = PRIO_FAIL; +#ifndef IRIX + } +#endif + } else if (device_prio == PCI_PRIO_LOW) { + if (*counter <= 0) + rc = PRIO_FAIL; + else if (--*counter == 0) + if (rtbits) + devreg &= ~rtbits; + } + if (pcibr_soft->bs_slot[pciio_slot].bss_device != devreg) { + bridge_t *bridge = pcibr_soft->bs_base; + + bridge->b_device[pciio_slot].reg = devreg; + pcibr_soft->bs_slot[pciio_slot].bss_device = devreg; + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ + } + pcibr_unlock(pcibr_soft, s); + + return rc; +} + +pciio_priority_t +pcibr_priority_set(devfs_handle_t pconn_vhdl, + pciio_priority_t device_prio) +{ + pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); + pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + + (void) pcibr_priority_bits_set(pcibr_soft, pciio_slot, device_prio); + + return device_prio; +} + +/* + * Interfaces to allow special (e.g. SGI) drivers to set/clear + * Bridge-specific device flags. Many flags are modified through + * PCI-generic interfaces; we don't allow them to be directly + * manipulated here. Only flags that at this point seem pretty + * Bridge-specific can be set through these special interfaces. + * We may add more flags as the need arises, or remove flags and + * create PCI-generic interfaces as the need arises. + * + * Returns 0 on failure, 1 on success + */ +int +pcibr_device_flags_set(devfs_handle_t pconn_vhdl, + pcibr_device_flags_t flags) +{ + pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); + pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + bridgereg_t set = 0; + bridgereg_t clr = 0; + + ASSERT((flags & PCIBR_DEVICE_FLAGS) == flags); + + if (flags & PCIBR_WRITE_GATHER) + set |= BRIDGE_DEV_PMU_WRGA_EN; + if (flags & PCIBR_NOWRITE_GATHER) + clr |= BRIDGE_DEV_PMU_WRGA_EN; + + if (flags & PCIBR_WRITE_GATHER) + set |= BRIDGE_DEV_DIR_WRGA_EN; + if (flags & PCIBR_NOWRITE_GATHER) + clr |= BRIDGE_DEV_DIR_WRGA_EN; + + if (flags & PCIBR_PREFETCH) + set |= BRIDGE_DEV_PREF; + if (flags & PCIBR_NOPREFETCH) + clr |= BRIDGE_DEV_PREF; + + if (flags & PCIBR_PRECISE) + set |= BRIDGE_DEV_PRECISE; + if (flags & PCIBR_NOPRECISE) + clr |= BRIDGE_DEV_PRECISE; + + if (flags & PCIBR_BARRIER) + set |= BRIDGE_DEV_BARRIER; + if (flags & PCIBR_NOBARRIER) + clr |= BRIDGE_DEV_BARRIER; + + if (flags & PCIBR_64BIT) + set |= BRIDGE_DEV_DEV_SIZE; + if (flags & PCIBR_NO64BIT) + clr |= BRIDGE_DEV_DEV_SIZE; + + if (set || clr) { + bridgereg_t devreg; + unsigned s; + + s = pcibr_lock(pcibr_soft); + devreg = pcibr_soft->bs_slot[pciio_slot].bss_device; +#ifdef IRIX + devreg = devreg & ~clr | set; +#else + devreg = (devreg & ~clr) | set; +#endif + if (pcibr_soft->bs_slot[pciio_slot].bss_device != devreg) { + bridge_t *bridge = pcibr_soft->bs_base; + + bridge->b_device[pciio_slot].reg = devreg; + pcibr_soft->bs_slot[pciio_slot].bss_device = devreg; + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ + } + pcibr_unlock(pcibr_soft, s); +#if DEBUG && PCIBR_DEV_DEBUG + printk("pcibr Device(%d): %R\n", pciio_slot, bridge->b_device[pciio_slot].regbridge->b_device[pciio_slot].reg, device_bits); +#endif + } + return (1); +} + +#ifdef LITTLE_ENDIAN +/* + * on sn-ia we need to twiddle the the addresses going out + * the pci bus because we use the unswizzled synergy space + * (the alternative is to use the swizzled synergy space + * and byte swap the data) + */ +#define CB(b,r) (((volatile uint8_t *) b)[((r)^4)]) +#define CS(b,r) (((volatile uint16_t *) b)[((r^4)/2)]) +#define CW(b,r) (((volatile uint32_t *) b)[((r^4)/4)]) +#else +#define CB(b,r) (((volatile uint8_t *) cfgbase)[(r)^3]) +#define CS(b,r) (((volatile uint16_t *) cfgbase)[((r)/2)^1]) +#define CW(b,r) (((volatile uint32_t *) cfgbase)[(r)/4]) +#endif /* LITTLE_ENDIAN */ + + +LOCAL cfg_p +pcibr_config_addr(devfs_handle_t conn, + unsigned reg) +{ + pcibr_info_t pcibr_info; + pciio_slot_t pciio_slot; + pciio_function_t pciio_func; + pcibr_soft_t pcibr_soft; + bridge_t *bridge; + cfg_p cfgbase = (cfg_p)0; + + pcibr_info = pcibr_info_get(conn); + + pciio_slot = pcibr_info->f_slot; + if (pciio_slot == PCIIO_SLOT_NONE) + pciio_slot = PCI_TYPE1_SLOT(reg); + + pciio_func = pcibr_info->f_func; + if (pciio_func == PCIIO_FUNC_NONE) + pciio_func = PCI_TYPE1_FUNC(reg); + + pcibr_soft = (pcibr_soft_t) pcibr_info->f_mfast; + + if ( (pcibr_soft_t)0 != pcibr_soft ) { + bridge = pcibr_soft->bs_base; + if ( (bridge_t *)0 != bridge ) { + cfgbase = bridge->b_type0_cfg_dev[pciio_slot].f[pciio_func].l; + } + } + + + return cfgbase; +} + +uint64_t +pcibr_config_get(devfs_handle_t conn, + unsigned reg, + unsigned size) +{ + return do_pcibr_config_get(pcibr_config_addr(conn, reg), + PCI_TYPE1_REG(reg), size); +} + +LOCAL uint64_t +do_pcibr_config_get( + cfg_p cfgbase, + unsigned reg, + unsigned size) +{ + unsigned value; + + + value = CW(cfgbase, reg); + + if (reg & 3) + value >>= 8 * (reg & 3); + if (size < 4) + value &= (1 << (8 * size)) - 1; + + return value; +} + +void +pcibr_config_set(devfs_handle_t conn, + unsigned reg, + unsigned size, + uint64_t value) +{ + do_pcibr_config_set(pcibr_config_addr(conn, reg), + PCI_TYPE1_REG(reg), size, value); +} + +LOCAL void +do_pcibr_config_set(cfg_p cfgbase, + unsigned reg, + unsigned size, + uint64_t value) +{ + switch (size) { + case 1: + CB(cfgbase, reg) = value; + break; + case 2: + if (reg & 1) { + CB(cfgbase, reg) = value; + CB(cfgbase, reg + 1) = value >> 8; + } else + CS(cfgbase, reg) = value; + break; + case 3: + if (reg & 1) { + CB(cfgbase, reg) = value; + CS(cfgbase, reg + 1) = value >> 8; + } else { + CS(cfgbase, reg) = value; + CB(cfgbase, reg + 2) = value >> 16; + } + break; + + case 4: + CW(cfgbase, reg) = value; + break; + } +} + +pciio_provider_t pcibr_provider = +{ + (pciio_piomap_alloc_f *) pcibr_piomap_alloc, + (pciio_piomap_free_f *) pcibr_piomap_free, + (pciio_piomap_addr_f *) pcibr_piomap_addr, + (pciio_piomap_done_f *) pcibr_piomap_done, + (pciio_piotrans_addr_f *) pcibr_piotrans_addr, + (pciio_piospace_alloc_f *) pcibr_piospace_alloc, + (pciio_piospace_free_f *) pcibr_piospace_free, + + (pciio_dmamap_alloc_f *) pcibr_dmamap_alloc, + (pciio_dmamap_free_f *) pcibr_dmamap_free, + (pciio_dmamap_addr_f *) pcibr_dmamap_addr, + (pciio_dmamap_list_f *) pcibr_dmamap_list, + (pciio_dmamap_done_f *) pcibr_dmamap_done, + (pciio_dmatrans_addr_f *) pcibr_dmatrans_addr, + (pciio_dmatrans_list_f *) pcibr_dmatrans_list, + (pciio_dmamap_drain_f *) pcibr_dmamap_drain, + (pciio_dmaaddr_drain_f *) pcibr_dmaaddr_drain, + (pciio_dmalist_drain_f *) pcibr_dmalist_drain, + + (pciio_intr_alloc_f *) pcibr_intr_alloc, + (pciio_intr_free_f *) pcibr_intr_free, + (pciio_intr_connect_f *) pcibr_intr_connect, + (pciio_intr_disconnect_f *) pcibr_intr_disconnect, + (pciio_intr_cpu_get_f *) pcibr_intr_cpu_get, + + (pciio_provider_startup_f *) pcibr_provider_startup, + (pciio_provider_shutdown_f *) pcibr_provider_shutdown, + (pciio_reset_f *) pcibr_reset, + (pciio_write_gather_flush_f *) pcibr_write_gather_flush, + (pciio_endian_set_f *) pcibr_endian_set, + (pciio_priority_set_f *) pcibr_priority_set, + (pciio_config_get_f *) pcibr_config_get, + (pciio_config_set_f *) pcibr_config_set, + + (pciio_error_devenable_f *) pcibr_error_devenable, + (pciio_error_extract_f *) pcibr_error_extract, +}; + +LOCAL pcibr_hints_t +pcibr_hints_get(devfs_handle_t xconn_vhdl, int alloc) +{ + arbitrary_info_t ainfo = 0; + graph_error_t rv; + pcibr_hints_t hint; + + rv = hwgraph_info_get_LBL(xconn_vhdl, INFO_LBL_PCIBR_HINTS, &ainfo); + + if (alloc && (rv != GRAPH_SUCCESS)) { + + NEW(hint); + hint->rrb_alloc_funct = NULL; + hint->ph_intr_bits = NULL; + rv = hwgraph_info_add_LBL(xconn_vhdl, + INFO_LBL_PCIBR_HINTS, + (arbitrary_info_t) hint); + if (rv != GRAPH_SUCCESS) + goto abnormal_exit; + + rv = hwgraph_info_get_LBL(xconn_vhdl, INFO_LBL_PCIBR_HINTS, &ainfo); + + if (rv != GRAPH_SUCCESS) + goto abnormal_exit; + + if (ainfo != (arbitrary_info_t) hint) + goto abnormal_exit; + } + return (pcibr_hints_t) ainfo; + +abnormal_exit: +#ifdef IRIX + printf("SHOULD NOT BE HERE\n"); +#endif + DEL(hint); + return(NULL); + +} + +void +pcibr_hints_fix_some_rrbs(devfs_handle_t xconn_vhdl, unsigned mask) +{ + pcibr_hints_t hint = pcibr_hints_get(xconn_vhdl, 1); + + if (hint) + hint->ph_rrb_fixed = mask; +#if DEBUG + else + printk("pcibr_hints_fix_rrbs: pcibr_hints_get failed at\n" + "\t%p\n", xconn_vhdl); +#endif +} + +void +pcibr_hints_fix_rrbs(devfs_handle_t xconn_vhdl) +{ + pcibr_hints_fix_some_rrbs(xconn_vhdl, 0xFF); +} + +void +pcibr_hints_dualslot(devfs_handle_t xconn_vhdl, + pciio_slot_t host, + pciio_slot_t guest) +{ + pcibr_hints_t hint = pcibr_hints_get(xconn_vhdl, 1); + + if (hint) + hint->ph_host_slot[guest] = host + 1; +#if DEBUG + else + printk("pcibr_hints_dualslot: pcibr_hints_get failed at\n" + "\t%p\n", xconn_vhdl); +#endif +} + +void +pcibr_hints_intr_bits(devfs_handle_t xconn_vhdl, + pcibr_intr_bits_f *xxx_intr_bits) +{ + pcibr_hints_t hint = pcibr_hints_get(xconn_vhdl, 1); + + if (hint) + hint->ph_intr_bits = xxx_intr_bits; +#if DEBUG + else + printk("pcibr_hints_intr_bits: pcibr_hints_get failed at\n" + "\t%p\n", xconn_vhdl); +#endif +} + +void +pcibr_set_rrb_callback(devfs_handle_t xconn_vhdl, rrb_alloc_funct_t rrb_alloc_funct) +{ + pcibr_hints_t hint = pcibr_hints_get(xconn_vhdl, 1); + + if (hint) + hint->rrb_alloc_funct = rrb_alloc_funct; +} + +void +pcibr_hints_handsoff(devfs_handle_t xconn_vhdl) +{ + pcibr_hints_t hint = pcibr_hints_get(xconn_vhdl, 1); + + if (hint) + hint->ph_hands_off = 1; +#if DEBUG + else + printk("pcibr_hints_handsoff: pcibr_hints_get failed at\n" + "\t%p\n", xconn_vhdl); +#endif +} + +void +pcibr_hints_subdevs(devfs_handle_t xconn_vhdl, + pciio_slot_t slot, + uint64_t subdevs) +{ + arbitrary_info_t ainfo = 0; + char sdname[16]; + devfs_handle_t pconn_vhdl = GRAPH_VERTEX_NONE; + + sprintf(sdname, "pci/%d", slot); + (void) hwgraph_path_add(xconn_vhdl, sdname, &pconn_vhdl); + if (pconn_vhdl == GRAPH_VERTEX_NONE) { +#if DEBUG + printk("pcibr_hints_subdevs: hwgraph_path_create failed at\n" + "\t%p (seeking %s)\n", xconn_vhdl, sdname); +#endif + return; + } + hwgraph_info_get_LBL(pconn_vhdl, INFO_LBL_SUBDEVS, &ainfo); + if (ainfo == 0) { + uint64_t *subdevp; + + NEW(subdevp); + if (!subdevp) { +#if DEBUG + printk("pcibr_hints_subdevs: subdev ptr alloc failed at\n" + "\t%p\n", pconn_vhdl); +#endif + return; + } + *subdevp = subdevs; + hwgraph_info_add_LBL(pconn_vhdl, INFO_LBL_SUBDEVS, (arbitrary_info_t) subdevp); + hwgraph_info_get_LBL(pconn_vhdl, INFO_LBL_SUBDEVS, &ainfo); + if (ainfo == (arbitrary_info_t) subdevp) + return; + DEL(subdevp); +#ifdef IRIX + if (ainfo == NULL) +#else + if (ainfo == (arbitrary_info_t) NULL) +#endif + { +#if DEBUG + printk("pcibr_hints_subdevs: null subdevs ptr at\n" + "\t%p\n", pconn_vhdl); +#endif + return; + } +#if DEBUG + printk("pcibr_subdevs_get: dup subdev add_LBL at\n" + "\t%p\n", pconn_vhdl); +#endif + } + *(uint64_t *) ainfo = subdevs; +} + + +#ifdef colin + +#include +#include + +char *pci_space[] = {"NONE", + "ROM", + "IO", + "", + "MEM", + "MEM32", + "MEM64", + "CFG", + "WIN0", + "WIN1", + "WIN2", + "WIN3", + "WIN4", + "WIN5", + "", + "BAD"}; + +void +idbg_pss_func(pcibr_info_h pcibr_infoh, int func) +{ + pcibr_info_t pcibr_info = pcibr_infoh[func]; + char name[MAXDEVNAME]; + int win; + + if (!pcibr_info) + return; + qprintf("Per-slot Function Info\n"); +#ifdef SUPPORT_PRINTING_V_FORMAT + sprintf(name, "%v", pcibr_info->f_vertex); +#endif + qprintf("\tSlot Name : %s\n",name); + qprintf("\tPCI Bus : %d ",pcibr_info->f_bus); + qprintf("Slot : %d ", pcibr_info->f_slot); + qprintf("Function : %d ", pcibr_info->f_func); + qprintf("VendorId : 0x%x " , pcibr_info->f_vendor); + qprintf("DeviceId : 0x%x\n", pcibr_info->f_device); +#ifdef SUPPORT_PRINTING_V_FORMAT + sprintf(name, "%v", pcibr_info->f_master); +#endif + qprintf("\tBus provider : %s\n",name); + qprintf("\tProvider Fns : 0x%x ", pcibr_info->f_pops); + qprintf("Error Handler : 0x%x Arg 0x%x\n", + pcibr_info->f_efunc,pcibr_info->f_einfo); + for(win = 0 ; win < 6 ; win++) + qprintf("\tBase Reg #%d space %s base 0x%x size 0x%x\n", + win,pci_space[pcibr_info->f_window[win].w_space], + pcibr_info->f_window[win].w_base, + pcibr_info->f_window[win].w_size); + + qprintf("\tRom base 0x%x size 0x%x\n", + pcibr_info->f_rbase,pcibr_info->f_rsize); + + qprintf("\tInterrupt Bit Map\n"); + qprintf("\t\tPCI Int#\tBridge Pin#\n"); + for (win = 0 ; win < 4; win++) + qprintf("\t\tINT%c\t\t%d\n",win+'A',pcibr_info->f_ibit[win]); + qprintf("\n"); +} + + +void +idbg_pss_info(pcibr_soft_t pcibr_soft, pciio_slot_t slot) +{ + pcibr_soft_slot_t pss; + char slot_conn_name[MAXDEVNAME]; + int func; + + pss = &pcibr_soft->bs_slot[slot]; + qprintf("PCI INFRASTRUCTURAL INFO FOR SLOT %d\n", slot); + qprintf("\tHost Present ? %s ", pss->has_host ? "yes" : "no"); + qprintf("\tHost Slot : %d\n",pss->host_slot); + sprintf(slot_conn_name, "%v", pss->slot_conn); + qprintf("\tSlot Conn : %s\n",slot_conn_name); + qprintf("\t#Functions : %d\n",pss->bss_ninfo); + for (func = 0; func < pss->bss_ninfo; func++) + idbg_pss_func(pss->bss_infos,func); + qprintf("\tSpace : %s ",pci_space[pss->bss_devio.bssd_space]); + qprintf("\tBase : 0x%x ", pss->bss_devio.bssd_base); + qprintf("\tShadow Devreg : 0x%x\n", pss->bss_device); + qprintf("\tUsage counts : pmu %d d32 %d d64 %d\n", + pss->bss_pmu_uctr,pss->bss_d32_uctr,pss->bss_d64_uctr); + + qprintf("\tDirect Trans Info : d64_base 0x%x d64_flags 0x%x" + "d32_base 0x%x d32_flags 0x%x\n", + pss->bss_d64_base, pss->bss_d64_flags, + pss->bss_d32_base, pss->bss_d32_flags); + + qprintf("\tExt ATEs active ? %s", + pss->bss_ext_ates_active ? "yes" : "no"); + qprintf(" Command register : 0x%x ", pss->bss_cmd_pointer); + qprintf(" Shadow command val : 0x%x\n", pss->bss_cmd_shadow); + + qprintf("\tRRB Info : Valid %d+%d Reserved %d\n", + pcibr_soft->bs_rrb_valid[slot], + pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL], + pcibr_soft->bs_rrb_res[slot]); + +} + +int ips = 0; + +void +idbg_pss(pcibr_soft_t pcibr_soft) +{ + pciio_slot_t slot; + + + if (ips >= 0 && ips < 8) + idbg_pss_info(pcibr_soft,ips); + else if (ips < 0) + for (slot = 0; slot < 8; slot++) + idbg_pss_info(pcibr_soft,slot); + else + qprintf("Invalid ips %d\n",ips); +} + +#endif /* colin */ + +int +pcibr_dma_enabled(devfs_handle_t pconn_vhdl) +{ + pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + + + return xtalk_dma_enabled(pcibr_soft->bs_conn); +} diff -urN linux-2.4.0-test10/arch/ia64/sn/io/pciio.c linux-2.4.0-test10-lia/arch/ia64/sn/io/pciio.c --- linux-2.4.0-test10/arch/ia64/sn/io/pciio.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/pciio.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,1562 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +#define USRPCI 0 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG_PCIIO +#undef DEBUG_PCIIO /* turn this on for yet more console output */ + + +#define NEW(ptr) (ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL)) +#define DEL(ptr) (kfree(ptr)) + +char pciio_info_fingerprint[] = "pciio_info"; + +cdl_p pciio_registry = NULL; + +int +badaddr_val(volatile void *addr, int len, volatile void *ptr) +{ + switch (len) { + case 4: *(volatile u32*)ptr = *(((volatile u32*)(((u64) addr)^4))); + default: printk("FIXME: argh fix badaddr_val\n"); + } + /* no such thing as a bad addr .... */ + return(0); +} + + +void +cmn_err_tag(int seqnumber, register int level, char *fmt, ...) +{ +} + +nasid_t +get_console_nasid(void) +{ +#ifdef IRIX + return console_nasid; +#else + return 0; +#endif +} + +int +hub_dma_enabled(devfs_handle_t xconn_vhdl) +{ + return(0); +} + +int +hub_error_devenable(devfs_handle_t xconn_vhdl, int devnum, int error_code) +{ + return(0); +} + +void +ioerror_dump(char *name, int error_code, int error_mode, ioerror_t *ioerror) +{ +} + +/****** + ****** end hack defines ...... + ******/ + + + + +/* ===================================================================== + * PCI Generic Bus Provider + * Implement PCI provider operations. The pciio* layer provides a + * platform-independent interface for PCI devices. This layer + * switches among the possible implementations of a PCI adapter. + */ + +/* ===================================================================== + * Provider Function Location SHORTCUT + * + * On platforms with only one possible PCI provider, macros can be + * set up at the top that cause the table lookups and indirections to + * completely disappear. + */ + +#if CONFIG_SGI_IP27 || CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 || CONFIG_IA64_GENERIC +/* + * For the moment, we will assume that IP27 + * only use Bridge ASICs to provide PCI support. + */ +#include +#define DEV_FUNC(dev,func) pcibr_##func +#define CAST_PIOMAP(x) ((pcibr_piomap_t)(x)) +#define CAST_DMAMAP(x) ((pcibr_dmamap_t)(x)) +#define CAST_INTR(x) ((pcibr_intr_t)(x)) +#endif /* CONFIG_SGI_IP27 || CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 */ + +/* ===================================================================== + * Function Table of Contents + */ + +#if !defined(DEV_FUNC) +static pciio_provider_t *pciio_to_provider_fns(devfs_handle_t dev); +#endif + +pciio_piomap_t pciio_piomap_alloc(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, size_t, unsigned); +void pciio_piomap_free(pciio_piomap_t); +caddr_t pciio_piomap_addr(pciio_piomap_t, iopaddr_t, size_t); + +void pciio_piomap_done(pciio_piomap_t); +caddr_t pciio_piotrans_addr(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, unsigned); +caddr_t pciio_pio_addr(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, pciio_piomap_t *, unsigned); + +iopaddr_t pciio_piospace_alloc(devfs_handle_t, device_desc_t, pciio_space_t, size_t, size_t); +void pciio_piospace_free(devfs_handle_t, pciio_space_t, iopaddr_t, size_t); + +pciio_dmamap_t pciio_dmamap_alloc(devfs_handle_t, device_desc_t, size_t, unsigned); +void pciio_dmamap_free(pciio_dmamap_t); +iopaddr_t pciio_dmamap_addr(pciio_dmamap_t, paddr_t, size_t); +alenlist_t pciio_dmamap_list(pciio_dmamap_t, alenlist_t, unsigned); +void pciio_dmamap_done(pciio_dmamap_t); +iopaddr_t pciio_dmatrans_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, unsigned); +alenlist_t pciio_dmatrans_list(devfs_handle_t, device_desc_t, alenlist_t, unsigned); +void pciio_dmamap_drain(pciio_dmamap_t); +void pciio_dmaaddr_drain(devfs_handle_t, paddr_t, size_t); +void pciio_dmalist_drain(devfs_handle_t, alenlist_t); +iopaddr_t pciio_dma_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, pciio_dmamap_t *, unsigned); + +pciio_intr_t pciio_intr_alloc(devfs_handle_t, device_desc_t, pciio_intr_line_t, devfs_handle_t); +void pciio_intr_free(pciio_intr_t); +int pciio_intr_connect(pciio_intr_t, intr_func_t, intr_arg_t, void *thread); +void pciio_intr_disconnect(pciio_intr_t); +devfs_handle_t pciio_intr_cpu_get(pciio_intr_t); + +void pciio_slot_func_to_name(char *, pciio_slot_t, pciio_function_t); +static pciio_info_t pciio_cardinfo_get(devfs_handle_t, pciio_slot_t); +int pciio_error_handler(devfs_handle_t, int, ioerror_mode_t, ioerror_t *); +int pciio_error_devenable(devfs_handle_t, int); + +void pciio_provider_startup(devfs_handle_t); +void pciio_provider_shutdown(devfs_handle_t); + +pciio_endian_t pciio_endian_set(devfs_handle_t, pciio_endian_t, pciio_endian_t); +pciio_priority_t pciio_priority_set(devfs_handle_t, pciio_priority_t); +devfs_handle_t pciio_intr_dev_get(pciio_intr_t); + +devfs_handle_t pciio_pio_dev_get(pciio_piomap_t); +pciio_slot_t pciio_pio_slot_get(pciio_piomap_t); +pciio_space_t pciio_pio_space_get(pciio_piomap_t); +iopaddr_t pciio_pio_pciaddr_get(pciio_piomap_t); +ulong pciio_pio_mapsz_get(pciio_piomap_t); +caddr_t pciio_pio_kvaddr_get(pciio_piomap_t); + +devfs_handle_t pciio_dma_dev_get(pciio_dmamap_t); +pciio_slot_t pciio_dma_slot_get(pciio_dmamap_t); + +pciio_info_t pciio_info_chk(devfs_handle_t); +pciio_info_t pciio_info_get(devfs_handle_t); +void pciio_info_set(devfs_handle_t, pciio_info_t); +devfs_handle_t pciio_info_dev_get(pciio_info_t); +pciio_slot_t pciio_info_slot_get(pciio_info_t); +pciio_function_t pciio_info_function_get(pciio_info_t); +pciio_vendor_id_t pciio_info_vendor_id_get(pciio_info_t); +pciio_device_id_t pciio_info_device_id_get(pciio_info_t); +devfs_handle_t pciio_info_master_get(pciio_info_t); +arbitrary_info_t pciio_info_mfast_get(pciio_info_t); +pciio_provider_t *pciio_info_pops_get(pciio_info_t); +error_handler_f *pciio_info_efunc_get(pciio_info_t); +error_handler_arg_t *pciio_info_einfo_get(pciio_info_t); +pciio_space_t pciio_info_bar_space_get(pciio_info_t, int); +iopaddr_t pciio_info_bar_base_get(pciio_info_t, int); +size_t pciio_info_bar_size_get(pciio_info_t, int); +iopaddr_t pciio_info_rom_base_get(pciio_info_t); +size_t pciio_info_rom_size_get(pciio_info_t); + +void pciio_init(void); +int pciio_attach(devfs_handle_t); + +void pciio_provider_register(devfs_handle_t, pciio_provider_t *pciio_fns); +void pciio_provider_unregister(devfs_handle_t); +pciio_provider_t *pciio_provider_fns_get(devfs_handle_t); + +int pciio_driver_register(pciio_vendor_id_t, pciio_device_id_t, char *driver_prefix, unsigned); +void pciio_driver_unregister(char *driver_prefix); + +devfs_handle_t pciio_device_register(devfs_handle_t, devfs_handle_t, pciio_slot_t, pciio_function_t, pciio_vendor_id_t, pciio_device_id_t); + +void pciio_device_unregister(devfs_handle_t); +pciio_info_t pciio_device_info_new(pciio_info_t, devfs_handle_t, pciio_slot_t, pciio_function_t, pciio_vendor_id_t, pciio_device_id_t); +void pciio_device_info_free(pciio_info_t); +devfs_handle_t pciio_device_info_register(devfs_handle_t, pciio_info_t); +void pciio_device_info_unregister(devfs_handle_t, pciio_info_t); +int pciio_device_attach(devfs_handle_t); +int pciio_device_detach(devfs_handle_t); +void pciio_error_register(devfs_handle_t, error_handler_f *, error_handler_arg_t); + +int pciio_reset(devfs_handle_t); +int pciio_write_gather_flush(devfs_handle_t); +int pciio_slot_inuse(devfs_handle_t); + +/* ===================================================================== + * Provider Function Location + * + * If there is more than one possible provider for + * this platform, we need to examine the master + * vertex of the current vertex for a provider + * function structure, and indirect through the + * appropriately named member. + */ + +#if !defined(DEV_FUNC) + +static pciio_provider_t * +pciio_to_provider_fns(devfs_handle_t dev) +{ + pciio_info_t card_info; + pciio_provider_t *provider_fns; + + card_info = pciio_info_get(dev); + ASSERT(card_info != NULL); + + provider_fns = pciio_info_pops_get(card_info); + ASSERT(provider_fns != NULL); + + return (provider_fns); +} + +#define DEV_FUNC(dev,func) pciio_to_provider_fns(dev)->func +#define CAST_PIOMAP(x) ((pciio_piomap_t)(x)) +#define CAST_DMAMAP(x) ((pciio_dmamap_t)(x)) +#define CAST_INTR(x) ((pciio_intr_t)(x)) +#endif + +/* + * Many functions are not passed their vertex + * information directly; rather, they must + * dive through a resource map. These macros + * are available to coordinate this detail. + */ +#define PIOMAP_FUNC(map,func) DEV_FUNC((map)->pp_dev,func) +#define DMAMAP_FUNC(map,func) DEV_FUNC((map)->pd_dev,func) +#define INTR_FUNC(intr_hdl,func) DEV_FUNC((intr_hdl)->pi_dev,func) + +/* ===================================================================== + * PIO MANAGEMENT + * + * For mapping system virtual address space to + * pciio space on a specified card + */ + +pciio_piomap_t +pciio_piomap_alloc(devfs_handle_t dev, /* set up mapping for this device */ + device_desc_t dev_desc, /* device descriptor */ + pciio_space_t space, /* CFG, MEM, IO, or a device-decoded window */ + iopaddr_t addr, /* lowest address (or offset in window) */ + size_t byte_count, /* size of region containing our mappings */ + size_t byte_count_max, /* maximum size of a mapping */ + unsigned flags) +{ /* defined in sys/pio.h */ + return (pciio_piomap_t) DEV_FUNC(dev, piomap_alloc) + (dev, dev_desc, space, addr, byte_count, byte_count_max, flags); +} + +void +pciio_piomap_free(pciio_piomap_t pciio_piomap) +{ + PIOMAP_FUNC(pciio_piomap, piomap_free) + (CAST_PIOMAP(pciio_piomap)); +} + +caddr_t +pciio_piomap_addr(pciio_piomap_t pciio_piomap, /* mapping resources */ + iopaddr_t pciio_addr, /* map for this pciio address */ + size_t byte_count) +{ /* map this many bytes */ + pciio_piomap->pp_kvaddr = PIOMAP_FUNC(pciio_piomap, piomap_addr) + (CAST_PIOMAP(pciio_piomap), pciio_addr, byte_count); + + return pciio_piomap->pp_kvaddr; +} + +void +pciio_piomap_done(pciio_piomap_t pciio_piomap) +{ + PIOMAP_FUNC(pciio_piomap, piomap_done) + (CAST_PIOMAP(pciio_piomap)); +} + +caddr_t +pciio_piotrans_addr(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + pciio_space_t space, /* CFG, MEM, IO, or a device-decoded window */ + iopaddr_t addr, /* starting address (or offset in window) */ + size_t byte_count, /* map this many bytes */ + unsigned flags) +{ /* (currently unused) */ + return DEV_FUNC(dev, piotrans_addr) + (dev, dev_desc, space, addr, byte_count, flags); +} + +caddr_t +pciio_pio_addr(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + pciio_space_t space, /* CFG, MEM, IO, or a device-decoded window */ + iopaddr_t addr, /* starting address (or offset in window) */ + size_t byte_count, /* map this many bytes */ + pciio_piomap_t *mapp, /* where to return the map pointer */ + unsigned flags) +{ /* PIO flags */ + pciio_piomap_t map = 0; + int errfree = 0; + caddr_t res; + + if (mapp) { + map = *mapp; /* possible pre-allocated map */ + *mapp = 0; /* record "no map used" */ + } + + res = pciio_piotrans_addr + (dev, dev_desc, space, addr, byte_count, flags); + if (res) + return res; /* pciio_piotrans worked */ + + if (!map) { + map = pciio_piomap_alloc + (dev, dev_desc, space, addr, byte_count, byte_count, flags); + if (!map) + return res; /* pciio_piomap_alloc failed */ + errfree = 1; + } + + res = pciio_piomap_addr + (map, addr, byte_count); + if (!res) { + if (errfree) + pciio_piomap_free(map); + return res; /* pciio_piomap_addr failed */ + } + if (mapp) + *mapp = map; /* pass back map used */ + + return res; /* pciio_piomap_addr succeeded */ +} + +iopaddr_t +pciio_piospace_alloc(devfs_handle_t dev, /* Device requiring space */ + device_desc_t dev_desc, /* Device descriptor */ + pciio_space_t space, /* MEM32/MEM64/IO */ + size_t byte_count, /* Size of mapping */ + size_t align) +{ /* Alignment needed */ + if (align < NBPP) + align = NBPP; + return DEV_FUNC(dev, piospace_alloc) + (dev, dev_desc, space, byte_count, align); +} + +void +pciio_piospace_free(devfs_handle_t dev, /* Device freeing space */ + pciio_space_t space, /* Type of space */ + iopaddr_t pciaddr, /* starting address */ + size_t byte_count) +{ /* Range of address */ + DEV_FUNC(dev, piospace_free) + (dev, space, pciaddr, byte_count); +} + +/* ===================================================================== + * DMA MANAGEMENT + * + * For mapping from pci space to system + * physical space. + */ + +pciio_dmamap_t +pciio_dmamap_alloc(devfs_handle_t dev, /* set up mappings for this device */ + device_desc_t dev_desc, /* device descriptor */ + size_t byte_count_max, /* max size of a mapping */ + unsigned flags) +{ /* defined in dma.h */ + return (pciio_dmamap_t) DEV_FUNC(dev, dmamap_alloc) + (dev, dev_desc, byte_count_max, flags); +} + +void +pciio_dmamap_free(pciio_dmamap_t pciio_dmamap) +{ + DMAMAP_FUNC(pciio_dmamap, dmamap_free) + (CAST_DMAMAP(pciio_dmamap)); +} + +iopaddr_t +pciio_dmamap_addr(pciio_dmamap_t pciio_dmamap, /* use these mapping resources */ + paddr_t paddr, /* map for this address */ + size_t byte_count) +{ /* map this many bytes */ + return DMAMAP_FUNC(pciio_dmamap, dmamap_addr) + (CAST_DMAMAP(pciio_dmamap), paddr, byte_count); +} + +alenlist_t +pciio_dmamap_list(pciio_dmamap_t pciio_dmamap, /* use these mapping resources */ + alenlist_t alenlist, /* map this Address/Length List */ + unsigned flags) +{ + return DMAMAP_FUNC(pciio_dmamap, dmamap_list) + (CAST_DMAMAP(pciio_dmamap), alenlist, flags); +} + +void +pciio_dmamap_done(pciio_dmamap_t pciio_dmamap) +{ + DMAMAP_FUNC(pciio_dmamap, dmamap_done) + (CAST_DMAMAP(pciio_dmamap)); +} + +iopaddr_t +pciio_dmatrans_addr(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + paddr_t paddr, /* system physical address */ + size_t byte_count, /* length */ + unsigned flags) +{ /* defined in dma.h */ + return DEV_FUNC(dev, dmatrans_addr) + (dev, dev_desc, paddr, byte_count, flags); +} + +alenlist_t +pciio_dmatrans_list(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + alenlist_t palenlist, /* system address/length list */ + unsigned flags) +{ /* defined in dma.h */ + return DEV_FUNC(dev, dmatrans_list) + (dev, dev_desc, palenlist, flags); +} + +iopaddr_t +pciio_dma_addr(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + paddr_t paddr, /* system physical address */ + size_t byte_count, /* length */ + pciio_dmamap_t *mapp, /* map to use, then map we used */ + unsigned flags) +{ /* PIO flags */ + pciio_dmamap_t map = 0; + int errfree = 0; + iopaddr_t res; + + if (mapp) { + map = *mapp; /* possible pre-allocated map */ + *mapp = 0; /* record "no map used" */ + } + + res = pciio_dmatrans_addr + (dev, dev_desc, paddr, byte_count, flags); + if (res) + return res; /* pciio_dmatrans worked */ + + if (!map) { + map = pciio_dmamap_alloc + (dev, dev_desc, byte_count, flags); + if (!map) + return res; /* pciio_dmamap_alloc failed */ + errfree = 1; + } + + res = pciio_dmamap_addr + (map, paddr, byte_count); + if (!res) { + if (errfree) + pciio_dmamap_free(map); + return res; /* pciio_dmamap_addr failed */ + } + if (mapp) + *mapp = map; /* pass back map used */ + + return res; /* pciio_dmamap_addr succeeded */ +} + +void +pciio_dmamap_drain(pciio_dmamap_t map) +{ + DMAMAP_FUNC(map, dmamap_drain) + (CAST_DMAMAP(map)); +} + +void +pciio_dmaaddr_drain(devfs_handle_t dev, paddr_t addr, size_t size) +{ + DEV_FUNC(dev, dmaaddr_drain) + (dev, addr, size); +} + +void +pciio_dmalist_drain(devfs_handle_t dev, alenlist_t list) +{ + DEV_FUNC(dev, dmalist_drain) + (dev, list); +} + +/* ===================================================================== + * INTERRUPT MANAGEMENT + * + * Allow crosstalk devices to establish interrupts + */ + +/* + * Allocate resources required for an interrupt as specified in intr_desc. + * Return resource handle in intr_hdl. + */ +pciio_intr_t +pciio_intr_alloc(devfs_handle_t dev, /* which Crosstalk device */ + device_desc_t dev_desc, /* device descriptor */ + pciio_intr_line_t lines, /* INTR line(s) to attach */ + devfs_handle_t owner_dev) +{ /* owner of this interrupt */ + return (pciio_intr_t) DEV_FUNC(dev, intr_alloc) + (dev, dev_desc, lines, owner_dev); +} + +/* + * Free resources consumed by intr_alloc. + */ +void +pciio_intr_free(pciio_intr_t intr_hdl) +{ + INTR_FUNC(intr_hdl, intr_free) + (CAST_INTR(intr_hdl)); +} + +/* + * Associate resources allocated with a previous pciio_intr_alloc call with the + * described handler, arg, name, etc. + * + * Returns 0 on success, returns <0 on failure. + */ +int +pciio_intr_connect(pciio_intr_t intr_hdl, /* pciio intr resource handle */ + intr_func_t intr_func, /* pciio intr handler */ + intr_arg_t intr_arg, /* arg to intr handler */ + void *thread) +{ /* intr thread to use */ + return INTR_FUNC(intr_hdl, intr_connect) + (CAST_INTR(intr_hdl), intr_func, intr_arg, thread); +} + +/* + * Disassociate handler with the specified interrupt. + */ +void +pciio_intr_disconnect(pciio_intr_t intr_hdl) +{ + INTR_FUNC(intr_hdl, intr_disconnect) + (CAST_INTR(intr_hdl)); +} + +/* + * Return a hwgraph vertex that represents the CPU currently + * targeted by an interrupt. + */ +devfs_handle_t +pciio_intr_cpu_get(pciio_intr_t intr_hdl) +{ + return INTR_FUNC(intr_hdl, intr_cpu_get) + (CAST_INTR(intr_hdl)); +} + +/* ===================================================================== + * ERROR MANAGEMENT + */ + +void +pciio_slot_func_to_name(char *name, + pciio_slot_t slot, + pciio_function_t func) +{ + /* + * standard connection points: + * + * PCIIO_SLOT_NONE: .../pci/direct + * PCIIO_FUNC_NONE: .../pci/ ie. .../pci/3 + * multifunction: .../pci/ ie. .../pci/3c + */ + + if (slot == PCIIO_SLOT_NONE) + sprintf(name, "direct"); + else if (func == PCIIO_FUNC_NONE) + sprintf(name, "%d", slot); + else + sprintf(name, "%d%c", slot, 'a'+func); +} + +/* + * pciio_cardinfo_get + * + * Get the pciio info structure corresponding to the + * specified PCI "slot" (we like it when the same index + * number is used for the PCI IDSEL, the REQ/GNT pair, + * and the interrupt line being used for INTA. We like + * it so much we call it the slot number). + */ +static pciio_info_t +pciio_cardinfo_get( + devfs_handle_t pciio_vhdl, + pciio_slot_t pci_slot) +{ + char namebuf[16]; + pciio_info_t info = 0; + devfs_handle_t conn; + + pciio_slot_func_to_name(namebuf, pci_slot, PCIIO_FUNC_NONE); + if (GRAPH_SUCCESS == + hwgraph_traverse(pciio_vhdl, namebuf, &conn)) { + info = pciio_info_chk(conn); + hwgraph_vertex_unref(conn); + } + + return info; +} + +/* + * pciio_error_handler: + * dispatch an error to the appropriate + * pciio connection point, or process + * it as a generic pci error. + * Yes, the first parameter is the + * provider vertex at the middle of + * the bus; we get to the pciio connect + * point using the ioerror widgetdev field. + * + * This function is called by the + * specific PCI provider, after it has figured + * out where on the PCI bus (including which slot, + * if it can tell) the error came from. + */ +/*ARGSUSED */ +int +pciio_error_handler( + devfs_handle_t pciio_vhdl, + int error_code, + ioerror_mode_t mode, + ioerror_t *ioerror) +{ + pciio_info_t pciio_info; + devfs_handle_t pconn_vhdl; +#if USRPCI + devfs_handle_t usrpci_v; +#endif + pciio_slot_t slot; + + int retval; +#if defined(CONFIG_SGI_IO_ERROR_HANDLING) + error_state_t e_state; +#endif + +#ifdef IRIX +#if DEBUG && ERROR_DEBUG + cmn_err(CE_CONT, "%v: pciio_error_handler\n", pciio_vhdl); +#endif +#endif + + IOERR_PRINTF(cmn_err(CE_NOTE, + "%v: PCI Bus Error: Error code: %d Error mode: %d\n", + pciio_vhdl, error_code, mode)); + + /* If there is an error handler sitting on + * the "no-slot" connection point, give it + * first crack at the error. NOTE: it is + * quite possible that this function may + * do further refining of the ioerror. + */ + pciio_info = pciio_cardinfo_get(pciio_vhdl, PCIIO_SLOT_NONE); + if (pciio_info && pciio_info->c_efunc) { + pconn_vhdl = pciio_info_dev_get(pciio_info); +#if defined(CONFIG_SGI_IO_ERROR_HANDLING) + e_state = error_state_get(pciio_vhdl); + + if (e_state == ERROR_STATE_ACTION) + (void)error_state_set(pciio_vhdl, ERROR_STATE_NONE); + + if (error_state_set(pconn_vhdl,e_state) == + ERROR_RETURN_CODE_CANNOT_SET_STATE) + return(IOERROR_UNHANDLED); +#endif + retval = pciio_info->c_efunc + (pciio_info->c_einfo, error_code, mode, ioerror); + if (retval != IOERROR_UNHANDLED) + return retval; + } + + /* Is the error associated with a particular slot? + */ + if (IOERROR_FIELDVALID(ioerror, widgetdev)) { + /* + * NOTE : + * widgetdev is a 4byte value encoded as slot in the higher order + * 2 bytes and function in the lower order 2 bytes. + */ +#ifdef IRIX + slot = pciio_widgetdev_slot_get(IOERROR_GETVALUE(ioerror, widgetdev)); +#else + slot = 0; +#endif + + /* If this slot has an error handler, + * deliver the error to it. + */ + pciio_info = pciio_cardinfo_get(pciio_vhdl, slot); + if (pciio_info != NULL) { + if (pciio_info->c_efunc != NULL) { + + pconn_vhdl = pciio_info_dev_get(pciio_info); +#if defined(CONFIG_SGI_IO_ERROR_HANDLING) + e_state = error_state_get(pciio_vhdl); + + if (e_state == ERROR_STATE_ACTION) + (void)error_state_set(pciio_vhdl, ERROR_STATE_NONE); + + if (error_state_set(pconn_vhdl,e_state) == + ERROR_RETURN_CODE_CANNOT_SET_STATE) + return(IOERROR_UNHANDLED); +#endif + retval = pciio_info->c_efunc + (pciio_info->c_einfo, error_code, mode, ioerror); + if (retval != IOERROR_UNHANDLED) + return retval; + } + +#if USRPCI + /* If the USRPCI driver is available and + * knows about this connection point, + * deliver the error to it. + * + * OK to use pconn_vhdl here, even though we + * have already UNREF'd it, since we know that + * it is not going away. + */ + pconn_vhdl = pciio_info_dev_get(pciio_info); + if (GRAPH_SUCCESS == + hwgraph_traverse(pconn_vhdl, EDGE_LBL_USRPCI, &usrpci_v)) { + retval = usrpci_error_handler + (usrpci_v, error_code, IOERROR_GETVALUE(ioerror, busaddr)); + hwgraph_vertex_unref(usrpci_v); + if (retval != IOERROR_UNHANDLED) { + /* + * This unref is not needed. If this code is called often enough, + * the system will crash, due to vertex reference count reaching 0, + * causing vertex to be unallocated. -jeremy + * hwgraph_vertex_unref(pconn_vhdl); + */ + return retval; + } + } +#endif + } + } + + return (mode == MODE_DEVPROBE) + ? IOERROR_HANDLED /* probes are OK */ + : IOERROR_UNHANDLED; /* otherwise, foo! */ +} + +int +pciio_error_devenable(devfs_handle_t pconn_vhdl, int error_code) +{ + return DEV_FUNC(pconn_vhdl, error_devenable) + (pconn_vhdl, error_code); + /* no cleanup specific to this layer. */ +} + +/* ===================================================================== + * CONFIGURATION MANAGEMENT + */ + +/* + * Startup a crosstalk provider + */ +void +pciio_provider_startup(devfs_handle_t pciio_provider) +{ + DEV_FUNC(pciio_provider, provider_startup) + (pciio_provider); +} + +/* + * Shutdown a crosstalk provider + */ +void +pciio_provider_shutdown(devfs_handle_t pciio_provider) +{ + DEV_FUNC(pciio_provider, provider_shutdown) + (pciio_provider); +} + +/* + * Specify endianness constraints. The driver tells us what the device + * does and how it would like to see things in memory. We reply with + * how things will actually appear in memory. + */ +pciio_endian_t +pciio_endian_set(devfs_handle_t dev, + pciio_endian_t device_end, + pciio_endian_t desired_end) +{ + ASSERT((device_end == PCIDMA_ENDIAN_BIG) || (device_end == PCIDMA_ENDIAN_LITTLE)); + ASSERT((desired_end == PCIDMA_ENDIAN_BIG) || (desired_end == PCIDMA_ENDIAN_LITTLE)); + +#if DEBUG + cmn_err(CE_ALERT, + "%v: pciio_endian_set is going away.\n" + "\tplease use PCIIO_BYTE_STREAM or PCIIO_WORD_VALUES in your\n" + "\tpciio_dmamap_alloc and pciio_dmatrans calls instead.\n", + dev); +#endif + + return DEV_FUNC(dev, endian_set) + (dev, device_end, desired_end); +} + +/* + * Specify PCI arbitration priority. + */ +pciio_priority_t +pciio_priority_set(devfs_handle_t dev, + pciio_priority_t device_prio) +{ + ASSERT((device_prio == PCI_PRIO_HIGH) || (device_prio == PCI_PRIO_LOW)); + + return DEV_FUNC(dev, priority_set) + (dev, device_prio); +} + +/* + * Read value of configuration register + */ +uint64_t +pciio_config_get(devfs_handle_t dev, + unsigned reg, + unsigned size) +{ + uint64_t value = 0; + unsigned shift = 0; + + /* handle accesses that cross words here, + * since that's common code between all + * possible providers. + */ + while (size > 0) { + unsigned biw = 4 - (reg&3); + if (biw > size) + biw = size; + + value |= DEV_FUNC(dev, config_get) + (dev, reg, biw) << shift; + + shift += 8*biw; + reg += biw; + size -= biw; + } + return value; +} + +/* + * Change value of configuration register + */ +void +pciio_config_set(devfs_handle_t dev, + unsigned reg, + unsigned size, + uint64_t value) +{ + /* handle accesses that cross words here, + * since that's common code between all + * possible providers. + */ + while (size > 0) { + unsigned biw = 4 - (reg&3); + if (biw > size) + biw = size; + + DEV_FUNC(dev, config_set) + (dev, reg, biw, value); + reg += biw; + size -= biw; + value >>= biw * 8; + } +} + +/* ===================================================================== + * GENERIC PCI SUPPORT FUNCTIONS + */ +pciio_slot_t +pciio_error_extract(devfs_handle_t dev, + pciio_space_t *space, + iopaddr_t *offset) +{ + ASSERT(dev != NODEV); + return DEV_FUNC(dev,error_extract)(dev,space,offset); +} + +/* + * Issue a hardware reset to a card. + */ +int +pciio_reset(devfs_handle_t dev) +{ + return DEV_FUNC(dev, reset) (dev); +} + +/* + * flush write gather buffers + */ +int +pciio_write_gather_flush(devfs_handle_t dev) +{ + return DEV_FUNC(dev, write_gather_flush) (dev); +} + +devfs_handle_t +pciio_intr_dev_get(pciio_intr_t pciio_intr) +{ + return (pciio_intr->pi_dev); +} + +/****** Generic crosstalk pio interfaces ******/ +devfs_handle_t +pciio_pio_dev_get(pciio_piomap_t pciio_piomap) +{ + return (pciio_piomap->pp_dev); +} + +pciio_slot_t +pciio_pio_slot_get(pciio_piomap_t pciio_piomap) +{ + return (pciio_piomap->pp_slot); +} + +pciio_space_t +pciio_pio_space_get(pciio_piomap_t pciio_piomap) +{ + return (pciio_piomap->pp_space); +} + +iopaddr_t +pciio_pio_pciaddr_get(pciio_piomap_t pciio_piomap) +{ + return (pciio_piomap->pp_pciaddr); +} + +ulong +pciio_pio_mapsz_get(pciio_piomap_t pciio_piomap) +{ + return (pciio_piomap->pp_mapsz); +} + +caddr_t +pciio_pio_kvaddr_get(pciio_piomap_t pciio_piomap) +{ + return (pciio_piomap->pp_kvaddr); +} + +/****** Generic crosstalk dma interfaces ******/ +devfs_handle_t +pciio_dma_dev_get(pciio_dmamap_t pciio_dmamap) +{ + return (pciio_dmamap->pd_dev); +} + +pciio_slot_t +pciio_dma_slot_get(pciio_dmamap_t pciio_dmamap) +{ + return (pciio_dmamap->pd_slot); +} + +/****** Generic pci slot information interfaces ******/ + +pciio_info_t +pciio_info_chk(devfs_handle_t pciio) +{ + arbitrary_info_t ainfo = 0; + + hwgraph_info_get_LBL(pciio, INFO_LBL_PCIIO, &ainfo); + return (pciio_info_t) ainfo; +} + +pciio_info_t +pciio_info_get(devfs_handle_t pciio) +{ + pciio_info_t pciio_info; + + pciio_info = (pciio_info_t) hwgraph_fastinfo_get(pciio); + +#ifdef DEBUG_PCIIO + { + int pos; + char dname[256]; + pos = devfs_generate_path(pciio, dname, 256); + printk("%s : path= %s\n", __FUNCTION__, &dname[pos]); + } +#endif /* DEBUG_PCIIO */ + +#ifdef BRINGUP + if ((pciio_info != NULL) && + (pciio_info->c_fingerprint != pciio_info_fingerprint) + && (pciio_info->c_fingerprint != NULL)) { +#else + if ((pciio_info != NULL) && + (pciio_info->c_fingerprint != pciio_info_fingerprint)) { +#endif /* BRINGUP */ + + printk("pciio_info_get: Found fastinfo 0x%p but wrong fingerprint %s\n", pciio_info, + pciio_info->c_fingerprint); + return((pciio_info_t)-1); /* Should panic .. */ + } + + + return pciio_info; +} + +void +pciio_info_set(devfs_handle_t pciio, pciio_info_t pciio_info) +{ + if (pciio_info != NULL) + pciio_info->c_fingerprint = pciio_info_fingerprint; + hwgraph_fastinfo_set(pciio, (arbitrary_info_t) pciio_info); + + /* Also, mark this vertex as a PCI slot + * and use the pciio_info, so pciio_info_chk + * can work (and be fairly efficient). + */ + hwgraph_info_add_LBL(pciio, INFO_LBL_PCIIO, + (arbitrary_info_t) pciio_info); +} + +devfs_handle_t +pciio_info_dev_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_vertex); +} + +/*ARGSUSED*/ +pciio_bus_t +pciio_info_bus_get(pciio_info_t pciio_info) +{ + /* XXX for now O2 always gets back bus 0 */ + return (pciio_bus_t)0; +} + +pciio_slot_t +pciio_info_slot_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_slot); +} + +pciio_function_t +pciio_info_function_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_func); +} + +pciio_vendor_id_t +pciio_info_vendor_id_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_vendor); +} + +pciio_device_id_t +pciio_info_device_id_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_device); +} + +devfs_handle_t +pciio_info_master_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_master); +} + +arbitrary_info_t +pciio_info_mfast_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_mfast); +} + +pciio_provider_t * +pciio_info_pops_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_pops); +} + +error_handler_f * +pciio_info_efunc_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_efunc); +} + +error_handler_arg_t * +pciio_info_einfo_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_einfo); +} + +pciio_space_t +pciio_info_bar_space_get(pciio_info_t info, int win) +{ + return info->c_window[win].w_space; +} + +iopaddr_t +pciio_info_bar_base_get(pciio_info_t info, int win) +{ + return info->c_window[win].w_base; +} + +size_t +pciio_info_bar_size_get(pciio_info_t info, int win) +{ + return info->c_window[win].w_size; +} + +iopaddr_t +pciio_info_rom_base_get(pciio_info_t info) +{ + return info->c_rbase; +} + +size_t +pciio_info_rom_size_get(pciio_info_t info) +{ + return info->c_rsize; +} + + +/* ===================================================================== + * GENERIC PCI INITIALIZATION FUNCTIONS + */ + +/* + * pciioinit: called once during device driver + * initializtion if this driver is configured into + * the system. + */ +void +pciio_init(void) +{ + cdl_p cp; + +#if DEBUG && ATTACH_DEBUG + printf("pciio_init\n"); +#endif + /* Allocate the registry. + * We might already have one. + * If we don't, go get one. + * MPness: someone might have + * set one up for us while we + * were not looking; use an atomic + * compare-and-swap to commit to + * using the new registry if and + * only if nobody else did first. + * If someone did get there first, + * toss the one we allocated back + * into the pool. + */ + if (pciio_registry == NULL) { + cp = cdl_new(EDGE_LBL_PCI, "vendor", "device"); + if (!compare_and_swap_ptr((void **) &pciio_registry, NULL, (void *) cp)) { + cdl_del(cp); + } + } + ASSERT(pciio_registry != NULL); +} + +/* + * pciioattach: called for each vertex in the graph + * that is a PCI provider. + */ +/*ARGSUSED */ +int +pciio_attach(devfs_handle_t pciio) +{ +#if DEBUG && ATTACH_DEBUG + cmn_err(CE_CONT, "%v: pciio_attach\n", pciio); +#endif + return 0; +} + +/* + * Associate a set of pciio_provider functions with a vertex. + */ +void +pciio_provider_register(devfs_handle_t provider, pciio_provider_t *pciio_fns) +{ + hwgraph_info_add_LBL(provider, INFO_LBL_PFUNCS, (arbitrary_info_t) pciio_fns); +} + +/* + * Disassociate a set of pciio_provider functions with a vertex. + */ +void +pciio_provider_unregister(devfs_handle_t provider) +{ + arbitrary_info_t ainfo; + +#ifdef IRIX + hwgraph_info_remove_LBL(provider, INFO_LBL_PFUNCS, &ainfo); +#else + hwgraph_info_remove_LBL(provider, INFO_LBL_PFUNCS, (long *) &ainfo); +#endif +} + +/* + * Obtain a pointer to the pciio_provider functions for a specified Crosstalk + * provider. + */ +pciio_provider_t * +pciio_provider_fns_get(devfs_handle_t provider) +{ + arbitrary_info_t ainfo = 0; + + (void) hwgraph_info_get_LBL(provider, INFO_LBL_PFUNCS, &ainfo); + return (pciio_provider_t *) ainfo; +} + +/*ARGSUSED4 */ +int +pciio_driver_register( + pciio_vendor_id_t vendor_id, + pciio_device_id_t device_id, + char *driver_prefix, + unsigned flags) +{ + /* a driver's init routine might call + * pciio_driver_register before the + * system calls pciio_init; so we + * make the init call ourselves here. + */ + if (pciio_registry == NULL) + pciio_init(); + + return cdl_add_driver(pciio_registry, + vendor_id, device_id, + driver_prefix, flags); +} + +/* + * Remove an initialization function. + */ +void +pciio_driver_unregister( + char *driver_prefix) +{ + /* before a driver calls unregister, + * it must have called register; so + * we can assume we have a registry here. + */ + ASSERT(pciio_registry != NULL); + + cdl_del_driver(pciio_registry, driver_prefix); +} + +/* + * Call some function with each vertex that + * might be one of this driver's attach points. + */ +void +pciio_iterate(char *driver_prefix, + pciio_iter_f * func) +{ + /* a driver's init routine might call + * pciio_iterate before the + * system calls pciio_init; so we + * make the init call ourselves here. + */ + if (pciio_registry == NULL) + pciio_init(); + + ASSERT(pciio_registry != NULL); + + cdl_iterate(pciio_registry, driver_prefix, (cdl_iter_f *) func); +} + +devfs_handle_t +pciio_device_register( + devfs_handle_t connectpt, /* vertex for /hw/.../pciio/%d */ + devfs_handle_t master, /* card's master ASIC (PCI provider) */ + pciio_slot_t slot, /* card's slot */ + pciio_function_t func, /* card's func */ + pciio_vendor_id_t vendor_id, + pciio_device_id_t device_id) +{ + + return pciio_device_info_register + (connectpt, pciio_device_info_new (NULL, master, slot, func, + vendor_id, device_id)); +} + +void +pciio_device_unregister(devfs_handle_t pconn) +{ + DEV_FUNC(pconn,device_unregister)(pconn); +} + +pciio_info_t +pciio_device_info_new( + pciio_info_t pciio_info, + devfs_handle_t master, + pciio_slot_t slot, + pciio_function_t func, + pciio_vendor_id_t vendor_id, + pciio_device_id_t device_id) +{ + if (!pciio_info) + NEW(pciio_info); + ASSERT(pciio_info != NULL); + + pciio_info->c_slot = slot; + pciio_info->c_func = func; + pciio_info->c_vendor = vendor_id; + pciio_info->c_device = device_id; + pciio_info->c_master = master; + pciio_info->c_mfast = hwgraph_fastinfo_get(master); + pciio_info->c_pops = pciio_provider_fns_get(master); + pciio_info->c_efunc = 0; + pciio_info->c_einfo = 0; + + return pciio_info; +} + +void +pciio_device_info_free(pciio_info_t pciio_info) +{ + /* NOTE : pciio_info is a structure within the pcibr_info + * and not a pointer to memory allocated on the heap !! + */ + BZERO((char *)pciio_info,sizeof(pciio_info)); +} + +devfs_handle_t +pciio_device_info_register( + devfs_handle_t connectpt, /* vertex at center of bus */ + pciio_info_t pciio_info) /* details about the connectpt */ +{ + char name[32]; + devfs_handle_t pconn; + + pciio_slot_func_to_name(name, + pciio_info->c_slot, + pciio_info->c_func); + + printk("pciio_device_info_register: connectpt 0x%p, pciio_info 0x%p\n", connectpt, pciio_info); + + if (GRAPH_SUCCESS != + hwgraph_path_add(connectpt, name, &pconn)) + return pconn; + + pciio_info->c_vertex = pconn; + pciio_info_set(pconn, pciio_info); +#ifdef BRINGUP + { + int pos; + char dname[256]; + pos = devfs_generate_path(pconn, dname, 256); + printk("%s : pconn path= %s \n", __FUNCTION__, &dname[pos]); + } +#endif /* BRINGUP */ + + /* + * create link to our pci provider + */ + + device_master_set(pconn, pciio_info->c_master); + +#if USRPCI + /* + * Call into usrpci provider to let it initialize for + * the given slot. + */ + if (pciio_info->c_slot != PCIIO_SLOT_NONE) + usrpci_device_register(pconn, pciio_info->c_master, pciio_info->c_slot); +#endif + + return pconn; +} + +void +pciio_device_info_unregister(devfs_handle_t connectpt, + pciio_info_t pciio_info) +{ + char name[32]; + devfs_handle_t pconn; + + if (!pciio_info) + return; + + pciio_slot_func_to_name(name, + pciio_info->c_slot, + pciio_info->c_func); + + hwgraph_edge_remove(connectpt,name,&pconn); + pciio_info_set(pconn,0); + + /* Remove the link to our pci provider */ + hwgraph_edge_remove(pconn, EDGE_LBL_MASTER, NULL); + + hwgraph_vertex_unref(pconn); + hwgraph_vertex_destroy(pconn); + +} +/* Add the pci card inventory information to the hwgraph + */ +static void +pciio_device_inventory_add(devfs_handle_t pconn_vhdl) +{ + pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); + + ASSERT(pciio_info); + ASSERT(pciio_info->c_vertex == pconn_vhdl); + + /* Donot add inventory for non-existent devices */ + if ((pciio_info->c_vendor == PCIIO_VENDOR_ID_NONE) || + (pciio_info->c_device == PCIIO_DEVICE_ID_NONE)) + return; + device_inventory_add(pconn_vhdl,INV_IOBD,INV_PCIADAP, + pciio_info->c_vendor,pciio_info->c_device, + pciio_info->c_slot); +} + +static void +pciio_device_inventory_remove(devfs_handle_t pconn_vhdl) +{ +#ifdef IRIX + hwgraph_inventory_remove(pconn_vhdl,-1,-1,-1,-1,-1); +#endif +} + +/*ARGSUSED */ +int +pciio_device_attach(devfs_handle_t pconn) +{ + pciio_info_t pciio_info; + pciio_vendor_id_t vendor_id; + pciio_device_id_t device_id; + + pciio_device_inventory_add(pconn); + pciio_info = pciio_info_get(pconn); + + vendor_id = pciio_info->c_vendor; + device_id = pciio_info->c_device; + + printk("pciio_device_attach: Function 0x%p, vendor 0x%x, device_id %x\n", pconn, vendor_id, device_id); + + /* we don't start attaching things until + * all the driver init routines (including + * pciio_init) have been called; so we + * can assume here that we have a registry. + */ + ASSERT(pciio_registry != NULL); + + return(cdl_add_connpt(pciio_registry, vendor_id, device_id, pconn)); + +} + +int +pciio_device_detach(devfs_handle_t pconn) +{ + pciio_info_t pciio_info; + pciio_vendor_id_t vendor_id; + pciio_device_id_t device_id; + + pciio_device_inventory_remove(pconn); + pciio_info = pciio_info_get(pconn); + + vendor_id = pciio_info->c_vendor; + device_id = pciio_info->c_device; + + /* we don't start attaching things until + * all the driver init routines (including + * pciio_init) have been called; so we + * can assume here that we have a registry. + */ + ASSERT(pciio_registry != NULL); + + cdl_del_connpt(pciio_registry, vendor_id, device_id, pconn); + + return(0); + +} + +/* + * pciio_error_register: + * arrange for a function to be called with + * a specified first parameter plus other + * information when an error is encountered + * and traced to the pci slot corresponding + * to the connection point pconn. + * + * may also be called with a null function + * pointer to "unregister" the error handler. + * + * NOTE: subsequent calls silently overwrite + * previous data for this vertex. We assume that + * cooperating drivers, well, cooperate ... + */ +void +pciio_error_register(devfs_handle_t pconn, + error_handler_f *efunc, + error_handler_arg_t einfo) +{ + pciio_info_t pciio_info; + + pciio_info = pciio_info_get(pconn); + ASSERT(pciio_info != NULL); + pciio_info->c_efunc = efunc; + pciio_info->c_einfo = einfo; +} + +/* + * Check if any device has been found in this slot, and return + * true or false + * vhdl is the vertex for the slot + */ +int +pciio_slot_inuse(devfs_handle_t pconn_vhdl) +{ + pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); + + ASSERT(pciio_info); + ASSERT(pciio_info->c_vertex == pconn_vhdl); + if (pciio_info->c_vendor) { + /* + * Non-zero value for vendor indicate + * a board being found in this slot. + */ + return 1; + } + return 0; +} + +int +pciio_dma_enabled(devfs_handle_t pconn_vhdl) +{ + return DEV_FUNC(pconn_vhdl, dma_enabled)(pconn_vhdl); +} diff -urN linux-2.4.0-test10/arch/ia64/sn/io/sgi_if.c linux-2.4.0-test10-lia/arch/ia64/sn/io/sgi_if.c --- linux-2.4.0-test10/arch/ia64/sn/io/sgi_if.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/sgi_if.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,73 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define spinlock_init(x,name) mutex_init(x, MUTEX_DEFAULT, name); + +void * +kmem_zalloc(size_t size, int flag) +{ + void *ptr = kmalloc(size, GFP_KERNEL); + BZERO(ptr, size); + return ptr; +} + +#define xtod(c) ((c) <= '9' ? '0' - (c) : 'a' - (c) - 10) +long +atoi(register char *p) +{ + register long n; + register int c, neg = 0; + + if (p == NULL) + return 0; + + if (!isdigit(c = *p)) { + while (isspace(c)) + c = *++p; + switch (c) { + case '-': + neg++; + case '+': /* fall-through */ + c = *++p; + } + if (!isdigit(c)) + return (0); + } + if (c == '0' && *(p + 1) == 'x') { + p += 2; + c = *p; + n = xtod(c); + while ((c = *++p) && isxdigit(c)) { + n *= 16; /* two steps to avoid unnecessary overflow */ + n += xtod(c); /* accum neg to avoid surprises at MAX */ + } + } else { + n = '0' - c; + while ((c = *++p) && isdigit(c)) { + n *= 10; /* two steps to avoid unnecessary overflow */ + n += '0' - c; /* accum neg to avoid surprises at MAX */ + } + } + return (neg ? n : -n); +} diff -urN linux-2.4.0-test10/arch/ia64/sn/io/sgi_io_init.c linux-2.4.0-test10-lia/arch/ia64/sn/io/sgi_io_init.c --- linux-2.4.0-test10/arch/ia64/sn/io/sgi_io_init.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/sgi_io_init.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,313 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern void mlreset(int ); +extern int init_hcl(void); +extern void klgraph_hack_init(void); +extern void per_hub_init(cnodeid_t); +extern void hubspc_init(void); +extern void pciba_init(void); +extern void pciio_init(void); +extern void pcibr_init(void); +extern void xtalk_init(void); +extern void xbow_init(void); +extern void xbmon_init(void); +extern void pciiox_init(void); +extern void usrpci_init(void); +extern void ioc3_init(void); +extern void initialize_io(void); +extern void init_platform_nodepda(nodepda_t *, cnodeid_t ); +extern void intr_clear_all(nasid_t); +extern void klhwg_add_all_modules(devfs_handle_t); +extern void klhwg_add_all_nodes(devfs_handle_t); + +void sn_mp_setup(void); +extern devfs_handle_t hwgraph_root; +extern void io_module_init(void); +extern cnodeid_t nasid_to_compact_node[]; +extern void pci_bus_cvlink_init(void); +extern void temp_hack(void); + +extern int pci_bus_to_hcl_cvlink(void); +extern synergy_da_t *Synergy_da_indr[]; + +#define DEBUG_IO_INIT +#ifdef DEBUG_IO_INIT +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif /* DEBUG_IO_INIT */ + +/* + * kern/ml/csu.s calls mlsetup + * mlsetup calls mlreset(master) - kern/os/startup.c + * j main + * + + * SN/slave.s start_slave_loop calls slave_entry + * SN/slave.s slave_entry calls slave_loop + * SN/slave.s slave_loop calls bootstrap + * bootstrap in SN1/SN1asm.s calls cboot + * cboot calls mlreset(slave) - ml/SN/mp.c + * + * sgi_io_infrastructure_init() gets called right before pci_init() + * in Linux mainline. This routine actually mirrors the IO Infrastructure + * call sequence in IRIX, ofcourse, nicely modified for Linux. + * + * It is very IMPORTANT that this call is only made by the Master CPU! + * + */ + +void +sgi_master_io_infr_init(void) +{ +#ifdef Colin + /* + * Simulate Big Window 0. + * Only when we build for lutsen etc. .. + */ + simulated_BW0_init(); +#endif + + /* + * Do any early init stuff .. einit_tbl[] etc. + */ + DBG("--> sgi_master_io_infr_init: calling init_hcl().\n"); + init_hcl(); /* Sets up the hwgraph compatibility layer with devfs */ + + /* + * initialize the Linux PCI to xwidget vertexes .. + */ + DBG("--> sgi_master_io_infr_init: calling pci_bus_cvlink_init().\n"); + pci_bus_cvlink_init(); + + /* + * Hack to provide statically initialzed klgraph entries. + */ + DBG("--> sgi_master_io_infr_init: calling klgraph_hack_init()\n"); + klgraph_hack_init(); + + /* + * This is the Master CPU. Emulate mlsetup and main.c in Irix. + */ + DBG("--> sgi_master_io_infr_init: calling mlreset(0).\n"); + mlreset(0); /* Master .. */ + + /* + * allowboot() is called by kern/os/main.c in main() + * Emulate allowboot() ... + * per_cpu_init() - only need per_hub_init() + * cpu_io_setup() - Nothing to do. + * + */ + DBG("--> sgi_master_io_infr_init: calling sn_mp_setup().\n"); + sn_mp_setup(); + + DBG("--> sgi_master_io_infr_init: calling per_hub_init(0).\n"); + per_hub_init(0); /* Need to get and send in actual cnode number */ + + /* We can do headless hub cnodes here .. */ + + /* + * io_init[] stuff. + * + * Get SGI IO Infrastructure drivers to init and register with + * each other etc. + */ + + DBG("--> sgi_master_io_infr_init: calling hubspc_init()\n"); + hubspc_init(); + + DBG("--> sgi_master_io_infr_init: calling pciba_init()\n"); + pciba_init(); + + DBG("--> sgi_master_io_infr_init: calling pciio_init()\n"); + pciio_init(); + + DBG("--> sgi_master_io_infr_init: calling pcibr_init()\n"); + pcibr_init(); + + DBG("--> sgi_master_io_infr_init: calling xtalk_init()\n"); + xtalk_init(); + + DBG("--> sgi_master_io_infr_init: calling xbow_init()\n"); + xbow_init(); + + DBG("--> sgi_master_io_infr_init: calling xbmon_init()\n"); + xbmon_init(); + + DBG("--> sgi_master_io_infr_init: calling pciiox_init()\n"); + pciiox_init(); + + DBG("--> sgi_master_io_infr_init: calling usrpci_init()\n"); + usrpci_init(); + + DBG("--> sgi_master_io_infr_init: calling ioc3_init()\n"); + ioc3_init(); + + /* + * + * Our IO Infrastructure drivers are in place .. + * Initialize the whole IO Infrastructure .. xwidget/device probes. + * + */ + DBG("--> sgi_master_io_infr_init: Start Probe and IO Initialization\n"); + initialize_io(); + + DBG("--> sgi_master_io_infr_init: Setting up SGI IO Links for Linux PCI\n"); + pci_bus_to_hcl_cvlink(); + + DBG("--> Leave sgi_master_io_infr_init: DONE setting up SGI Links for PCI\n"); +} + +/* + * sgi_slave_io_infr_init - This routine must be called on all cpus except + * the Master CPU. + */ +void +sgi_slave_io_infr_init(void) +{ + /* Emulate cboot() .. */ + mlreset(1); /* This is a slave cpu */ + + per_hub_init(0); /* Need to get and send in actual cnode number */ + + /* Done */ +} + +/* + * One-time setup for MP SN. + * Allocate per-node data, slurp prom klconfig information and + * convert it to hwgraph information. + */ +void +sn_mp_setup(void) +{ + cnodeid_t cnode; + extern int maxnodes; + + DBG("sn_mp_setup: Entered.\n"); + /* + * NODEPDA(x) Macro depends on nodepda + * subnodepda is also statically set to calias space which we + * do not currently support yet .. just a hack for now. + */ +#ifdef NUMA_BASE + DBG("sn_mp_setup(): maxnodes= %d numnodes= %d\n", maxnodes,numnodes); + maxnodes = numnodes; +#ifdef SIMULATED_KLGRAPH + maxnodes = 1; + numnodes = 1; +#endif /* SIMULATED_KLGRAPH */ + printk("sn_mp_setup(): Allocating backing store for *Nodepdaindr[%2d] \n", + maxnodes); + + /* + * Initialize Nodpdaindr and per-node nodepdaindr array + */ + *Nodepdaindr = (nodepda_t *) kmalloc(sizeof(nodepda_t *)*numnodes, GFP_KERNEL); + for (cnode=0; cnodepernode_pdaindr = Nodepdaindr; + subnodepda = &Nodepdaindr[cnode]->snpda[cnode]; + } + nodepda = Nodepdaindr[0]; +#else + Nodepdaindr = (nodepda_t *) kmalloc(sizeof(struct nodepda_s), GFP_KERNEL); + nodepda = Nodepdaindr[0]; + subnodepda = &Nodepdaindr[0]->snpda[0]; + +#endif /* NUMA_BASE */ + + /* + * Before we let the other processors run, set up the platform specific + * stuff in the nodepda. + * + * ???? maxnodes set in mlreset .. who sets it now ???? + * ???? cpu_node_probe() called in mlreset to set up the following: + * compact_to_nasid_node[] - cnode id gives nasid + * nasid_to_compact_node[] - nasid gives cnode id + * + * do_cpumask() sets the following: + * cpuid_to_compact_node[] - cpuid gives cnode id + * + * nasid comes from gdap->g_nasidtable[] + * ml/SN/promif.c + */ + + for (cnode = 0; cnode < maxnodes; cnode++) { + /* + * Set up platform-dependent nodepda fields. + * The following routine actually sets up the hubinfo struct + * in nodepda. + */ + DBG("sn_mp_io_setup: calling init_platform_nodepda(%2d)\n",cnode); + init_platform_nodepda(Nodepdaindr[cnode], cnode); + + /* + * This routine clears the Hub's Interrupt registers. + */ +#ifndef CONFIG_IA64_SGI_IO + /* + * We need to move this intr_clear_all() routine + * from SN/intr.c to a more appropriate file. + * Talk to Al Mayer. + */ + intr_clear_all(COMPACT_TO_NASID_NODEID(cnode)); +#endif + } + +#ifndef CONFIG_IA64_SGI_IO + /* + * Now set up platform specific stuff in the processor PDA. + * Not doing it in LINUX for now .. need to talk to Al Mayer. + */ + for (cpu = 0; cpu < maxcpus; cpu++) { + /* Skip holes in CPU space */ + if (CPUMASK_TSTB(boot_cpumask, cpu)) { + init_platform_pda(pdaindr[cpu].pda, cpu); + } + } +#endif + + /* + * Initialize platform-dependent vertices in the hwgraph: + * module + * node + * cpu + * memory + * slot + * hub + * router + * xbow + */ + + DBG("sn_mp_io_setup: calling io_module_init()\n"); + io_module_init(); /* Use to be called module_init() .. */ + + DBG("sn_mp_setup: calling klhwg_add_all_modules()\n"); + klhwg_add_all_modules(hwgraph_root); + DBG("sn_mp_setup: calling klhwg_add_all_nodes()\n"); + klhwg_add_all_nodes(hwgraph_root); +} diff -urN linux-2.4.0-test10/arch/ia64/sn/io/sgi_io_sim.c linux-2.4.0-test10-lia/arch/ia64/sn/io/sgi_io_sim.c --- linux-2.4.0-test10/arch/ia64/sn/io/sgi_io_sim.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/sgi_io_sim.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,189 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +cnodeid_t nasid_to_compact_node[MAX_NASIDS]; +nasid_t compact_to_nasid_node[MAX_COMPACT_NODES]; +cnodeid_t cpuid_to_compact_node[MAXCPUS]; +cpuid_t master_procid = 0; +int maxnodes; +char arg_maxnodes[4]; + +nodepda_t *Nodepdaindr[MAX_COMPACT_NODES]; +nodepda_t *nodepda; +subnode_pda_t *subnodepda; + +synergy_da_t *Synergy_da_indr[MAX_COMPACT_NODES * 2]; + +extern void init_all_devices(void); + + +/* + * Return non-zero if the given variable was specified + */ +int +is_specified(char *s) +{ + return (strlen(s) != 0); +} + + +#if 0 +void hubspc_init(void) +{ + +} + +void pciio_init(void) +{ + +} + +void pcibr_init(void) +{ + +} + +void xtalk_init(void) +{ + +} + +void xbow_init(void) +{ + +} +#endif + +void pciba_init(void) +{ + FIXME("pciba_init : no-op\n"); +} + +void xbmon_init(void) +{ + FIXME("xbmon_init : no-op\n"); + +} + +void pciiox_init(void) +{ + FIXME("pciiox_init : no-op\n"); + +} + +void usrpci_init(void) +{ + FIXME("usrpci_init : no-op\n"); + +} + +void ioc3_init(void) +{ + FIXME("ioc3_init : no-op\n"); + +} + +void initialize_io(void) +{ + + init_all_devices(); +} + +/* + * Routines provided by ml/SN/promif.c. + */ +static __psunsigned_t master_bridge_base = (__psunsigned_t)NULL; +static nasid_t console_nasid; +static char console_wid; +static char console_pcislot; + +void +set_master_bridge_base(void) +{ + +#ifdef SIMULATED_KLGRAPH + printk("set_master_bridge_base: SIMULATED_KLGRAPH FIXME hardwired master.\n"); + console_nasid = 0; + console_wid = 0x8; + console_pcislot = 0x2; +#else + console_nasid = KL_CONFIG_CH_CONS_INFO(master_nasid)->nasid; + console_wid = WIDGETID_GET(KL_CONFIG_CH_CONS_INFO(master_nasid)->memory_base); + console_pcislot = KL_CONFIG_CH_CONS_INFO(master_nasid)->npci; +#endif /* SIMULATED_KLGRAPH */ + + master_bridge_base = (__psunsigned_t)NODE_SWIN_BASE(console_nasid, + console_wid); +} + +int +check_nasid_equiv(nasid_t nasida, nasid_t nasidb) +{ + if ((nasida == nasidb) || + (nasida == NODEPDA(NASID_TO_COMPACT_NODEID(nasidb))->xbow_peer)) + return 1; + else + return 0; +} + +int +is_master_nasid_widget(nasid_t test_nasid, xwidgetnum_t test_wid) +{ + + /* + * If the widget numbers are different, we're not the master. + */ + if (test_wid != (xwidgetnum_t)console_wid) + return 0; + + /* + * If the NASIDs are the same or equivalent, we're the master. + */ + if (check_nasid_equiv(test_nasid, console_nasid)) { + return 1; + } else { + return 0; + } +} + +cnodeid_t +nasid_to_compact_nodeid(nasid_t nasid) +{ + ASSERT(nasid >= 0 && nasid < MAX_NASIDS); + return nasid_to_compact_node[nasid]; +} + +nasid_t +compact_to_nasid_nodeid(cnodeid_t cnode) +{ + ASSERT(cnode >= 0 && cnode <= MAX_COMPACT_NODES); + ASSERT(compact_to_nasid_node[cnode] >= 0); + return compact_to_nasid_node[cnode]; +} + +/* + * Routines provided by ml/SN/nvram.c + */ +void +nvram_baseinit(void) +{ + FIXME("nvram_baseinit : no-op\n"); + +} diff -urN linux-2.4.0-test10/arch/ia64/sn/io/stubs.c linux-2.4.0-test10-lia/arch/ia64/sn/io/stubs.c --- linux-2.4.0-test10/arch/ia64/sn/io/stubs.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/stubs.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,214 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/****** + ****** hack defines ...... + ******/ + +int pcibr_prefetch_enable_rev, pcibr_wg_enable_rev; +int default_intr_pri; +int force_fire_and_forget; +int ignore_conveyor_override; + +#define spinlock_init(x,name) mutex_init(x, MUTEX_DEFAULT, name); + +devfs_handle_t dummy_vrtx; /* Needed for cpuid_to_vertex() in hack.h */ + + +/* ARGSUSED */ +void hub_widgetdev_enable(devfs_handle_t xconn_vhdl, int devnum) + {FIXME("hub_widgetdev_enable");} + +/* ARGSUSED */ +void hub_widgetdev_shutdown(devfs_handle_t xconn_vhdl, int devnum) + {FIXME("hub_widgetdev_shutdown");} + +/* ARGSUSED */ +void hub_widget_reset(devfs_handle_t hubv, xwidgetnum_t widget) + {FIXME("hub_widget_reset");} + +boolean_t +is_sys_critical_vertex(devfs_handle_t x) +{ + FIXME("is_sys_critical_vertex : returns 0"); + return(0); +} + +char * +nic_bridge_vertex_info(devfs_handle_t v, nic_data_t mcr) +{ + FIXME("nic_bridge_vertex_info : returns NULL"); + return((char *)0); +} + +void * +kmem_alloc_node(register size_t size, register int flags, cnodeid_t node) +{ + /* Allocates on node 'node' */ + FIXME("kmem_alloc_node : use kmalloc"); + return(kmalloc(size, GFP_KERNEL)); +} + +void * +kmem_zalloc_node(register size_t size, register int flags, cnodeid_t node) +{ + FIXME("kmem_zalloc_node : use kmalloc"); + return(kmalloc(size, GFP_KERNEL)); +} + +void * +kmem_zone_alloc(register zone_t *zone, int flags) +{ + FIXME("kmem_zone_alloc : return null"); + return((void *)0); +} + +void +kmem_zone_free(register zone_t *zone, void *ptr) +{ + FIXME("kmem_zone_free : no-op"); +} + +zone_t * +kmem_zone_init(register int size, char *zone_name) +{ + FIXME("kmem_zone_free : returns NULL"); + return((zone_t *)0); +} + +uint64_t +rmalloc(struct map *mp, size_t size) +{ + FIXME("rmalloc : returns NULL"); + return((uint64_t)0); +} + +void +rmfree(struct map *mp, size_t size, uint64_t a) +{ + FIXME("rmfree : no-op"); +} + +struct map * +rmallocmap(uint64_t mapsiz) +{ + FIXME("rmallocmap : returns NULL"); + return((struct map *)0); +} + +void +rmfreemap(struct map *mp) +{ + FIXME("rmfreemap : no-op"); +} + +int +compare_and_swap_ptr(void **location, void *old_ptr, void *new_ptr) +{ + FIXME("compare_and_swap_ptr : NOT ATOMIC"); + if (*location == old_ptr) { + *location = new_ptr; + return(1); + } + else + return(0); +} + +void * +swap_ptr(void **loc, void *new) +{ + FIXME("swap_ptr : returns null"); + return((void *)0); +} + +/* For ml/SN/SN1/slots.c */ +/* ARGSUSED */ +slotid_t get_widget_slotnum(int xbow, int widget) + {FIXME("get_widget_slotnum"); return (unsigned char)NULL;} + +/* For router */ +int +router_init(cnodeid_t cnode,int writeid, void *npda_rip) + {FIXME("router_init"); return(0);} + +/* From io/ioerror_handling.c */ +error_return_code_t +sys_critical_graph_vertex_add(devfs_handle_t parent, devfs_handle_t child) + {FIXME("sys_critical_graph_vertex_add"); return(0);} + +/* From io/ioc3.c */ +devfs_handle_t +ioc3_console_vhdl_get(void) + {FIXME("ioc3_console_vhdl_get"); return( (devfs_handle_t)-1);} + + +#if 0 +#define io_splock(l) 1 +#define io_spunlock(l,s) + +#define spinlock_destroy(a) /* needed by pcibr_detach() */ +#define mutex_spinlock(a) 0 +#define mutex_spinunlock(a,b) +#define mutex_init(a,b,c) ; +#define mutex_lock(a,b) ; +#define mutex_unlock(a) ; +#define dev_to_vhdl(dev) 0 +#define get_timestamp() 0 +#define us_delay(a) +#define v_mapphys(a,b,c) 0 +#define splhi() 0 +#define splx(s) +#define spinlock_init(x,name) mutex_init(x, MUTEX_DEFAULT, name); +#endif /* 0 */ + +int +cap_able(uint64_t x) +{ + FIXME("cap_able : returns 1"); + return(1); +} + +int +cap_able_cred(uint64_t a, uint64_t b) +{ + FIXME("cap_able_cred : returns 1"); + return(1); +} + +void +nic_vmc_check(devfs_handle_t vhdl, char *nicinfo) +{ + + FIXME("nic_vmc_check\n"); + +} + +char * +nic_vertex_info_get(devfs_handle_t v) +{ + + FIXME("nic_vertex_info_get\n"); + return(NULL); + +} diff -urN linux-2.4.0-test10/arch/ia64/sn/io/xbow.c linux-2.4.0-test10-lia/arch/ia64/sn/io/xbow.c --- linux-2.4.0-test10/arch/ia64/sn/io/xbow.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/xbow.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,1871 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG 1 +#define XBOW_DEBUG 1 + + +/* + * Files needed to get the device driver entry points + */ + +/* #include */ + +#include +#include +#include +#include + +#include +#include + + +#define NEW(ptr) (ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL)) +#define DEL(ptr) (kfree(ptr)) + +int xbow_devflag = D_MP; + +/* + * This file supports the Xbow chip. Main functions: initializtion, + * error handling, and GBR. + */ + +/* + * each vertex corresponding to an xbow chip + * has a "fastinfo" pointer pointing at one + * of these things. + */ +typedef struct xbow_soft_s *xbow_soft_t; + +struct xbow_soft_s { + devfs_handle_t conn; /* our connection point */ + devfs_handle_t vhdl; /* xbow's private vertex */ + devfs_handle_t busv; /* the xswitch vertex */ + xbow_t *base; /* PIO pointer to crossbow chip */ + char *name; /* hwgraph name */ + + xbow_perf_t xbow_perfcnt[XBOW_PERF_COUNTERS]; + xbow_perf_link_t xbow_perflink[MAX_XBOW_PORTS]; + xbow_link_status_t xbow_link_status[MAX_XBOW_PORTS]; + lock_t xbow_perf_lock; + int link_monitor; + widget_cfg_t *wpio[MAX_XBOW_PORTS]; /* cached PIO pointer */ + + /* Bandwidth allocation state. Bandwidth values are for the + * destination port since contention happens there. + * Implicit mapping from xbow ports (8..f) -> (0..7) array indices. + */ + lock_t xbow_bw_alloc_lock; /* bw allocation lock */ + unsigned long long bw_hiwm[MAX_XBOW_PORTS]; /* hiwater mark values */ + unsigned long long bw_cur_used[MAX_XBOW_PORTS]; /* bw used currently */ +}; + +#define xbow_soft_set(v,i) hwgraph_fastinfo_set((v), (arbitrary_info_t)(i)) +#define xbow_soft_get(v) ((xbow_soft_t)hwgraph_fastinfo_get((v))) + +/* + * Function Table of Contents + */ + +void xbow_mlreset(xbow_t *); +void xbow_init(void); +int xbow_attach(devfs_handle_t); + +int xbow_open(devfs_handle_t *, int, int, cred_t *); +int xbow_close(devfs_handle_t, int, int, cred_t *); + +int xbow_map(devfs_handle_t, vhandl_t *, off_t, size_t, uint); +int xbow_unmap(devfs_handle_t, vhandl_t *); +int xbow_ioctl(devfs_handle_t, int, void *, int, struct cred *, int *); + +int xbow_widget_present(xbow_t *, int); +static int xbow_link_alive(xbow_t *, int); +devfs_handle_t xbow_widget_lookup(devfs_handle_t, int); + +#ifdef LATER +static void xbow_setwidint(xtalk_intr_t); +static void xbow_errintr_handler(intr_arg_t); +static error_handler_f xbow_error_handler; +#endif +void xbow_intr_preset(void *, int, xwidgetnum_t, iopaddr_t, xtalk_intr_vector_t); + + + +void xbow_update_perf_counters(devfs_handle_t); +xbow_perf_link_t *xbow_get_perf_counters(devfs_handle_t); +int xbow_enable_perf_counter(devfs_handle_t, int, int, int); +xbow_link_status_t *xbow_get_llp_status(devfs_handle_t); +void xbow_update_llp_status(devfs_handle_t); + +int xbow_disable_llp_monitor(devfs_handle_t); +int xbow_enable_llp_monitor(devfs_handle_t); + +#ifdef IRIX +int xbow_prio_bw_alloc(devfs_handle_t, xwidgetnum_t, xwidgetnum_t, + unsigned long long, unsigned long long); +#else +int xbow_prio_bw_alloc(devfs_handle_t, xwidgetnum_t, xwidgetnum_t, + unsigned long long, unsigned long long); +#endif + + +xswitch_reset_link_f xbow_reset_link; + +void idbg_xbowregs(int64_t); + +xswitch_provider_t xbow_provider = +{ + xbow_reset_link, +}; + +/* + * xbow_mlreset: called at mlreset time if the + * platform specific code determines that there is + * a crossbow in a critical path that must be + * functional before the driver would normally get + * the device properly set up. + * + * what do we need to do, that the boot prom can + * not be counted on to have already done, that is + * generic across all platforms using crossbows? + */ +/*ARGSUSED */ +void +xbow_mlreset(xbow_t * xbow) +{ +} + +/* + * xbow_init: called with the rest of the device + * driver XXX_init routines. This platform *might* + * have a Crossbow chip, or even several, but it + * might have none. Register with the crosstalk + * generic provider so when we encounter the chip + * the right magic happens. + */ +void +xbow_init(void) +{ + +#if DEBUG && ATTACH_DEBUG + printf("xbow_init\n"); +#endif + + xwidget_driver_register(XXBOW_WIDGET_PART_NUM, + 0, /* XXBOW_WIDGET_MFGR_NUM, */ + "xbow_", + CDL_PRI_HI); /* attach before friends */ + + xwidget_driver_register(XBOW_WIDGET_PART_NUM, + XBOW_WIDGET_MFGR_NUM, + "xbow_", + CDL_PRI_HI); /* attach before friends */ +} + +#ifdef XBRIDGE_REGS_SIM +/* xbow_set_simulated_regs: sets xbow regs as needed + * for powering through the boot + */ +void +xbow_set_simulated_regs(xbow_t *xbow, int port) +{ + /* + * turn on link + */ + xbow->xb_link(port).link_status = (1<<31); + /* + * and give it a live widget too + */ + xbow->xb_link(port).link_aux_status = XB_AUX_STAT_PRESENT; + /* + * zero the link control reg + */ + xbow->xb_link(port).link_control = 0x0; +} +#endif /* XBRIDGE_REGS_SIM */ + +/* + * xbow_attach: the crosstalk provider has + * determined that there is a crossbow widget + * present, and has handed us the connection + * point for that vertex. + * + * We not only add our own vertex, but add + * some "xtalk switch" data to the switch + * vertex (at the connect point's parent) if + * it does not have any. + */ + +/*ARGSUSED */ +int +xbow_attach(devfs_handle_t conn) +{ + /*REFERENCED */ + devfs_handle_t vhdl; + devfs_handle_t busv; + xbow_t *xbow; + xbow_soft_t soft; + int port; + xswitch_info_t info; +#ifdef LATER + xtalk_intr_t intr_hdl; + device_desc_t dev_desc; +#endif + char devnm[MAXDEVNAME], *s; + xbowreg_t id; + int rev; + int i; + int xbow_num; + +#if DEBUG && ATTACH_DEBUG + cmn_err(CE_CONT, "%v: xbow_attach\n", conn); +#endif + + /* + * Get a PIO pointer to the base of the crossbow + * chip. + */ +#ifdef XBRIDGE_REGS_SIM + printk("xbow_attach: XBRIDGE_REGS_SIM FIXME: allocating %ld bytes for xbow_s\n", sizeof(xbow_t)); + xbow = (xbow_t *) kmalloc(sizeof(xbow_t), GFP_KERNEL); + /* + * turn on ports e and f like in a real live ibrick + */ + xbow_set_simulated_regs(xbow, 0xe); + xbow_set_simulated_regs(xbow, 0xf); +#else + xbow = (xbow_t *) xtalk_piotrans_addr(conn, 0, 0, sizeof(xbow_t), 0); +#endif /* XBRIDGE_REGS_SIM */ + + /* + * Locate the "switch" vertex: it is the parent + * of our connection point. + */ + busv = hwgraph_connectpt_get(conn); + printk("xbow_attach: Bus Vertex 0x%p, conn 0x%p, xbow register 0x%p wid= 0x%x\n", busv, conn, xbow, *(volatile u32 *)xbow); + + ASSERT(busv != GRAPH_VERTEX_NONE); + + /* + * Create our private vertex, and connect our + * driver information to it. This makes it possible + * for diagnostic drivers to open the crossbow + * vertex for access to registers. + */ + + /* + * We need to teach xbow drivers to provide the right set of + * file ops. + */ + vhdl = NULL; + vhdl = hwgraph_register(conn, EDGE_LBL_XBOW, + 0, DEVFS_FL_AUTO_DEVNUM, + 0, 0, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0, + /* &hcl_fops */ (void *)&vhdl, NULL); + if (!vhdl) { + printk("xbow_attach: Unable to create char device for xbow conn +0x%p\n", + conn); + } + + /* + * Allocate the soft state structure and attach + * it to the xbow's vertex + */ + NEW(soft); + soft->conn = conn; + soft->vhdl = vhdl; + soft->busv = busv; + soft->base = xbow; + /* does the universe really need another macro? */ + /* xbow_soft_set(vhdl, (arbitrary_info_t) soft); */ + hwgraph_fastinfo_set(vhdl, (arbitrary_info_t) soft); + +#define XBOW_NUM_SUFFIX_FORMAT "[xbow# %d]" + + /* Add xbow number as a suffix to the hwgraph name of the xbow. + * This is helpful while looking at the error/warning messages. + */ +#if CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 || CONFIG_IA64_GENERIC + xbow_num = 0; +#else + xbow_num = xswitch_id_get(busv); +#endif + + /* + * get the name of this xbow vertex and keep the info. + * This is needed during errors and interupts, but as + * long as we have it, we can use it elsewhere. + */ + s = dev_to_name(vhdl, devnm, MAXDEVNAME); + soft->name = kmalloc(strlen(s) + strlen(XBOW_NUM_SUFFIX_FORMAT) + 1, + GFP_KERNEL); + sprintf(soft->name,"%s"XBOW_NUM_SUFFIX_FORMAT, s,xbow_num); + +#ifdef XBRIDGE_REGS_SIM + /* my o200/ibrick has id=0x2d002049, but XXBOW_WIDGET_PART_NUM is defined + * as 0xd000, so I'm using that for the partnum bitfield. + */ + printk("xbow_attach: XBRIDGE_REGS_SIM FIXME: need xb_wid_id value!!\n"); + id = 0x2d000049; +#else + id = xbow->xb_wid_id; +#endif /* XBRIDGE_REGS_SIM */ + rev = XWIDGET_PART_REV_NUM(id); + + /* + * Print the revision if DEBUG, or SHOW_REVS and kdebug, + * or the xbow is downrev. + * + * If xbow is downrev, make it a WARNING that the + * Crossbow is DOWNREV: these chips are not good + * to have around, and the operator should be told. + */ +#ifdef IRIX +#if !DEBUG + if ( +#if SHOW_REVS + (kdebug) || +#endif /* SHOW_REVS */ + (rev < XBOW_REV_1_1)) +#endif /* !DEBUG */ + cmn_err((rev < XBOW_REV_1_1) ? CE_WARN : CE_CONT, + "%sCrossbow ASIC: rev %s (code=%d) at %s%s", + (rev < XBOW_REV_1_1) ? "DOWNREV " : "", + (rev == XBOW_REV_1_0) ? "1.0" : + (rev == XBOW_REV_1_1) ? "1.1" : + (rev == XBOW_REV_1_2) ? "1.2" : + (rev == XBOW_REV_1_3) ? "1.3" : + (rev == XBOW_REV_2_0) ? "2.0" : + (rev == XXBOW_PART_REV_1_0) ? "Xbridge 1.0" : + (rev == XXBOW_PART_REV_2_0) ? "Xbridge 2.0" : + "unknown", + rev, soft->name, + (rev < XBOW_REV_1_1) ? "" : "\n"); +#endif /* IRIX */ + + spinlock_init(&soft->xbow_perf_lock, "xbow_perf_lock"); + soft->xbow_perfcnt[0].xp_perf_reg = &xbow->xb_perf_ctr_a; + soft->xbow_perfcnt[1].xp_perf_reg = &xbow->xb_perf_ctr_b; + + /* Initialization for GBR bw allocation */ + spinlock_init(&soft->xbow_bw_alloc_lock, "xbow_bw_alloc_lock"); + +#define XBOW_8_BIT_PORT_BW_MAX (400 * 1000 * 1000) /* 400 MB/s */ +#define XBOW_16_BIT_PORT_BW_MAX (800 * 1000 * 1000) /* 800 MB/s */ + + /* Set bandwidth hiwatermark and current values */ + for (i = 0; i < MAX_XBOW_PORTS; i++) { + soft->bw_hiwm[i] = XBOW_16_BIT_PORT_BW_MAX; /* for now */ + soft->bw_cur_used[i] = 0; + } + + /* + * attach the crossbow error interrupt. + */ +#ifdef LATER + dev_desc = device_desc_dup(vhdl); + device_desc_flags_set(dev_desc, + device_desc_flags_get(dev_desc) | D_INTR_ISERR); + device_desc_intr_name_set(dev_desc, "Crossbow error"); + + intr_hdl = xtalk_intr_alloc(conn, dev_desc, vhdl); + ASSERT(intr_hdl != NULL); + + xtalk_intr_connect(intr_hdl, + (intr_func_t) xbow_errintr_handler, + (intr_arg_t) soft, + (xtalk_intr_setfunc_t) xbow_setwidint, + (void *) xbow, + (void *) 0); + device_desc_free(dev_desc); + + xwidget_error_register(conn, xbow_error_handler, soft); + +#else + printk("xbow_attach: Fixme: we bypassed attaching xbow error interrupt.\n"); +#endif /* LATER */ + + /* + * Enable xbow error interrupts + */ + xbow->xb_wid_control = (XB_WID_CTRL_REG_ACC_IE | + XB_WID_CTRL_XTALK_IE); + + /* + * take a census of the widgets present, + * leaving notes at the switch vertex. + */ + info = xswitch_info_new(busv); + + for (port = MAX_PORT_NUM - MAX_XBOW_PORTS; + port < MAX_PORT_NUM; ++port) { + if (!xbow_link_alive(xbow, port)) { +#if DEBUG && XBOW_DEBUG + printk(KERN_INFO "0x%p link %d is not alive\n", + busv, port); +#endif + continue; + } + if (!xbow_widget_present(xbow, port)) { +#if DEBUG && XBOW_DEBUG + printk(KERN_INFO "0x%p link %d is alive but no widget is present\n", busv, port); +#endif + continue; + } +#if DEBUG && XBOW_DEBUG + printk(KERN_INFO "0x%p link %d has a widget\n", + busv, port); +#endif + + xswitch_info_link_is_ok(info, port); + /* + * Turn some error interrupts on + * and turn others off. The PROM has + * some things turned on we don't + * want to see (bandwidth allocation + * errors for instance); so if it + * is not listed here, it is not on. + */ + xbow->xb_link(port).link_control = + ( (xbow->xb_link(port).link_control + /* + * Turn off these bits; they are non-fatal, + * but we might want to save some statistics + * on the frequency of these errors. + * XXX FIXME XXX + */ + & ~XB_CTRL_RCV_CNT_OFLOW_IE + & ~XB_CTRL_XMT_CNT_OFLOW_IE + & ~XB_CTRL_BNDWDTH_ALLOC_IE + & ~XB_CTRL_RCV_IE) + /* + * These are the ones we want to turn on. + */ + | (XB_CTRL_ILLEGAL_DST_IE + | XB_CTRL_OALLOC_IBUF_IE + | XB_CTRL_XMT_MAX_RTRY_IE + | XB_CTRL_MAXREQ_TOUT_IE + | XB_CTRL_XMT_RTRY_IE + | XB_CTRL_SRC_TOUT_IE) ); + } + + xswitch_provider_register(busv, &xbow_provider); + + return 0; /* attach successful */ +} + +/*ARGSUSED */ +int +xbow_open(devfs_handle_t *devp, int oflag, int otyp, cred_t *credp) +{ + if (!_CAP_CRABLE((uint64_t)credp, CAP_DEVICE_MGT)) + return EPERM; + return 0; + +} + +/*ARGSUSED */ +int +xbow_close(devfs_handle_t dev, int oflag, int otyp, cred_t *crp) +{ + return 0; +} + +/*ARGSUSED */ +int +xbow_map(devfs_handle_t dev, vhandl_t *vt, off_t off, size_t len, uint prot) +{ + devfs_handle_t vhdl = dev_to_vhdl(dev); + xbow_soft_t soft = xbow_soft_get(vhdl); + int error; + + ASSERT(soft); + len = ctob(btoc(len)); + /* XXX- this ignores the offset!!! */ + error = v_mapphys(vt, (void *) soft->base, len); + return error; +} + +/*ARGSUSED */ +int +xbow_unmap(devfs_handle_t dev, vhandl_t *vt) +{ + return 0; +} + +/* This contains special-case code for grio. There are plans to make + * this general sometime in the future, but till then this should + * be good enough. + */ +xwidgetnum_t +xbow_widget_num_get(devfs_handle_t dev) +{ + devfs_handle_t tdev; + char devname[MAXDEVNAME]; + xwidget_info_t xwidget_info; + int i; +#if IP27 + cnodeid_t cnodeid = CNODEID_NONE; +#endif + + vertex_to_name(dev, devname, MAXDEVNAME); + +#if IP30 + /* If there is a ".connection" edge from this vertex, + * then it must be "/hw/node" vertex. Return the widget + * number for heart: 8. + */ + if (hwgraph_edge_get(dev, EDGE_LBL_CONN, &tdev) == + GRAPH_SUCCESS) { + return ((xwidgetnum_t) 8); + } +#elif IP27 + if ((cnodeid = nodevertex_to_cnodeid(dev)) != CNODEID_NONE) { + ASSERT(cnodeid < maxnodes); + return(hub_widget_id(COMPACT_TO_NASID_NODEID(cnodeid))); + } +#endif + + /* If this is a pci controller vertex, traverse up using + * the ".." links to get to the widget. + */ + if (strstr(devname, EDGE_LBL_PCI) && + strstr(devname, EDGE_LBL_CONTROLLER)) { + tdev = dev; + for (i=0; i< 2; i++) { + if (hwgraph_edge_get(tdev, + HWGRAPH_EDGELBL_DOTDOT, &tdev) != + GRAPH_SUCCESS) + return XWIDGET_NONE; + } + + if ((xwidget_info = xwidget_info_chk(tdev)) != NULL) { + return (xwidget_info_id_get(xwidget_info)); + } else { + return XWIDGET_NONE; + } + } + + return XWIDGET_NONE; +} + +int +xbow_ioctl(devfs_handle_t dev, + int cmd, + void *arg, + int flag, + struct cred *cr, + int *rvalp) +{ + devfs_handle_t vhdl; + int error = 0; + +#if defined (DEBUG) + int rc; + devfs_handle_t conn; + struct xwidget_info_s *xwidget_info; + xbow_soft_t xbow_soft; +#endif + *rvalp = 0; + + vhdl = dev_to_vhdl(dev); +#if defined (DEBUG) + xbow_soft = xbow_soft_get(vhdl); + conn = xbow_soft->conn; + + xwidget_info = xwidget_info_get(conn); + ASSERT_ALWAYS(xwidget_info != NULL); + + rc = xwidget_hwid_is_xswitch(&xwidget_info->w_hwid); + ASSERT_ALWAYS(rc != 0); +#endif + switch (cmd) { +#ifdef IRIX + case XBOWIOC_PERF_ENABLE: + case XBOWIOC_PERF_DISABLE: + { + struct xbow_perfarg_t xbow_perf_en; + + if (!_CAP_CRABLE(cr, CAP_DEVICE_MGT)) { + error = EPERM; + break; + } + if ((flag & FWRITE) == 0) { + error = EBADF; + break; + } + if (COPYIN(arg, &xbow_perf_en, sizeof(xbow_perf_en))) { + error = EFAULT; + break; + } + if (error = xbow_enable_perf_counter(vhdl, + xbow_perf_en.link, + (cmd == XBOWIOC_PERF_DISABLE) ? 0 : xbow_perf_en.mode, + xbow_perf_en.counter)) { + error = EINVAL; + break; + } + break; + } +#endif + +#ifdef IRIX + case XBOWIOC_PERF_GET: + { + xbow_perf_link_t *xbow_perf_cnt; + + if ((flag & FREAD) == 0) { + error = EBADF; + break; + } + xbow_perf_cnt = xbow_get_perf_counters(vhdl); + ASSERT_ALWAYS(xbow_perf_cnt != NULL); + + if (COPYOUT((void *) xbow_perf_cnt, (void *) arg, + MAX_XBOW_PORTS * sizeof(xbow_perf_link_t))) { + error = EFAULT; + break; + } + break; + } +#endif + + case XBOWIOC_LLP_ERROR_ENABLE: + if (!_CAP_CRABLE((uint64_t)cr, CAP_DEVICE_MGT)) { + error = EPERM; + break; + } + if ((error = xbow_enable_llp_monitor(vhdl)) != 0) + error = EINVAL; + + break; + + case XBOWIOC_LLP_ERROR_DISABLE: + + if (!_CAP_CRABLE((uint64_t)cr, CAP_DEVICE_MGT)) { + error = EPERM; + break; + } + if ((error = xbow_disable_llp_monitor(vhdl)) != 0) + error = EINVAL; + + break; + +#ifdef IRIX + case XBOWIOC_LLP_ERROR_GET: + { + xbow_link_status_t *xbow_llp_status; + + if ((flag & FREAD) == 0) { + error = EBADF; + break; + } + xbow_llp_status = xbow_get_llp_status(vhdl); + ASSERT_ALWAYS(xbow_llp_status != NULL); + + if (COPYOUT((void *) xbow_llp_status, (void *) arg, + MAX_XBOW_PORTS * sizeof(xbow_link_status_t))) { + error = EFAULT; + break; + } + break; + } +#endif + +#ifdef IRIX + case GIOCSETBW: + { + grio_ioctl_info_t info; + xwidgetnum_t src_widgetnum, dest_widgetnum; + + if (!cap_able(CAP_DEVICE_MGT)) { + error = EPERM; + break; + } + + if (COPYIN(arg, &info, sizeof(grio_ioctl_info_t))) { + error = EFAULT; + break; + } +#ifdef GRIO_DEBUG + printf("xbow:: prev_vhdl: %d next_vhdl: %d reqbw: %lld\n", + info.prev_vhdl, info.next_vhdl, info.reqbw); +#endif /* GRIO_DEBUG */ + + src_widgetnum = xbow_widget_num_get(info.prev_vhdl); + dest_widgetnum = xbow_widget_num_get(info.next_vhdl); + + /* Bandwidth allocation is bi-directional. Since bandwidth + * reservations have already been done at an earlier stage, + * we cannot fail here for lack of bandwidth. + */ + xbow_prio_bw_alloc(dev, src_widgetnum, dest_widgetnum, + 0, info.reqbw); + xbow_prio_bw_alloc(dev, dest_widgetnum, src_widgetnum, + 0, info.reqbw); + + break; + } + + case GIOCRELEASEBW: + { + grio_ioctl_info_t info; + xwidgetnum_t src_widgetnum, dest_widgetnum; + + if (!cap_able(CAP_DEVICE_MGT)) { + error = EPERM; + break; + } + + if (COPYIN(arg, &info, sizeof(grio_ioctl_info_t))) { + error = EFAULT; + break; + } +#ifdef GRIO_DEBUG + printf("xbow:: prev_vhdl: %d next_vhdl: %d reqbw: %lld\n", + info.prev_vhdl, info.next_vhdl, info.reqbw); +#endif /* GRIO_DEBUG */ + + src_widgetnum = xbow_widget_num_get(info.prev_vhdl); + dest_widgetnum = xbow_widget_num_get(info.next_vhdl); + + /* Bandwidth reservation is bi-directional. Hence, remove + * bandwidth reservations for both directions. + */ + xbow_prio_bw_alloc(dev, src_widgetnum, dest_widgetnum, + info.reqbw, (-1 * info.reqbw)); + xbow_prio_bw_alloc(dev, dest_widgetnum, src_widgetnum, + info.reqbw, (-1 * info.reqbw)); + + break; + } +#endif + + default: + break; + + } + return error; +} + +/* + * xbow_widget_present: See if a device is present + * on the specified port of this crossbow. + */ +int +xbow_widget_present(xbow_t * xbow, int port) +{ + if ( IS_RUNNING_ON_SIMULATOR() ) { + if ( (port == 14) || (port == 15) ) { + return 1; + } + else { + return 0; + } + } + else { + return xbow->xb_link(port).link_aux_status & XB_AUX_STAT_PRESENT; + } +} + +static int +xbow_link_alive(xbow_t * xbow, int port) +{ + xbwX_stat_t xbow_linkstat; + + xbow_linkstat.linkstatus = xbow->xb_link(port).link_status; + return (xbow_linkstat.link_alive); +} + +/* + * xbow_widget_lookup + * Lookup the edges connected to the xbow specified, and + * retrieve the handle corresponding to the widgetnum + * specified. + * If not found, return 0. + */ +devfs_handle_t +xbow_widget_lookup(devfs_handle_t vhdl, + int widgetnum) +{ + xswitch_info_t xswitch_info; + devfs_handle_t conn; + + xswitch_info = xswitch_info_get(vhdl); +#if CONFIG_SGI_IP27 + ASSERT_ALWAYS((widgetnum >= HUB_WIDGET_ID_MIN) && + (widgetnum <= HUB_WIDGET_ID_MAX)); +#endif /* CONFIG_SGI_IP27 */ + + conn = xswitch_info_vhdl_get(xswitch_info, widgetnum); + return conn; +} + +/* + * xbow_setwidint: called when xtalk + * is establishing or migrating our + * interrupt service. + */ +#ifdef LATER +static void +xbow_setwidint(xtalk_intr_t intr) +{ + xwidgetnum_t targ = xtalk_intr_target_get(intr); + iopaddr_t addr = xtalk_intr_addr_get(intr); + xtalk_intr_vector_t vect = xtalk_intr_vector_get(intr); + xbow_t *xbow = (xbow_t *) xtalk_intr_sfarg_get(intr); + + xbow_intr_preset((void *) xbow, 0, targ, addr, vect); +} +#endif /* LATER */ + +/* + * xbow_intr_preset: called during mlreset time + * if the platform specific code needs to route + * an xbow interrupt before the xtalk infrastructure + * is available for use. + * + * Also called from xbow_setwidint, so we don't + * replicate the guts of the routine. + * + * XXX- probably should be renamed xbow_wid_intr_set or + * something to reduce confusion. + */ +/*ARGSUSED3 */ +void +xbow_intr_preset(void *which_widget, + int which_widget_intr, + xwidgetnum_t targ, + iopaddr_t addr, + xtalk_intr_vector_t vect) +{ + xbow_t *xbow = (xbow_t *) which_widget; + + xbow->xb_wid_int_upper = ((0xFF000000 & (vect << 24)) | + (0x000F0000 & (targ << 16)) | + XTALK_ADDR_TO_UPPER(addr)); + xbow->xb_wid_int_lower = XTALK_ADDR_TO_LOWER(addr); +} + +#define XEM_ADD_STR(s) cmn_err(CE_CONT, "%s", (s)) +#define XEM_ADD_NVAR(n,v) cmn_err(CE_CONT, "\t%20s: 0x%x\n", (n), (v)) +#define XEM_ADD_VAR(v) XEM_ADD_NVAR(#v,(v)) +#define XEM_ADD_IOEF(n) if (IOERROR_FIELDVALID(ioe,n)) \ + XEM_ADD_NVAR("ioe." #n, \ + IOERROR_GETVALUE(ioe,n)) + +#ifdef IRIX +static void +xem_add_ioe(ioerror_t *ioe) +{ + XEM_ADD_IOEF(errortype); + XEM_ADD_IOEF(widgetnum); + XEM_ADD_IOEF(widgetdev); + XEM_ADD_IOEF(srccpu); + XEM_ADD_IOEF(srcnode); + XEM_ADD_IOEF(errnode); + XEM_ADD_IOEF(sysioaddr); + XEM_ADD_IOEF(xtalkaddr); + XEM_ADD_IOEF(busspace); + XEM_ADD_IOEF(busaddr); + XEM_ADD_IOEF(vaddr); + XEM_ADD_IOEF(memaddr); + XEM_ADD_IOEF(epc); + XEM_ADD_IOEF(ef); +} + +#define XEM_ADD_IOE() (xem_add_ioe(ioe)) +#endif /* IRIX */ + +int xbow_xmit_retry_errors = 0; + +int +xbow_xmit_retry_error(xbow_soft_t soft, + int port) +{ + xswitch_info_t info; + devfs_handle_t vhdl; + widget_cfg_t *wid; + widgetreg_t id; + int part; + int mfgr; + + wid = soft->wpio[port - BASE_XBOW_PORT]; + if (wid == NULL) { + /* If we can't track down a PIO + * pointer to our widget yet, + * leave our caller knowing that + * we are interested in this + * interrupt if it occurs in + * the future. + */ + info = xswitch_info_get(soft->busv); + if (!info) + return 1; + vhdl = xswitch_info_vhdl_get(info, port); + if (vhdl == GRAPH_VERTEX_NONE) + return 1; + wid = (widget_cfg_t *) xtalk_piotrans_addr + (vhdl, 0, 0, sizeof *wid, 0); + if (!wid) + return 1; + soft->wpio[port - BASE_XBOW_PORT] = wid; + } + id = wid->w_id; + part = XWIDGET_PART_NUM(id); + mfgr = XWIDGET_MFG_NUM(id); + + /* If this thing is not a Bridge, + * do not activate the WAR, and + * tell our caller we do not need + * to be called again. + */ + if ((part != BRIDGE_WIDGET_PART_NUM) || + (mfgr != BRIDGE_WIDGET_MFGR_NUM)) { + /* FIXME: add Xbridge to the WAR. + * Shouldn't hurt anything. Later need to + * check if we can remove this. + */ + if ((part != XBRIDGE_WIDGET_PART_NUM) || + (mfgr != XBRIDGE_WIDGET_MFGR_NUM)) + return 0; + } + + /* count how many times we + * have picked up after + * LLP Transmit problems. + */ + xbow_xmit_retry_errors++; + + /* rewrite the control register + * to fix things up. + */ + wid->w_control = wid->w_control; + wid->w_control; + + return 1; +} + +/* + * xbow_errintr_handler will be called if the xbow + * sends an interrupt request to report an error. + */ + +#ifdef LATER +static void +xbow_errintr_handler(intr_arg_t arg) +{ +#ifdef IRIX + ioerror_t ioe[1]; + xbow_soft_t soft = (xbow_soft_t) arg; + xbow_t *xbow = soft->base; + xbowreg_t wid_control; + xbowreg_t wid_stat; + xbowreg_t wid_err_cmdword; + xbowreg_t wid_err_upper; + xbowreg_t wid_err_lower; + w_err_cmd_word_u wid_err; + uint64_t wid_err_addr; + + int fatal = 0; + int dump_ioe = 0; + + wid_control = xbow->xb_wid_control; + wid_stat = xbow->xb_wid_stat_clr; + wid_err_cmdword = xbow->xb_wid_err_cmdword; + wid_err_upper = xbow->xb_wid_err_upper; + wid_err_lower = xbow->xb_wid_err_lower; + xbow->xb_wid_err_cmdword = 0; + + wid_err_addr = + wid_err_lower + | (((iopaddr_t) wid_err_upper + & WIDGET_ERR_UPPER_ADDR_ONLY) + << 32); + + if (wid_stat & XB_WID_STAT_LINK_INTR_MASK) { + int port; + + wid_err.r = wid_err_cmdword; + + for (port = MAX_PORT_NUM - MAX_XBOW_PORTS; + port < MAX_PORT_NUM; port++) { + if (wid_stat & XB_WID_STAT_LINK_INTR(port)) { + xb_linkregs_t *link = &(xbow->xb_link(port)); + xbowreg_t link_control = link->link_control; + xbowreg_t link_status = link->link_status_clr; + xbowreg_t link_aux_status = link->link_aux_status; + xbowreg_t link_pend; + + link_pend = link_status & link_control & + (XB_STAT_ILLEGAL_DST_ERR + | XB_STAT_OALLOC_IBUF_ERR + | XB_STAT_RCV_CNT_OFLOW_ERR + | XB_STAT_XMT_CNT_OFLOW_ERR + | XB_STAT_XMT_MAX_RTRY_ERR + | XB_STAT_RCV_ERR + | XB_STAT_XMT_RTRY_ERR + | XB_STAT_MAXREQ_TOUT_ERR + | XB_STAT_SRC_TOUT_ERR + ); + + if (link_pend & XB_STAT_ILLEGAL_DST_ERR) { + if (wid_err.f.sidn == port) { + IOERROR_INIT(ioe); + IOERROR_SETVALUE(ioe, widgetnum, port); + IOERROR_SETVALUE(ioe, xtalkaddr, wid_err_addr); + if (IOERROR_HANDLED == + xbow_error_handler(soft, + IOECODE_DMA, + MODE_DEVERROR, + ioe)) { + link_pend &= ~XB_STAT_ILLEGAL_DST_ERR; + } else { + dump_ioe++; + } + } + } + /* Xbow/Bridge WAR: + * if the bridge signals an LLP Transmitter Retry, + * rewrite its control register. + * If someone else triggers this interrupt, + * ignore (and disable) the interrupt. + */ + if (link_pend & XB_STAT_XMT_RTRY_ERR) { + if (!xbow_xmit_retry_error(soft, port)) { + link_control &= ~XB_CTRL_XMT_RTRY_IE; + link->link_control = link_control; + link->link_control; /* stall until written */ + } + link_pend &= ~XB_STAT_XMT_RTRY_ERR; + } + if (link_pend) { + devfs_handle_t xwidget_vhdl; + char *xwidget_name; + + /* Get the widget name corresponding to the current + * xbow link. + */ + xwidget_vhdl = xbow_widget_lookup(soft->busv,port); + xwidget_name = xwidget_name_get(xwidget_vhdl); + +#ifdef IRIX + cmn_err(CE_CONT, + "%s port %X[%s] XIO Bus Error", + soft->name, port, xwidget_name); + if (link_status & XB_STAT_MULTI_ERR) + XEM_ADD_STR("\tMultiple Errors\n"); + if (link_status & XB_STAT_ILLEGAL_DST_ERR) + XEM_ADD_STR("\tInvalid Packet Destination\n"); + if (link_status & XB_STAT_OALLOC_IBUF_ERR) + XEM_ADD_STR("\tInput Overallocation Error\n"); + if (link_status & XB_STAT_RCV_CNT_OFLOW_ERR) + XEM_ADD_STR("\tLLP receive error counter overflow\n"); + if (link_status & XB_STAT_XMT_CNT_OFLOW_ERR) + XEM_ADD_STR("\tLLP transmit retry counter overflow\n"); + if (link_status & XB_STAT_XMT_MAX_RTRY_ERR) + XEM_ADD_STR("\tLLP Max Transmitter Retry\n"); + if (link_status & XB_STAT_RCV_ERR) + XEM_ADD_STR("\tLLP Receiver error\n"); + if (link_status & XB_STAT_XMT_RTRY_ERR) + XEM_ADD_STR("\tLLP Transmitter Retry\n"); + if (link_status & XB_STAT_MAXREQ_TOUT_ERR) + XEM_ADD_STR("\tMaximum Request Timeout\n"); + if (link_status & XB_STAT_SRC_TOUT_ERR) + XEM_ADD_STR("\tSource Timeout Error\n"); +#endif + + { + int other_port; + + for (other_port = 8; other_port < 16; ++other_port) { + if (link_aux_status & (1 << other_port)) { + /* XXX- need to go to "other_port" + * and clean up after the timeout? + */ + XEM_ADD_VAR(other_port); + } + } + } + +#if !DEBUG + if (kdebug) { +#endif + XEM_ADD_VAR(link_control); + XEM_ADD_VAR(link_status); + XEM_ADD_VAR(link_aux_status); + + if (dump_ioe) { + XEM_ADD_IOE(); + dump_ioe = 0; + } +#if !DEBUG + } +#endif + fatal++; + } + } + } + } + if (wid_stat & wid_control & XB_WID_STAT_WIDGET0_INTR) { + /* we have a "widget zero" problem */ + + if (wid_stat & (XB_WID_STAT_MULTI_ERR + | XB_WID_STAT_XTALK_ERR + | XB_WID_STAT_REG_ACC_ERR)) { + + cmn_err(CE_CONT, + "%s Port 0 XIO Bus Error", + soft->name); + if (wid_stat & XB_WID_STAT_MULTI_ERR) + XEM_ADD_STR("\tMultiple Error\n"); + if (wid_stat & XB_WID_STAT_XTALK_ERR) + XEM_ADD_STR("\tXIO Error\n"); + if (wid_stat & XB_WID_STAT_REG_ACC_ERR) + XEM_ADD_STR("\tRegister Access Error\n"); + + fatal++; + } + } + if (fatal) { + XEM_ADD_VAR(wid_stat); + XEM_ADD_VAR(wid_control); + XEM_ADD_VAR(wid_err_cmdword); + XEM_ADD_VAR(wid_err_upper); + XEM_ADD_VAR(wid_err_lower); + XEM_ADD_VAR(wid_err_addr); + cmn_err_tag(8, CE_PANIC, "XIO Bus Error"); + } +#endif +} +#endif /* LATER */ + +/* + * XBOW ERROR Handling routines. + * These get invoked as part of walking down the error handling path + * from hub/heart towards the I/O device that caused the error. + */ + +/* + * xbow_error_handler + * XBow error handling dispatch routine. + * This is the primary interface used by external world to invoke + * in case of an error related to a xbow. + * Only functionality in this layer is to identify the widget handle + * given the widgetnum. Otherwise, xbow does not gathers any error + * data. + */ + +#ifdef LATER +static int +xbow_error_handler( + void *einfo, + int error_code, + ioerror_mode_t mode, + ioerror_t *ioerror) +{ +#ifdef IRIX + int retval = IOERROR_WIDGETLEVEL; + + xbow_soft_t soft = (xbow_soft_t) einfo; + int port; + devfs_handle_t conn; + devfs_handle_t busv; + + xbow_t *xbow = soft->base; + xbowreg_t wid_stat; + xbowreg_t wid_err_cmdword; + xbowreg_t wid_err_upper; + xbowreg_t wid_err_lower; + uint64_t wid_err_addr; + + xb_linkregs_t *link; + xbowreg_t link_control; + xbowreg_t link_status; + xbowreg_t link_aux_status; + + ASSERT(soft != 0); + busv = soft->busv; + +#if DEBUG && ERROR_DEBUG + cmn_err(CE_CONT, "%s: xbow_error_handler\n", soft->name, busv); +#endif + + port = IOERROR_GETVALUE(ioerror, widgetnum); + + if (port == 0) { + /* error during access to xbow: + * do NOT attempt to access xbow regs. + */ + if (mode == MODE_DEVPROBE) + return IOERROR_HANDLED; + + if (error_code & IOECODE_DMA) { + cmn_err(CE_ALERT, + "DMA error blamed on Crossbow at %s\n" + "\tbut Crosbow never initiates DMA!", + soft->name); + } + if (error_code & IOECODE_PIO) { + cmn_err(CE_ALERT, + "PIO Error on XIO Bus %s\n" + "\tattempting to access XIO controller\n" + "\twith offset 0x%X", + soft->name, + IOERROR_GETVALUE(ioerror, xtalkaddr)); + } + /* caller will dump contents of ioerror + * in DEBUG and kdebug kernels. + */ + + return retval; + } + /* + * error not on port zero: + * safe to read xbow registers. + */ + wid_stat = xbow->xb_wid_stat; + wid_err_cmdword = xbow->xb_wid_err_cmdword; + wid_err_upper = xbow->xb_wid_err_upper; + wid_err_lower = xbow->xb_wid_err_lower; + + wid_err_addr = + wid_err_lower + | (((iopaddr_t) wid_err_upper + & WIDGET_ERR_UPPER_ADDR_ONLY) + << 32); + + if ((port < BASE_XBOW_PORT) || + (port >= MAX_PORT_NUM)) { + + if (mode == MODE_DEVPROBE) + return IOERROR_HANDLED; + + if (error_code & IOECODE_DMA) { + cmn_err(CE_ALERT, + "DMA error blamed on XIO port at %s/%d\n" + "\tbut Crossbow does not support that port", + soft->name, port); + } + if (error_code & IOECODE_PIO) { + cmn_err(CE_ALERT, + "PIO Error on XIO Bus %s\n" + "\tattempting to access XIO port %d\n" + "\t(which Crossbow does not support)" + "\twith offset 0x%X", + soft->name, port, + IOERROR_GETVALUE(ioerror, xtalkaddr)); + } +#if !DEBUG + if (kdebug) { +#endif + XEM_ADD_STR("Raw status values for Crossbow:\n"); + XEM_ADD_VAR(wid_stat); + XEM_ADD_VAR(wid_err_cmdword); + XEM_ADD_VAR(wid_err_upper); + XEM_ADD_VAR(wid_err_lower); + XEM_ADD_VAR(wid_err_addr); +#if !DEBUG + } +#endif + + /* caller will dump contents of ioerror + * in DEBUG and kdebug kernels. + */ + + return retval; + } + /* access to valid port: + * ok to check port status. + */ + + link = &(xbow->xb_link(port)); + link_control = link->link_control; + link_status = link->link_status; + link_aux_status = link->link_aux_status; + + /* Check that there is something present + * in that XIO port. + */ + if (!(link_aux_status & XB_AUX_STAT_PRESENT)) { + /* nobody connected. */ + if (mode == MODE_DEVPROBE) + return IOERROR_HANDLED; + + if (error_code & IOECODE_DMA) { + cmn_err(CE_ALERT, + "DMA error blamed on XIO port at %s/%d\n" + "\tbut there is no device connected there.", + soft->name, port); + } + if (error_code & IOECODE_PIO) { + cmn_err(CE_ALERT, + "PIO Error on XIO Bus %s\n" + "\tattempting to access XIO port %d\n" + "\t(which has no device connected)" + "\twith offset 0x%X", + soft->name, port, + IOERROR_GETVALUE(ioerror, xtalkaddr)); + } +#if !DEBUG + if (kdebug) { +#endif + XEM_ADD_STR("Raw status values for Crossbow:\n"); + XEM_ADD_VAR(wid_stat); + XEM_ADD_VAR(wid_err_cmdword); + XEM_ADD_VAR(wid_err_upper); + XEM_ADD_VAR(wid_err_lower); + XEM_ADD_VAR(wid_err_addr); + XEM_ADD_VAR(port); + XEM_ADD_VAR(link_control); + XEM_ADD_VAR(link_status); + XEM_ADD_VAR(link_aux_status); +#if !DEBUG + } +#endif + return retval; + + } + /* Check that the link is alive. + */ + if (!(link_status & XB_STAT_LINKALIVE)) { + /* nobody connected. */ + if (mode == MODE_DEVPROBE) + return IOERROR_HANDLED; + + cmn_err(CE_ALERT, + "%s%sError on XIO Bus %s port %d", + (error_code & IOECODE_DMA) ? "DMA " : "", + (error_code & IOECODE_PIO) ? "PIO " : "", + soft->name, port); + + if ((error_code & IOECODE_PIO) && + (IOERROR_FIELDVALID(ioerror, xtalkaddr))) { + cmn_err(CE_CONT, + "\tAccess attempted to offset 0x%X\n", + IOERROR_GETVALUE(ioerror, xtalkaddr)); + } + if (link_aux_status & XB_AUX_LINKFAIL_RST_BAD) + XEM_ADD_STR("\tLink never came out of reset\n"); + else + XEM_ADD_STR("\tLink failed while transferring data\n"); + + } + /* get the connection point for the widget + * involved in this error; if it exists and + * is not our connectpoint, cycle back through + * xtalk_error_handler to deliver control to + * the proper handler (or to report a generic + * crosstalk error). + * + * If the downstream handler won't handle + * the problem, we let our upstream caller + * deal with it, after (in DEBUG and kdebug + * kernels) dumping the xbow state for this + * port. + */ + conn = xbow_widget_lookup(busv, port); + if ((conn != GRAPH_VERTEX_NONE) && + (conn != soft->conn)) { + retval = xtalk_error_handler(conn, error_code, mode, ioerror); + if (retval == IOERROR_HANDLED) + return IOERROR_HANDLED; + } + if (mode == MODE_DEVPROBE) + return IOERROR_HANDLED; + + if (retval == IOERROR_UNHANDLED) { + retval = IOERROR_PANIC; + + cmn_err(CE_ALERT, + "%s%sError on XIO Bus %s port %d", + (error_code & IOECODE_DMA) ? "DMA " : "", + (error_code & IOECODE_PIO) ? "PIO " : "", + soft->name, port); + + if ((error_code & IOECODE_PIO) && + (IOERROR_FIELDVALID(ioerror, xtalkaddr))) { + cmn_err(CE_CONT, + "\tAccess attempted to offset 0x%X\n", + IOERROR_GETVALUE(ioerror, xtalkaddr)); + } + } + +#if !DEBUG + if (kdebug) { +#endif + XEM_ADD_STR("Raw status values for Crossbow:\n"); + XEM_ADD_VAR(wid_stat); + XEM_ADD_VAR(wid_err_cmdword); + XEM_ADD_VAR(wid_err_upper); + XEM_ADD_VAR(wid_err_lower); + XEM_ADD_VAR(wid_err_addr); + XEM_ADD_VAR(port); + XEM_ADD_VAR(link_control); + XEM_ADD_VAR(link_status); + XEM_ADD_VAR(link_aux_status); +#if !DEBUG + } +#endif + /* caller will dump raw ioerror data + * in DEBUG and kdebug kernels. + */ + + return retval; +#endif /* IRIX */ +} + +#endif /* LATER */ + +void +xbow_update_perf_counters(devfs_handle_t vhdl) +{ + xbow_soft_t xbow_soft = xbow_soft_get(vhdl); + xbow_perf_t *xbow_perf = xbow_soft->xbow_perfcnt; + xbow_perf_link_t *xbow_plink = xbow_soft->xbow_perflink; + xbow_perfcount_t perf_reg; + int link, s, i; + + for (i = 0; i < XBOW_PERF_COUNTERS; i++, xbow_perf++) { + if (xbow_perf->xp_mode == XBOW_MONITOR_NONE) + continue; + + s = mutex_spinlock(&xbow_soft->xbow_perf_lock); + + perf_reg.xb_counter_val = *(xbowreg_t *) xbow_perf->xp_perf_reg; + + link = perf_reg.xb_perf.link_select; + + (xbow_plink + link)->xlp_cumulative[xbow_perf->xp_curmode] += + ((perf_reg.xb_perf.count - xbow_perf->xp_current) & XBOW_COUNTER_MASK); + xbow_perf->xp_current = perf_reg.xb_perf.count; + + mutex_spinunlock(&xbow_soft->xbow_perf_lock, s); + } + /* Do port /mode multiplexing here */ + +#ifdef IRIX + (void) timeout(xbow_update_perf_counters, + (void *) (__psunsigned_t) vhdl, XBOW_PERF_TIMEOUT); +#endif + +} + +xbow_perf_link_t * +xbow_get_perf_counters(devfs_handle_t vhdl) +{ + xbow_soft_t xbow_soft = xbow_soft_get(vhdl); + xbow_perf_link_t *xbow_perf_link = xbow_soft->xbow_perflink; + + return xbow_perf_link; +} + +int +xbow_enable_perf_counter(devfs_handle_t vhdl, int link, int mode, int counter) +{ + xbow_soft_t xbow_soft = xbow_soft_get(vhdl); + xbow_perf_t *xbow_perf = xbow_soft->xbow_perfcnt; + xbow_linkctrl_t xbow_link_ctrl; + xbow_t *xbow = xbow_soft->base; + xbow_perfcount_t perf_reg; + int s, i; + + link -= BASE_XBOW_PORT; + if ((link < 0) || (link >= MAX_XBOW_PORTS)) + return -1; + + if ((mode < XBOW_MONITOR_NONE) || (mode > XBOW_MONITOR_DEST_LINK)) + return -1; + + if ((counter < 0) || (counter >= XBOW_PERF_COUNTERS)) + return -1; + + s = mutex_spinlock(&xbow_soft->xbow_perf_lock); + + if ((xbow_perf + counter)->xp_mode && mode) { + mutex_spinunlock(&xbow_soft->xbow_perf_lock, s); + return -1; + } + for (i = 0; i < XBOW_PERF_COUNTERS; i++) { + if (i == counter) + continue; + if (((xbow_perf + i)->xp_link == link) && + ((xbow_perf + i)->xp_mode)) { + mutex_spinunlock(&xbow_soft->xbow_perf_lock, s); + return -1; + } + } + xbow_perf += counter; + + xbow_perf->xp_curlink = xbow_perf->xp_link = link; + xbow_perf->xp_curmode = xbow_perf->xp_mode = mode; + + xbow_link_ctrl.xbl_ctrlword = xbow->xb_link_raw[link].link_control; + xbow_link_ctrl.xb_linkcontrol.perf_mode = mode; + xbow->xb_link_raw[link].link_control = xbow_link_ctrl.xbl_ctrlword; + + perf_reg.xb_counter_val = *(xbowreg_t *) xbow_perf->xp_perf_reg; + perf_reg.xb_perf.link_select = link; + *(xbowreg_t *) xbow_perf->xp_perf_reg = perf_reg.xb_counter_val; + xbow_perf->xp_current = perf_reg.xb_perf.count; + +#ifdef IRIX + (void) timeout(xbow_update_perf_counters, + (void *) (__psunsigned_t) vhdl, XBOW_PERF_TIMEOUT); +#endif + + mutex_spinunlock(&xbow_soft->xbow_perf_lock, s); + + return 0; +} + +xbow_link_status_t * +xbow_get_llp_status(devfs_handle_t vhdl) +{ + xbow_soft_t xbow_soft = xbow_soft_get(vhdl); + xbow_link_status_t *xbow_llp_status = xbow_soft->xbow_link_status; + + return xbow_llp_status; +} + +void +xbow_update_llp_status(devfs_handle_t vhdl) +{ + xbow_soft_t xbow_soft = xbow_soft_get(vhdl); + xbow_link_status_t *xbow_llp_status = xbow_soft->xbow_link_status; + xbow_t *xbow; + xbwX_stat_t lnk_sts; + xbow_aux_link_status_t aux_sts; + int link; + devfs_handle_t xwidget_vhdl; + char *xwidget_name; + + xbow = (xbow_t *) xbow_soft->base; + for (link = 0; link < MAX_XBOW_PORTS; link++, xbow_llp_status++) { + /* Get the widget name corresponding the current link. + * Note : 0 <= link < MAX_XBOW_PORTS(8). + * BASE_XBOW_PORT(0x8) <= xwidget number < MAX_PORT_NUM (0x10) + */ + xwidget_vhdl = xbow_widget_lookup(xbow_soft->busv,link+BASE_XBOW_PORT); + xwidget_name = xwidget_name_get(xwidget_vhdl); + aux_sts.aux_linkstatus + = xbow->xb_link_raw[link].link_aux_status; + lnk_sts.linkstatus = xbow->xb_link_raw[link].link_status_clr; + + if (lnk_sts.link_alive == 0) + continue; + + xbow_llp_status->rx_err_count += + aux_sts.xb_aux_linkstatus.rx_err_cnt; + + xbow_llp_status->tx_retry_count += + aux_sts.xb_aux_linkstatus.tx_retry_cnt; + + if (lnk_sts.linkstatus & ~(XB_STAT_RCV_ERR | XB_STAT_XMT_RTRY_ERR | XB_STAT_LINKALIVE)) { +#ifdef IRIX + cmn_err(CE_WARN, "link %d[%s]: bad status 0x%x\n", + link, xwidget_name, lnk_sts.linkstatus); +#endif + } + } +#ifdef IRIX + if (xbow_soft->link_monitor) + (void) timeout(xbow_update_llp_status, + (void *) (__psunsigned_t) vhdl, XBOW_STATS_TIMEOUT); +#endif +} + +int +xbow_disable_llp_monitor(devfs_handle_t vhdl) +{ + xbow_soft_t xbow_soft = xbow_soft_get(vhdl); + int port; + + for (port = 0; port < MAX_XBOW_PORTS; port++) { + xbow_soft->xbow_link_status[port].rx_err_count = 0; + xbow_soft->xbow_link_status[port].tx_retry_count = 0; + } + + xbow_soft->link_monitor = 0; + return 0; +} + +int +xbow_enable_llp_monitor(devfs_handle_t vhdl) +{ + xbow_soft_t xbow_soft = xbow_soft_get(vhdl); + +#ifdef IRIX + (void) timeout(xbow_update_llp_status, + (void *) (__psunsigned_t) vhdl, XBOW_STATS_TIMEOUT); +#endif + xbow_soft->link_monitor = 1; + return 0; +} + + +int +xbow_reset_link(devfs_handle_t xconn_vhdl) +{ + xwidget_info_t widget_info; + xwidgetnum_t port; + xbow_t *xbow; + xbowreg_t ctrl; + xbwX_stat_t stat; + unsigned itick; + unsigned dtick; + static int ticks_per_ms = 0; + + if (!ticks_per_ms) { + itick = get_timestamp(); + us_delay(1000); + ticks_per_ms = get_timestamp() - itick; + } + widget_info = xwidget_info_get(xconn_vhdl); + port = xwidget_info_id_get(widget_info); + +#ifdef XBOW_K1PTR /* defined if we only have one xbow ... */ + xbow = XBOW_K1PTR; +#else + { + devfs_handle_t xbow_vhdl; + xbow_soft_t xbow_soft; + + hwgraph_traverse(xconn_vhdl, ".master/xtalk/0/xbow", &xbow_vhdl); + xbow_soft = xbow_soft_get(xbow_vhdl); + xbow = xbow_soft->base; + } +#endif + + /* + * This requires three PIOs (reset the link, check for the + * reset, restore the control register for the link) plus + * 10us to wait for the reset. We allow up to 1ms for the + * widget to come out of reset before giving up and + * returning a failure. + */ + ctrl = xbow->xb_link(port).link_control; + xbow->xb_link(port).link_reset = 0; + itick = get_timestamp(); + while (1) { + stat.linkstatus = xbow->xb_link(port).link_status; + if (stat.link_alive) + break; + dtick = get_timestamp() - itick; + if (dtick > ticks_per_ms) { + return -1; /* never came out of reset */ + } + DELAY(2); /* don't beat on link_status */ + } + xbow->xb_link(port).link_control = ctrl; + return 0; +} + +/* + * Dump xbow registers. + * input parameter is either a pointer to + * the xbow chip or the vertex handle for + * an xbow vertex. + */ +void +idbg_xbowregs(int64_t regs) +{ + xbow_t *xbow; + int i; + xb_linkregs_t *link; + +#ifdef IRIX + if (dev_is_vertex((devfs_handle_t) regs)) { + devfs_handle_t vhdl = (devfs_handle_t) regs; + xbow_soft_t soft = xbow_soft_get(vhdl); + + xbow = soft->base; + } else +#endif + { + xbow = (xbow_t *) regs; + } + +#ifdef IRIX + qprintf("Printing xbow registers starting at 0x%x\n", xbow); + qprintf("wid %x status %x erruppr %x errlower %x control %x timeout %x\n", + xbow->xb_wid_id, xbow->xb_wid_stat, xbow->xb_wid_err_upper, + xbow->xb_wid_err_lower, xbow->xb_wid_control, + xbow->xb_wid_req_timeout); + qprintf("intr uppr %x lower %x errcmd %x llp ctrl %x arb_reload %x\n", + xbow->xb_wid_int_upper, xbow->xb_wid_int_lower, + xbow->xb_wid_err_cmdword, xbow->xb_wid_llp, + xbow->xb_wid_arb_reload); +#endif + + for (i = 8; i <= 0xf; i++) { + link = &xbow->xb_link(i); +#ifdef IRIX + qprintf("Link %d registers\n", i); + qprintf("\tctrl %x stat %x arbuppr %x arblowr %x auxstat %x\n", + link->link_control, link->link_status, + link->link_arb_upper, link->link_arb_lower, + link->link_aux_status); +#endif + } +} + + +#define XBOW_ARB_RELOAD_TICKS 25 + /* granularity: 4 MB/s, max: 124 MB/s */ +#define GRANULARITY ((100 * 1000000) / XBOW_ARB_RELOAD_TICKS) + +#define XBOW_BYTES_TO_GBR(BYTES_per_s) (int) (BYTES_per_s / GRANULARITY) + +#define XBOW_GBR_TO_BYTES(cnt) (bandwidth_t) ((cnt) * GRANULARITY) + +#define CEILING_BYTES_TO_GBR(gbr, bytes_per_sec) \ + ((XBOW_GBR_TO_BYTES(gbr) < bytes_per_sec) ? gbr+1 : gbr) + +#define XBOW_ARB_GBR_MAX 31 + +#define ABS(x) ((x > 0) ? (x) : (-1 * x)) + /* absolute value */ + +int +xbow_bytes_to_gbr(bandwidth_t old_bytes_per_sec, bandwidth_t bytes_per_sec) +{ + int gbr_granted; + int new_total_gbr; + int change_gbr; + bandwidth_t new_total_bw; + +#ifdef GRIO_DEBUG + printf("xbow_bytes_to_gbr: old_bytes_per_sec %lld bytes_per_sec %lld\n", + old_bytes_per_sec, bytes_per_sec); +#endif /* GRIO_DEBUG */ + + gbr_granted = CEILING_BYTES_TO_GBR((XBOW_BYTES_TO_GBR(old_bytes_per_sec)), + old_bytes_per_sec); + new_total_bw = old_bytes_per_sec + bytes_per_sec; + new_total_gbr = CEILING_BYTES_TO_GBR((XBOW_BYTES_TO_GBR(new_total_bw)), + new_total_bw); + + change_gbr = new_total_gbr - gbr_granted; + +#ifdef GRIO_DEBUG + printf("xbow_bytes_to_gbr: gbr_granted %d new_total_gbr %d change_gbr %d\n", + gbr_granted, new_total_gbr, change_gbr); +#endif /* GRIO_DEBUG */ + + return (change_gbr); +} + +/* Conversion from GBR to bytes */ +bandwidth_t +xbow_gbr_to_bytes(int gbr) +{ + return (XBOW_GBR_TO_BYTES(gbr)); +} + +/* Given the vhdl for the desired xbow, the src and dest. widget ids + * and the req_bw value, this xbow driver entry point accesses the + * xbow registers and allocates the desired bandwidth if available. + * + * If bandwidth allocation is successful, return success else return failure. + */ +int +xbow_prio_bw_alloc(devfs_handle_t vhdl, + xwidgetnum_t src_wid, + xwidgetnum_t dest_wid, + unsigned long long old_alloc_bw, + unsigned long long req_bw) +{ + xbow_soft_t soft = xbow_soft_get(vhdl); + volatile xbowreg_t *xreg; + xbowreg_t mask; + int s; + int error = 0; + bandwidth_t old_bw_BYTES, req_bw_BYTES; + xbowreg_t old_xreg; + int old_bw_GBR, req_bw_GBR, new_bw_GBR; + +#ifdef GRIO_DEBUG + printf("xbow_prio_bw_alloc: vhdl %d src_wid %d dest_wid %d req_bw %lld\n", + (int) vhdl, (int) src_wid, (int) dest_wid, req_bw); +#endif + + ASSERT(XBOW_WIDGET_IS_VALID(src_wid)); + ASSERT(XBOW_WIDGET_IS_VALID(dest_wid)); + + s = mutex_spinlock(&soft->xbow_bw_alloc_lock); + + /* Get pointer to the correct register */ + xreg = XBOW_PRIO_ARBREG_PTR(soft->base, dest_wid, src_wid); + + /* Get mask for GBR count value */ + mask = XB_ARB_GBR_MSK << XB_ARB_GBR_SHFT(src_wid); + + req_bw_GBR = xbow_bytes_to_gbr(old_alloc_bw, req_bw); + req_bw_BYTES = (req_bw_GBR < 0) ? (-1 * xbow_gbr_to_bytes(ABS(req_bw_GBR))) + : xbow_gbr_to_bytes(req_bw_GBR); + +#ifdef GRIO_DEBUG + printf("req_bw %lld req_bw_BYTES %lld req_bw_GBR %d\n", + req_bw, req_bw_BYTES, req_bw_GBR); +#endif /* GRIO_DEBUG */ + + old_bw_BYTES = soft->bw_cur_used[(int) dest_wid - MAX_XBOW_PORTS]; + old_xreg = *xreg; + old_bw_GBR = (((*xreg) & mask) >> XB_ARB_GBR_SHFT(src_wid)); + +#ifdef GRIO_DEBUG + ASSERT(XBOW_BYTES_TO_GBR(old_bw_BYTES) == old_bw_GBR); + + printf("old_bw_BYTES %lld old_bw_GBR %d\n", old_bw_BYTES, old_bw_GBR); + + printf("req_bw_BYTES %lld old_bw_BYTES %lld soft->bw_hiwm %lld\n", + req_bw_BYTES, old_bw_BYTES, + soft->bw_hiwm[(int) dest_wid - MAX_XBOW_PORTS]); + +#endif /* GRIO_DEBUG */ + + /* Accept the request only if we don't exceed the destination + * port HIWATER_MARK *AND* the max. link GBR arbitration count + */ + if (((old_bw_BYTES + req_bw_BYTES) <= + soft->bw_hiwm[(int) dest_wid - MAX_XBOW_PORTS]) && + (req_bw_GBR + old_bw_GBR <= XBOW_ARB_GBR_MAX)) { + + new_bw_GBR = (old_bw_GBR + req_bw_GBR); + + /* Set this in the xbow link register */ + *xreg = (old_xreg & ~mask) | \ + (new_bw_GBR << XB_ARB_GBR_SHFT(src_wid) & mask); + + soft->bw_cur_used[(int) dest_wid - MAX_XBOW_PORTS] = + xbow_gbr_to_bytes(new_bw_GBR); + } else { + error = 1; + } + + mutex_spinunlock(&soft->xbow_bw_alloc_lock, s); + + return (error); +} diff -urN linux-2.4.0-test10/arch/ia64/sn/io/xswitch.c linux-2.4.0-test10-lia/arch/ia64/sn/io/xswitch.c --- linux-2.4.0-test10/arch/ia64/sn/io/xswitch.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/xswitch.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,268 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NEW(ptr) (ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL)) +#define DEL(ptr) (kfree(ptr)) + +int xswitch_devflag = D_MP; + +/* + * This file provides generic support for Crosstalk + * Switches, in a way that insulates crosstalk providers + * from specifics about the switch chips being used. + */ + +#include +#define DEV_FUNC(dev,func) xbow_##func + +#if !defined(DEV_FUNC) +/* + * There is more than one possible provider + * for this platform. We need to examine the + * master vertex of the current vertex for + * a provider function structure, and indirect + * through the appropriately named member. + */ +#define DEV_FUNC(dev,func) xwidget_to_provider_fns(dev)->func + +static xswitch_provider_t * +xwidget_to_provider_fns(devfs_handle_t xconn) +{ + devfs_handle_t busv; + xswitch_info_t xswitch_info; + xswitch_provider_t provider_fns; + + busv = hwgraph_connectpt_get(xconn_vhdl); + ASSERT(busv != GRAPH_VERTEX_NONE); + + xswitch_info = xswitch_info_get(busv); + ASSERT(xswitch_info != NULL); + + provider_fns = xswitch_info->xswitch_fns; + ASSERT(provider_fns != NULL); + + return provider_fns; +} +#endif + +#define XSWITCH_CENSUS_BIT(port) (1<<(port)) +#define XSWITCH_CENSUS_PORT_MIN (0x0) +#define XSWITCH_CENSUS_PORT_MAX (0xF) +#define XSWITCH_CENSUS_PORTS (0x10) +#define XSWITCH_WIDGET_PRESENT(infop,port) ((infop)->census & XSWITCH_CENSUS_BIT(port)) + +static char xswitch_info_fingerprint[] = "xswitch_info"; + +struct xswitch_info_s { + char *fingerprint; + unsigned census; + devfs_handle_t vhdl[XSWITCH_CENSUS_PORTS]; + devfs_handle_t master_vhdl[XSWITCH_CENSUS_PORTS]; + xswitch_provider_t *xswitch_fns; +}; + +xswitch_info_t +xswitch_info_get(devfs_handle_t xwidget) +{ + xswitch_info_t xswitch_info; + + xswitch_info = (xswitch_info_t) + hwgraph_fastinfo_get(xwidget); +#ifdef IRIX + if ((xswitch_info != NULL) && + (xswitch_info->fingerprint != xswitch_info_fingerprint)) + cmn_err(CE_PANIC, "%v xswitch_info_get bad fingerprint", xwidget); +#endif + + printk("xswitch_info_get: xwidget 0x%p xswitch_info 0x%p\n", xwidget, xswitch_info); + + return (xswitch_info); +} + +void +xswitch_info_vhdl_set(xswitch_info_t xswitch_info, + xwidgetnum_t port, + devfs_handle_t xwidget) +{ +#if XSWITCH_CENSUS_PORT_MIN + if (port < XSWITCH_CENSUS_PORT_MIN) + return; +#endif + if (port > XSWITCH_CENSUS_PORT_MAX) + return; + + xswitch_info->vhdl[port - XSWITCH_CENSUS_PORT_MIN] = xwidget; +} + +devfs_handle_t +xswitch_info_vhdl_get(xswitch_info_t xswitch_info, + xwidgetnum_t port) +{ +#ifdef IRIX + if (xswitch_info == NULL) + cmn_err(CE_PANIC, "xswitch_info_vhdl_get: null xswitch_info"); +#endif + +#if XSWITCH_CENSUS_PORT_MIN + if (port < XSWITCH_CENSUS_PORT_MIN) + return GRAPH_VERTEX_NONE; +#endif + if (port > XSWITCH_CENSUS_PORT_MAX) + return GRAPH_VERTEX_NONE; + + return xswitch_info->vhdl[port - XSWITCH_CENSUS_PORT_MIN]; +} + +/* + * Some systems may allow for multiple switch masters. On such systems, + * we assign a master for each port on the switch. These interfaces + * establish and retrieve that assignment. + */ +void +xswitch_info_master_assignment_set(xswitch_info_t xswitch_info, + xwidgetnum_t port, + devfs_handle_t master_vhdl) +{ +#if XSWITCH_CENSUS_PORT_MIN + if (port < XSWITCH_CENSUS_PORT_MIN) + return; +#endif + if (port > XSWITCH_CENSUS_PORT_MAX) + return; + + xswitch_info->master_vhdl[port - XSWITCH_CENSUS_PORT_MIN] = master_vhdl; +} + +devfs_handle_t +xswitch_info_master_assignment_get(xswitch_info_t xswitch_info, + xwidgetnum_t port) +{ +#if XSWITCH_CENSUS_PORT_MIN + if (port < XSWITCH_CENSUS_PORT_MIN) + return GRAPH_VERTEX_NONE; +#endif + if (port > XSWITCH_CENSUS_PORT_MAX) + return GRAPH_VERTEX_NONE; + + return xswitch_info->master_vhdl[port - XSWITCH_CENSUS_PORT_MIN]; +} + +void +xswitch_info_set(devfs_handle_t xwidget, xswitch_info_t xswitch_info) +{ + xswitch_info->fingerprint = xswitch_info_fingerprint; + hwgraph_fastinfo_set(xwidget, (arbitrary_info_t) xswitch_info); +} + +xswitch_info_t +xswitch_info_new(devfs_handle_t xwidget) +{ + xswitch_info_t xswitch_info; + + xswitch_info = xswitch_info_get(xwidget); + if (xswitch_info == NULL) { + int port; + + NEW(xswitch_info); + xswitch_info->census = 0; + for (port = XSWITCH_CENSUS_PORT_MIN; + port <= XSWITCH_CENSUS_PORT_MAX; + port++) { + xswitch_info_vhdl_set(xswitch_info, port, + GRAPH_VERTEX_NONE); + + xswitch_info_master_assignment_set(xswitch_info, + port, + GRAPH_VERTEX_NONE); + } + xswitch_info_set(xwidget, xswitch_info); + printk("xswitch_info_new: xswitch_info_set xwidget 0x%p, xswitch_info 0x%p\n", + xwidget, xswitch_info); + } + return xswitch_info; +} + +void +xswitch_provider_register(devfs_handle_t busv, + xswitch_provider_t * xswitch_fns) +{ + xswitch_info_t xswitch_info = xswitch_info_get(busv); + + ASSERT(xswitch_info); + xswitch_info->xswitch_fns = xswitch_fns; +} + +void +xswitch_info_link_is_ok(xswitch_info_t xswitch_info, xwidgetnum_t port) +{ + xswitch_info->census |= XSWITCH_CENSUS_BIT(port); +} + +int +xswitch_info_link_ok(xswitch_info_t xswitch_info, xwidgetnum_t port) +{ +#if XSWITCH_CENSUS_PORT_MIN + if (port < XSWITCH_CENSUS_PORT_MIN) + return 0; +#endif + + if (port > XSWITCH_CENSUS_PORT_MAX) + return 0; + + return (xswitch_info->census & XSWITCH_CENSUS_BIT(port)); +} + +int +xswitch_reset_link(devfs_handle_t xconn_vhdl) +{ + return DEV_FUNC(xconn_vhdl, reset_link) + (xconn_vhdl); +} + +/* Given a vertex handle to the xswitch get its logical + * id. + */ +int +xswitch_id_get(devfs_handle_t xconn_vhdl) +{ + arbitrary_info_t xbow_num; + graph_error_t rv; + + rv = hwgraph_info_get_LBL(xconn_vhdl,INFO_LBL_XSWITCH_ID,&xbow_num); + ASSERT(rv == GRAPH_SUCCESS); + return(xbow_num); +} + +/* Given a vertex handle to the xswitch set its logical + * id. + */ +void +xswitch_id_set(devfs_handle_t xconn_vhdl,int xbow_num) +{ + graph_error_t rv; + + rv = hwgraph_info_add_LBL(xconn_vhdl,INFO_LBL_XSWITCH_ID, + (arbitrary_info_t)xbow_num); + ASSERT(rv == GRAPH_SUCCESS); +} diff -urN linux-2.4.0-test10/arch/ia64/sn/io/xtalk.c linux-2.4.0-test10-lia/arch/ia64/sn/io/xtalk.c --- linux-2.4.0-test10/arch/ia64/sn/io/xtalk.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/io/xtalk.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,1137 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +/* + * Implement crosstalk provider operations. The xtalk* layer provides a + * platform-independent interface for crosstalk devices. This layer + * switches among the possible implementations of a crosstalk adapter. + * + * On platforms with only one possible xtalk provider, macros can be + * set up at the top that cause the table lookups and indirections to + * completely disappear. + */ + +#define NEW(ptr) (ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL)) +#define DEL(ptr) (kfree(ptr)) + +char widget_info_fingerprint[] = "widget_info"; + +cdl_p xtalk_registry = NULL; + +#include +#define DEV_FUNC(dev,func) hub_##func +#define CAST_PIOMAP(x) ((hub_piomap_t)(x)) +#define CAST_DMAMAP(x) ((hub_dmamap_t)(x)) +#define CAST_INTR(x) ((hub_intr_t)(x)) + +/* ===================================================================== + * Function Table of Contents + */ +xtalk_piomap_t xtalk_piomap_alloc(devfs_handle_t, device_desc_t, iopaddr_t, size_t, size_t, unsigned); +void xtalk_piomap_free(xtalk_piomap_t); +caddr_t xtalk_piomap_addr(xtalk_piomap_t, iopaddr_t, size_t); +void xtalk_piomap_done(xtalk_piomap_t); +caddr_t xtalk_piotrans_addr(devfs_handle_t, device_desc_t, iopaddr_t, size_t, unsigned); +caddr_t xtalk_pio_addr(devfs_handle_t, device_desc_t, iopaddr_t, size_t, xtalk_piomap_t *, unsigned); +void xtalk_set_early_piotrans_addr(xtalk_early_piotrans_addr_f *); +caddr_t xtalk_early_piotrans_addr(xwidget_part_num_t, xwidget_mfg_num_t, int, iopaddr_t, size_t, unsigned); +static caddr_t null_xtalk_early_piotrans_addr(xwidget_part_num_t, xwidget_mfg_num_t, int, iopaddr_t, size_t, unsigned); +xtalk_dmamap_t xtalk_dmamap_alloc(devfs_handle_t, device_desc_t, size_t, unsigned); +void xtalk_dmamap_free(xtalk_dmamap_t); +iopaddr_t xtalk_dmamap_addr(xtalk_dmamap_t, paddr_t, size_t); +alenlist_t xtalk_dmamap_list(xtalk_dmamap_t, alenlist_t, unsigned); +void xtalk_dmamap_done(xtalk_dmamap_t); +iopaddr_t xtalk_dmatrans_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, unsigned); +alenlist_t xtalk_dmatrans_list(devfs_handle_t, device_desc_t, alenlist_t, unsigned); +void xtalk_dmamap_drain(xtalk_dmamap_t); +void xtalk_dmaaddr_drain(devfs_handle_t, iopaddr_t, size_t); +void xtalk_dmalist_drain(devfs_handle_t, alenlist_t); +xtalk_intr_t xtalk_intr_alloc(devfs_handle_t, device_desc_t, devfs_handle_t); +void xtalk_intr_free(xtalk_intr_t); +int xtalk_intr_connect(xtalk_intr_t, intr_func_t, intr_arg_t, xtalk_intr_setfunc_t, void *, void *); +void xtalk_intr_disconnect(xtalk_intr_t); +devfs_handle_t xtalk_intr_cpu_get(xtalk_intr_t); +int xtalk_error_handler(devfs_handle_t, int, ioerror_mode_t, ioerror_t *); +int xtalk_error_devenable(devfs_handle_t, int, int); +void xtalk_provider_startup(devfs_handle_t); +void xtalk_provider_shutdown(devfs_handle_t); +devfs_handle_t xtalk_intr_dev_get(xtalk_intr_t); +xwidgetnum_t xtalk_intr_target_get(xtalk_intr_t); +xtalk_intr_vector_t xtalk_intr_vector_get(xtalk_intr_t); +iopaddr_t xtalk_intr_addr_get(struct xtalk_intr_s *); +void *xtalk_intr_sfarg_get(xtalk_intr_t); +devfs_handle_t xtalk_pio_dev_get(xtalk_piomap_t); +xwidgetnum_t xtalk_pio_target_get(xtalk_piomap_t); +iopaddr_t xtalk_pio_xtalk_addr_get(xtalk_piomap_t); +ulong xtalk_pio_mapsz_get(xtalk_piomap_t); +caddr_t xtalk_pio_kvaddr_get(xtalk_piomap_t); +devfs_handle_t xtalk_dma_dev_get(xtalk_dmamap_t); +xwidgetnum_t xtalk_dma_target_get(xtalk_dmamap_t); +xwidget_info_t xwidget_info_chk(devfs_handle_t); +xwidget_info_t xwidget_info_get(devfs_handle_t); +void xwidget_info_set(devfs_handle_t, xwidget_info_t); +devfs_handle_t xwidget_info_dev_get(xwidget_info_t); +xwidgetnum_t xwidget_info_id_get(xwidget_info_t); +devfs_handle_t xwidget_info_master_get(xwidget_info_t); +xwidgetnum_t xwidget_info_masterid_get(xwidget_info_t); +xwidget_part_num_t xwidget_info_part_num_get(xwidget_info_t); +xwidget_mfg_num_t xwidget_info_mfg_num_get(xwidget_info_t); +char *xwidget_info_name_get(xwidget_info_t); +void xtalk_init(void); +void xtalk_provider_register(devfs_handle_t, xtalk_provider_t *); +void xtalk_provider_unregister(devfs_handle_t); +xtalk_provider_t *xtalk_provider_fns_get(devfs_handle_t); +int xwidget_driver_register(xwidget_part_num_t, + xwidget_mfg_num_t, + char *, unsigned); +void xwidget_driver_unregister(char *); +int xwidget_register(xwidget_hwid_t, devfs_handle_t, + xwidgetnum_t, devfs_handle_t, + xwidgetnum_t, async_attach_t); +int xwidget_unregister(devfs_handle_t); +void xwidget_error_register(devfs_handle_t, error_handler_f *, + error_handler_arg_t); +void xwidget_reset(devfs_handle_t); +char *xwidget_name_get(devfs_handle_t); +#if !defined(DEV_FUNC) +/* + * There is more than one possible provider + * for this platform. We need to examine the + * master vertex of the current vertex for + * a provider function structure, and indirect + * through the appropriately named member. + */ +#define DEV_FUNC(dev,func) xwidget_to_provider_fns(dev)->func +#define CAST_PIOMAP(x) ((xtalk_piomap_t)(x)) +#define CAST_DMAMAP(x) ((xtalk_dmamap_t)(x)) +#define CAST_INTR(x) ((xtalk_intr_t)(x)) + +static xtalk_provider_t * +xwidget_to_provider_fns(devfs_handle_t xconn) +{ + xwidget_info_t widget_info; + xtalk_provider_t *provider_fns; + + widget_info = xwidget_info_get(xconn); + ASSERT(widget_info != NULL); + + provider_fns = xwidget_info_pops_get(widget_info); + ASSERT(provider_fns != NULL); + + return (provider_fns); +} +#endif + +/* + * Many functions are not passed their vertex + * information directly; rather, they must + * dive through a resource map. These macros + * are available to coordinate this detail. + */ +#define PIOMAP_FUNC(map,func) DEV_FUNC(map->xp_dev,func) +#define DMAMAP_FUNC(map,func) DEV_FUNC(map->xd_dev,func) +#define INTR_FUNC(intr,func) DEV_FUNC(intr_hdl->xi_dev,func) + +/* ===================================================================== + * PIO MANAGEMENT + * + * For mapping system virtual address space to + * xtalk space on a specified widget + */ + +xtalk_piomap_t +xtalk_piomap_alloc(devfs_handle_t dev, /* set up mapping for this device */ + device_desc_t dev_desc, /* device descriptor */ + iopaddr_t xtalk_addr, /* map for this xtalk_addr range */ + size_t byte_count, + size_t byte_count_max, /* maximum size of a mapping */ + unsigned flags) +{ /* defined in sys/pio.h */ + return (xtalk_piomap_t) DEV_FUNC(dev, piomap_alloc) + (dev, dev_desc, xtalk_addr, byte_count, byte_count_max, flags); +} + + +void +xtalk_piomap_free(xtalk_piomap_t xtalk_piomap) +{ + PIOMAP_FUNC(xtalk_piomap, piomap_free) + (CAST_PIOMAP(xtalk_piomap)); +} + + +caddr_t +xtalk_piomap_addr(xtalk_piomap_t xtalk_piomap, /* mapping resources */ + iopaddr_t xtalk_addr, /* map for this xtalk address */ + size_t byte_count) +{ /* map this many bytes */ + return PIOMAP_FUNC(xtalk_piomap, piomap_addr) + (CAST_PIOMAP(xtalk_piomap), xtalk_addr, byte_count); +} + + +void +xtalk_piomap_done(xtalk_piomap_t xtalk_piomap) +{ + PIOMAP_FUNC(xtalk_piomap, piomap_done) + (CAST_PIOMAP(xtalk_piomap)); +} + + +caddr_t +xtalk_piotrans_addr(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + iopaddr_t xtalk_addr, /* Crosstalk address */ + size_t byte_count, /* map this many bytes */ + unsigned flags) +{ /* (currently unused) */ + return DEV_FUNC(dev, piotrans_addr) + (dev, dev_desc, xtalk_addr, byte_count, flags); +} + +caddr_t +xtalk_pio_addr(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + iopaddr_t addr, /* starting address (or offset in window) */ + size_t byte_count, /* map this many bytes */ + xtalk_piomap_t *mapp, /* where to return the map pointer */ + unsigned flags) +{ /* PIO flags */ + xtalk_piomap_t map = 0; + caddr_t res; + + if (mapp) + *mapp = 0; /* record "no map used" */ + + res = xtalk_piotrans_addr + (dev, dev_desc, addr, byte_count, flags); + if (res) + return res; /* xtalk_piotrans worked */ + + map = xtalk_piomap_alloc + (dev, dev_desc, addr, byte_count, byte_count, flags); + if (!map) + return res; /* xtalk_piomap_alloc failed */ + + res = xtalk_piomap_addr + (map, addr, byte_count); + if (!res) { + xtalk_piomap_free(map); + return res; /* xtalk_piomap_addr failed */ + } + if (mapp) + *mapp = map; /* pass back map used */ + + return res; /* xtalk_piomap_addr succeeded */ +} + +/* ===================================================================== + * EARLY PIOTRANS SUPPORT + * + * There are places where drivers (mgras, for instance) + * need to get PIO translations before the infrastructure + * is extended to them (setting up textports, for + * instance). These drivers should call + * xtalk_early_piotrans_addr with their xtalk ID + * information, a sequence number (so we can use the second + * mgras for instance), and the usual piotrans parameters. + * + * Machine specific code should provide an implementation + * of early_piotrans_addr, and present a pointer to this + * function to xtalk_set_early_piotrans_addr so it can be + * used by clients without the clients having to know what + * platform or what xtalk provider is in use. + */ + +static xtalk_early_piotrans_addr_f null_xtalk_early_piotrans_addr; + +xtalk_early_piotrans_addr_f *impl_early_piotrans_addr = null_xtalk_early_piotrans_addr; + +/* xtalk_set_early_piotrans_addr: + * specify the early_piotrans_addr implementation function. + */ +void +xtalk_set_early_piotrans_addr(xtalk_early_piotrans_addr_f *impl) +{ + impl_early_piotrans_addr = impl; +} + +/* xtalk_early_piotrans_addr: + * figure out a PIO address for the "nth" crosstalk widget that + * matches the specified part and mfgr number. Returns NULL if + * there is no such widget, or if the requested mapping can not + * be constructed. + * Limitations on which crosstalk slots (and busses) are + * checked, and definitions of the ordering of the search across + * the crosstalk slots, are defined by the platform. + */ +caddr_t +xtalk_early_piotrans_addr(xwidget_part_num_t part_num, + xwidget_mfg_num_t mfg_num, + int which, + iopaddr_t xtalk_addr, + size_t byte_count, + unsigned flags) +{ + return impl_early_piotrans_addr + (part_num, mfg_num, which, xtalk_addr, byte_count, flags); +} + +/* null_xtalk_early_piotrans_addr: + * used as the early_piotrans_addr implementation until and + * unless a real implementation is provided. In DEBUG kernels, + * we want to know who is calling before the implementation is + * registered; in non-DEBUG kernels, return NULL representing + * lack of mapping support. + */ +/*ARGSUSED */ +static caddr_t +null_xtalk_early_piotrans_addr(xwidget_part_num_t part_num, + xwidget_mfg_num_t mfg_num, + int which, + iopaddr_t xtalk_addr, + size_t byte_count, + unsigned flags) +{ +#if DEBUG + cmn_err(CE_PANIC, "null_xtalk_early_piotrans_addr"); +#endif + return NULL; +} + +/* ===================================================================== + * DMA MANAGEMENT + * + * For mapping from crosstalk space to system + * physical space. + */ + +xtalk_dmamap_t +xtalk_dmamap_alloc(devfs_handle_t dev, /* set up mappings for this device */ + device_desc_t dev_desc, /* device descriptor */ + size_t byte_count_max, /* max size of a mapping */ + unsigned flags) +{ /* defined in dma.h */ + return (xtalk_dmamap_t) DEV_FUNC(dev, dmamap_alloc) + (dev, dev_desc, byte_count_max, flags); +} + + +void +xtalk_dmamap_free(xtalk_dmamap_t xtalk_dmamap) +{ + DMAMAP_FUNC(xtalk_dmamap, dmamap_free) + (CAST_DMAMAP(xtalk_dmamap)); +} + + +iopaddr_t +xtalk_dmamap_addr(xtalk_dmamap_t xtalk_dmamap, /* use these mapping resources */ + paddr_t paddr, /* map for this address */ + size_t byte_count) +{ /* map this many bytes */ + return DMAMAP_FUNC(xtalk_dmamap, dmamap_addr) + (CAST_DMAMAP(xtalk_dmamap), paddr, byte_count); +} + + +alenlist_t +xtalk_dmamap_list(xtalk_dmamap_t xtalk_dmamap, /* use these mapping resources */ + alenlist_t alenlist, /* map this Address/Length List */ + unsigned flags) +{ + return DMAMAP_FUNC(xtalk_dmamap, dmamap_list) + (CAST_DMAMAP(xtalk_dmamap), alenlist, flags); +} + + +void +xtalk_dmamap_done(xtalk_dmamap_t xtalk_dmamap) +{ + DMAMAP_FUNC(xtalk_dmamap, dmamap_done) + (CAST_DMAMAP(xtalk_dmamap)); +} + + +iopaddr_t +xtalk_dmatrans_addr(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + paddr_t paddr, /* system physical address */ + size_t byte_count, /* length */ + unsigned flags) +{ /* defined in dma.h */ + return DEV_FUNC(dev, dmatrans_addr) + (dev, dev_desc, paddr, byte_count, flags); +} + + +alenlist_t +xtalk_dmatrans_list(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + alenlist_t palenlist, /* system address/length list */ + unsigned flags) +{ /* defined in dma.h */ + return DEV_FUNC(dev, dmatrans_list) + (dev, dev_desc, palenlist, flags); +} + +void +xtalk_dmamap_drain(xtalk_dmamap_t map) +{ + DMAMAP_FUNC(map, dmamap_drain) + (CAST_DMAMAP(map)); +} + +void +xtalk_dmaaddr_drain(devfs_handle_t dev, paddr_t addr, size_t size) +{ + DEV_FUNC(dev, dmaaddr_drain) + (dev, addr, size); +} + +void +xtalk_dmalist_drain(devfs_handle_t dev, alenlist_t list) +{ + DEV_FUNC(dev, dmalist_drain) + (dev, list); +} + +/* ===================================================================== + * INTERRUPT MANAGEMENT + * + * Allow crosstalk devices to establish interrupts + */ + +/* + * Allocate resources required for an interrupt as specified in intr_desc. + * Return resource handle in intr_hdl. + */ +xtalk_intr_t +xtalk_intr_alloc(devfs_handle_t dev, /* which Crosstalk device */ + device_desc_t dev_desc, /* device descriptor */ + devfs_handle_t owner_dev) +{ /* owner of this interrupt */ + return (xtalk_intr_t) DEV_FUNC(dev, intr_alloc) + (dev, dev_desc, owner_dev); +} + + +/* + * Free resources consumed by intr_alloc. + */ +void +xtalk_intr_free(xtalk_intr_t intr_hdl) +{ + INTR_FUNC(intr_hdl, intr_free) + (CAST_INTR(intr_hdl)); +} + + +/* + * Associate resources allocated with a previous xtalk_intr_alloc call with the + * described handler, arg, name, etc. + * + * Returns 0 on success, returns <0 on failure. + */ +int +xtalk_intr_connect(xtalk_intr_t intr_hdl, /* xtalk intr resource handle */ + intr_func_t intr_func, /* xtalk intr handler */ + intr_arg_t intr_arg, /* arg to intr handler */ + xtalk_intr_setfunc_t setfunc, /* func to set intr hw */ + void *setfunc_arg, /* arg to setfunc */ + void *thread) +{ /* intr thread to use */ + return INTR_FUNC(intr_hdl, intr_connect) + (CAST_INTR(intr_hdl), intr_func, intr_arg, setfunc, setfunc_arg, thread); +} + + +/* + * Disassociate handler with the specified interrupt. + */ +void +xtalk_intr_disconnect(xtalk_intr_t intr_hdl) +{ + INTR_FUNC(intr_hdl, intr_disconnect) + (CAST_INTR(intr_hdl)); +} + + +/* + * Return a hwgraph vertex that represents the CPU currently + * targeted by an interrupt. + */ +devfs_handle_t +xtalk_intr_cpu_get(xtalk_intr_t intr_hdl) +{ + return INTR_FUNC(intr_hdl, intr_cpu_get) + (CAST_INTR(intr_hdl)); +} + + +/* + * ===================================================================== + * ERROR MANAGEMENT + */ + +/* + * xtalk_error_handler: + * pass this error on to the handler registered + * at the specified xtalk connecdtion point, + * or complain about it here if there is no handler. + * + * This routine plays two roles during error delivery + * to most widgets: first, the external agent (heart, + * hub, or whatever) calls in with the error and the + * connect point representing the crosstalk switch, + * or whatever crosstalk device is directly connected + * to the agent. + * + * If there is a switch, it will generally look at the + * widget number stashed in the ioerror structure; and, + * if the error came from some widget other than the + * switch, it will call back into xtalk_error_handler + * with the connection point of the offending port. + */ +int +xtalk_error_handler( + devfs_handle_t xconn, + int error_code, + ioerror_mode_t mode, + ioerror_t *ioerror) +{ + xwidget_info_t xwidget_info; + +#if DEBUG && ERROR_DEBUG + cmn_err(CE_CONT, "%v: xtalk_error_handler\n", xconn); +#endif + + xwidget_info = xwidget_info_get(xconn); + /* Make sure that xwidget_info is a valid pointer before derefencing it. + * We could come in here during very early initialization. + */ + if (xwidget_info && xwidget_info->w_efunc) + return xwidget_info->w_efunc + (xwidget_info->w_einfo, + error_code, mode, ioerror); + /* + * no error handler registered for + * the offending port. it's not clear + * what needs to be done, but reporting + * it would be a good thing, unless it + * is a mode that requires nothing. + */ + if ((mode == MODE_DEVPROBE) || (mode == MODE_DEVUSERERROR) || + (mode == MODE_DEVREENABLE)) + return IOERROR_HANDLED; + +#ifdef IRIX + cmn_err(CE_WARN, "Xbow at %v encountered Fatal error", xconn); +#endif + ioerror_dump("xtalk", error_code, mode, ioerror); + + return IOERROR_UNHANDLED; +} + +int +xtalk_error_devenable(devfs_handle_t xconn_vhdl, int devnum, int error_code) +{ + return DEV_FUNC(xconn_vhdl, error_devenable) (xconn_vhdl, devnum, error_code); +} + + +/* ===================================================================== + * CONFIGURATION MANAGEMENT + */ + +/* + * Startup a crosstalk provider + */ +void +xtalk_provider_startup(devfs_handle_t xtalk_provider) +{ + DEV_FUNC(xtalk_provider, provider_startup) + (xtalk_provider); +} + + +/* + * Shutdown a crosstalk provider + */ +void +xtalk_provider_shutdown(devfs_handle_t xtalk_provider) +{ + DEV_FUNC(xtalk_provider, provider_shutdown) + (xtalk_provider); +} + +/* + * Enable a device on a xtalk widget + */ +void +xtalk_widgetdev_enable(devfs_handle_t xconn_vhdl, int devnum) +{ + DEV_FUNC(xconn_vhdl, widgetdev_enable) (xconn_vhdl, devnum); +} + +/* + * Shutdown a device on a xtalk widget + */ +void +xtalk_widgetdev_shutdown(devfs_handle_t xconn_vhdl, int devnum) +{ + DEV_FUNC(xconn_vhdl, widgetdev_shutdown) (xconn_vhdl, devnum); +} + +int +xtalk_dma_enabled(devfs_handle_t xconn_vhdl) +{ + return DEV_FUNC(xconn_vhdl, dma_enabled) (xconn_vhdl); +} +/* + * Generic crosstalk functions, for use with all crosstalk providers + * and all crosstalk devices. + */ + +/****** Generic crosstalk interrupt interfaces ******/ +devfs_handle_t +xtalk_intr_dev_get(xtalk_intr_t xtalk_intr) +{ + return (xtalk_intr->xi_dev); +} + +xwidgetnum_t +xtalk_intr_target_get(xtalk_intr_t xtalk_intr) +{ + return (xtalk_intr->xi_target); +} + +xtalk_intr_vector_t +xtalk_intr_vector_get(xtalk_intr_t xtalk_intr) +{ + return (xtalk_intr->xi_vector); +} + +iopaddr_t +xtalk_intr_addr_get(struct xtalk_intr_s *xtalk_intr) +{ + return (xtalk_intr->xi_addr); +} + +void * +xtalk_intr_sfarg_get(xtalk_intr_t xtalk_intr) +{ + return (xtalk_intr->xi_sfarg); +} + + +int +xtalk_intr_flags_get(xtalk_intr_t xtalk_intr) +{ + return(xtalk_intr->xi_flags); +} + +/****** Generic crosstalk pio interfaces ******/ +devfs_handle_t +xtalk_pio_dev_get(xtalk_piomap_t xtalk_piomap) +{ + return (xtalk_piomap->xp_dev); +} + +xwidgetnum_t +xtalk_pio_target_get(xtalk_piomap_t xtalk_piomap) +{ + return (xtalk_piomap->xp_target); +} + +iopaddr_t +xtalk_pio_xtalk_addr_get(xtalk_piomap_t xtalk_piomap) +{ + return (xtalk_piomap->xp_xtalk_addr); +} + +ulong +xtalk_pio_mapsz_get(xtalk_piomap_t xtalk_piomap) +{ + return (xtalk_piomap->xp_mapsz); +} + +caddr_t +xtalk_pio_kvaddr_get(xtalk_piomap_t xtalk_piomap) +{ + return (xtalk_piomap->xp_kvaddr); +} + + +/****** Generic crosstalk dma interfaces ******/ +devfs_handle_t +xtalk_dma_dev_get(xtalk_dmamap_t xtalk_dmamap) +{ + return (xtalk_dmamap->xd_dev); +} + +xwidgetnum_t +xtalk_dma_target_get(xtalk_dmamap_t xtalk_dmamap) +{ + return (xtalk_dmamap->xd_target); +} + + +/****** Generic crosstalk widget information interfaces ******/ + +/* xwidget_info_chk: + * check to see if this vertex is a widget; + * if so, return its widget_info (if any). + * if not, return NULL. + */ +xwidget_info_t +xwidget_info_chk(devfs_handle_t xwidget) +{ + arbitrary_info_t ainfo = 0; + + hwgraph_info_get_LBL(xwidget, INFO_LBL_XWIDGET, &ainfo); + return (xwidget_info_t) ainfo; +} + + +xwidget_info_t +xwidget_info_get(devfs_handle_t xwidget) +{ + xwidget_info_t widget_info; + + widget_info = (xwidget_info_t) + hwgraph_fastinfo_get(xwidget); + +#ifdef IRIX + if ((widget_info != NULL) && + (widget_info->w_fingerprint != widget_info_fingerprint)) + cmn_err(CE_PANIC, "%v bad xwidget_info", xwidget); +#endif + + return (widget_info); +} + +void +xwidget_info_set(devfs_handle_t xwidget, xwidget_info_t widget_info) +{ + if (widget_info != NULL) + widget_info->w_fingerprint = widget_info_fingerprint; + + hwgraph_fastinfo_set(xwidget, (arbitrary_info_t) widget_info); + + /* Also, mark this vertex as an xwidget, + * and use the widget_info, so xwidget_info_chk + * can work (and be fairly efficient). + */ + hwgraph_info_add_LBL(xwidget, INFO_LBL_XWIDGET, + (arbitrary_info_t) widget_info); +} + +devfs_handle_t +xwidget_info_dev_get(xwidget_info_t xwidget_info) +{ + if (xwidget_info == NULL) + panic("null xwidget_info"); + return (xwidget_info->w_vertex); +} + +xwidgetnum_t +xwidget_info_id_get(xwidget_info_t xwidget_info) +{ + if (xwidget_info == NULL) + panic("null xwidget_info"); + return (xwidget_info->w_id); +} + + +devfs_handle_t +xwidget_info_master_get(xwidget_info_t xwidget_info) +{ + if (xwidget_info == NULL) + panic("null xwidget_info"); + return (xwidget_info->w_master); +} + +xwidgetnum_t +xwidget_info_masterid_get(xwidget_info_t xwidget_info) +{ + if (xwidget_info == NULL) + panic("null xwidget_info"); + return (xwidget_info->w_masterid); +} + +xwidget_part_num_t +xwidget_info_part_num_get(xwidget_info_t xwidget_info) +{ + if (xwidget_info == NULL) + panic("null xwidget_info"); + return (xwidget_info->w_hwid.part_num); +} + +xwidget_mfg_num_t +xwidget_info_mfg_num_get(xwidget_info_t xwidget_info) +{ + if (xwidget_info == NULL) + panic("null xwidget_info"); + return (xwidget_info->w_hwid.mfg_num); +} +/* Extract the widget name from the widget information + * for the xtalk widget. + */ +char * +xwidget_info_name_get(xwidget_info_t xwidget_info) +{ + if (xwidget_info == NULL) + panic("null xwidget info"); + return(xwidget_info->w_name); +} +/****** Generic crosstalk initialization interfaces ******/ + +/* + * One-time initialization needed for systems that support crosstalk. + */ +void +xtalk_init(void) +{ + cdl_p cp; + +#if DEBUG && ATTACH_DEBUG + printf("xtalk_init\n"); +#endif + /* Allocate the registry. + * We might already have one. + * If we don't, go get one. + * MPness: someone might have + * set one up for us while we + * were not looking; use an atomic + * compare-and-swap to commit to + * using the new registry if and + * only if nobody else did first. + * If someone did get there first, + * toss the one we allocated back + * into the pool. + */ + if (xtalk_registry == NULL) { + cp = cdl_new(EDGE_LBL_XIO, "part", "mfgr"); + if (!compare_and_swap_ptr((void **) &xtalk_registry, NULL, (void *) cp)) { + cdl_del(cp); + } + } + ASSERT(xtalk_registry != NULL); +} + +/* + * Associate a set of xtalk_provider functions with a vertex. + */ +void +xtalk_provider_register(devfs_handle_t provider, xtalk_provider_t *xtalk_fns) +{ + hwgraph_fastinfo_set(provider, (arbitrary_info_t) xtalk_fns); +} + +/* + * Disassociate a set of xtalk_provider functions with a vertex. + */ +void +xtalk_provider_unregister(devfs_handle_t provider) +{ + hwgraph_fastinfo_set(provider, (arbitrary_info_t)NULL); +} + +/* + * Obtain a pointer to the xtalk_provider functions for a specified Crosstalk + * provider. + */ +xtalk_provider_t * +xtalk_provider_fns_get(devfs_handle_t provider) +{ + return ((xtalk_provider_t *) hwgraph_fastinfo_get(provider)); +} + +/* + * Announce a driver for a particular crosstalk part. + * Returns 0 on success or -1 on failure. Failure occurs if the + * specified hardware already has a driver. + */ +/*ARGSUSED4 */ +int +xwidget_driver_register(xwidget_part_num_t part_num, + xwidget_mfg_num_t mfg_num, + char *driver_prefix, + unsigned flags) +{ + /* a driver's init routine could call + * xwidget_driver_register before the + * system calls xtalk_init; so, we + * make the call here. + */ + if (xtalk_registry == NULL) + xtalk_init(); + + return cdl_add_driver(xtalk_registry, + part_num, mfg_num, + driver_prefix, flags); +} + +/* + * Inform xtalk infrastructure that a driver is no longer available for + * handling any widgets. + */ +void +xwidget_driver_unregister(char *driver_prefix) +{ + /* before a driver calls unregister, + * it must have called registger; so we + * can assume we have a registry here. + */ + ASSERT(xtalk_registry != NULL); + + cdl_del_driver(xtalk_registry, driver_prefix); +} + +/* + * Call some function with each vertex that + * might be one of this driver's attach points. + */ +void +xtalk_iterate(char *driver_prefix, + xtalk_iter_f *func) +{ + ASSERT(xtalk_registry != NULL); + + cdl_iterate(xtalk_registry, driver_prefix, (cdl_iter_f *)func); +} + +/* + * xwidget_register: + * Register a xtalk device (xwidget) by doing the following. + * -allocate and initialize xwidget_info data + * -allocate a hwgraph vertex with name based on widget number (id) + * -look up the widget's initialization function and call it, + * or remember the vertex for later initialization. + * + */ +int +xwidget_register(xwidget_hwid_t hwid, /* widget's hardware ID */ + devfs_handle_t widget, /* widget to initialize */ + xwidgetnum_t id, /* widget's target id (0..f) */ + devfs_handle_t master, /* widget's master vertex */ + xwidgetnum_t targetid, /* master's target id (9/a) */ + async_attach_t aa) +{ + xwidget_info_t widget_info; + char *s,devnm[MAXDEVNAME]; + + /* Allocate widget_info and associate it with widget vertex */ + NEW(widget_info); + + /* Initialize widget_info */ + widget_info->w_vertex = widget; + widget_info->w_id = id; + widget_info->w_master = master; + widget_info->w_masterid = targetid; + widget_info->w_hwid = *hwid; /* structure copy */ + widget_info->w_efunc = 0; + widget_info->w_einfo = 0; + /* + * get the name of this xwidget vertex and keep the info. + * This is needed during errors and interupts, but as + * long as we have it, we can use it elsewhere. + */ + s = dev_to_name(widget,devnm,MAXDEVNAME); + printk("xwidget_register: dev_to_name widget id 0x%p, s = %s\n", widget, s); + widget_info->w_name = kmalloc(strlen(s) + 1, GFP_KERNEL); + strcpy(widget_info->w_name,s); + + xwidget_info_set(widget, widget_info); + + device_master_set(widget, master); + + /* All the driver init routines (including + * xtalk_init) are called before we get into + * attaching devices, so we can assume we + * have a registry here. + */ + ASSERT(xtalk_registry != NULL); + + /* + * Add pointer to async attach info -- tear down will be done when + * the particular descendant is done with the info. + */ + if (aa) + async_attach_add_info(widget, aa); + + return cdl_add_connpt(xtalk_registry, hwid->part_num, hwid->mfg_num, widget); +} + +/* + * xwidget_unregister : + * Unregister the xtalk device and detach all its hwgraph namespace. + */ +int +xwidget_unregister(devfs_handle_t widget) +{ + xwidget_info_t widget_info; + xwidget_hwid_t hwid; + + /* Make sure that we have valid widget information initialized */ + if (!(widget_info = xwidget_info_get(widget))) + return(1); + + /* Remove the inventory information associated + * with the widget. + */ + hwgraph_inventory_remove(widget, -1, -1, -1, -1, -1); + + hwid = &(widget_info->w_hwid); + + cdl_del_connpt(xtalk_registry, hwid->part_num, + hwid->mfg_num, widget); + + /* Clean out the xwidget information */ + (void)kfree(widget_info->w_name); + BZERO((void *)widget_info, sizeof(widget_info)); + DEL(widget_info); + + return(0); +} + +void +xwidget_error_register(devfs_handle_t xwidget, + error_handler_f *efunc, + error_handler_arg_t einfo) +{ + xwidget_info_t xwidget_info; + + xwidget_info = xwidget_info_get(xwidget); + ASSERT(xwidget_info != NULL); + xwidget_info->w_efunc = efunc; + xwidget_info->w_einfo = einfo; +} + +/* + * Issue a link reset to a widget. + */ +void +xwidget_reset(devfs_handle_t xwidget) +{ + xswitch_reset_link(xwidget); + +} + + +void +xwidget_gfx_reset(devfs_handle_t xwidget) +{ + xwidget_info_t info; + + xswitch_reset_link(xwidget); + info = xwidget_info_get(xwidget); +#ifdef IRIX + ASSERT_ALWAYS(info != NULL); +#endif + + /* + * Enable this for other architectures once we add widget_reset to the + * xtalk provider interface. + */ + DEV_FUNC(xtalk_provider, widget_reset) + (xwidget_info_master_get(info), xwidget_info_id_get(info)); +} + +#define ANON_XWIDGET_NAME "No Name" /* Default Widget Name */ + +/* Get the canonical hwgraph name of xtalk widget */ +char * +xwidget_name_get(devfs_handle_t xwidget_vhdl) +{ + xwidget_info_t info; + + /* If we have a bogus widget handle then return + * a default anonymous widget name. + */ + if (xwidget_vhdl == GRAPH_VERTEX_NONE) + return(ANON_XWIDGET_NAME); + /* Read the widget name stored in the widget info + * for the widget setup during widget initialization. + */ + info = xwidget_info_get(xwidget_vhdl); + ASSERT(info != NULL); + return(xwidget_info_name_get(info)); +} +/* + * xtalk_device_powerup + * Reset and initialize the specified xtalk widget + */ +int +xtalk_device_powerup(devfs_handle_t xbus_vhdl, xwidgetnum_t widget) +{ +#ifndef CONFIG_IA64_SGI_IO + extern void io_xswitch_widget_init(devfs_handle_t, + devfs_handle_t, + xwidgetnum_t, + async_attach_t); + io_xswitch_widget_init(xbus_vhdl, + hwgraph_connectpt_get(xbus_vhdl), + widget, + NULL); +#endif /* CONFIG_IA64_SGI_IO */ + + return(0); +} +/* + * xtalk_device_shutdown + * Disable the specified xtalk widget and clean out all the software + * state associated with it. + */ +int +xtalk_device_shutdown(devfs_handle_t xbus_vhdl, xwidgetnum_t widget) +{ + devfs_handle_t widget_vhdl; + char edge_name[8]; + + sprintf(edge_name, "%d", widget); + if (hwgraph_traverse(xbus_vhdl, edge_name, &widget_vhdl) + != GRAPH_SUCCESS) + return(1); + + xwidget_unregister(widget_vhdl); + + return(0); +} +/* + * xtalk_device_inquiry + * Find out hardware information about the xtalk widget. + */ +int +xtalk_device_inquiry(devfs_handle_t xbus_vhdl, xwidgetnum_t widget) +{ + + extern void hub_device_inquiry(devfs_handle_t, xwidgetnum_t); + hub_device_inquiry(xbus_vhdl, widget); + return(0); +} diff -urN linux-2.4.0-test10/arch/ia64/sn/sn1/Makefile linux-2.4.0-test10-lia/arch/ia64/sn/sn1/Makefile --- linux-2.4.0-test10/arch/ia64/sn/sn1/Makefile Thu Mar 30 16:56:04 2000 +++ linux-2.4.0-test10-lia/arch/ia64/sn/sn1/Makefile Wed Nov 15 19:11:39 2000 @@ -5,20 +5,25 @@ # Copyright (C) Srinivasa Thirumalachar (sprasad@engr.sgi.com) # -CFLAGS := $(CFLAGS) -DCONFIG_SGI_SN1 -DSN1 -DSN -DSOFTSDV \ - -DLANGUAGE_C=1 -D_LANGUAGE_C=1 -AFLAGS := $(AFLAGS) -DCONFIG_SGI_SN1 -DSN1 -DSOFTSDV +CFLAGS += -DCONFIG_SGI_SN1 -DSN1 -DSN -DLANGUAGE_C=1 -D_LANGUAGE_C=1 +AFLAGS += -DCONFIG_SGI_SN1 -DSN1 .S.s: - $(CPP) $(AFLAGS) -o $*.s $< + $(CPP) $(AFLAGS) $(AFLAGS_KERNEL) -o $*.s $< .S.o: - $(CC) $(AFLAGS) -c -o $*.o $< + $(CC) $(AFLAGS) $(AFLAGS_KERNEL) -c -o $*.o $< all: sn1.a O_TARGET = sn1.a O_HEADERS = -O_OBJS = irq.o setup.o +O_OBJS = irq.o setup.o iomv.o mm.o smp.o synergy.o sn1_asm.o \ + discontig.o + +ifeq ($(CONFIG_IA64_SGI_AUTOTEST),y) +O_OBJS += llsc4.o +endif + ifeq ($(CONFIG_IA64_GENERIC),y) O_OBJS += machvec.o diff -urN linux-2.4.0-test10/arch/ia64/sn/sn1/discontig.c linux-2.4.0-test10-lia/arch/ia64/sn/sn1/discontig.c --- linux-2.4.0-test10/arch/ia64/sn/sn1/discontig.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/sn1/discontig.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,158 @@ +/* + * Copyright 2000, Silicon Graphics, sprasad@engr.sgi.com + * Copyright 2000, Kanoj Sarcar, kanoj@sgi.com + */ + +/* + * Contains common definitions and globals for NUMA platform + * support. For now, SN-IA64 and SN-MIPS are the NUMA platforms. + */ + +#include +#include +#include +#include +#include + +extern int numnodes ; + +plat_pg_data_t plat_node_data[MAXNODES]; +bootmem_data_t bdata[MAXNODES]; +int chunktonid[MAXCHUNKS]; +int nasid_map[MAXNASIDS]; + +void __init +init_chunktonid(void) +{ + memset(chunktonid, -1, sizeof(chunktonid)) ; +} + +void __init +init_nodeidmap(void) +{ + memset(nasid_map, -1, sizeof(nasid_map)) ; +} + +int cnodeid_map[MAXNODES] ; +void __init +init_cnodeidmap(void) +{ + memset(cnodeid_map, -1, sizeof(cnodeid_map)) ; +} + +int +numa_debug(void) +{ + panic("NUMA debug\n"); + return(0); +} + +int __init +build_cnodeid_map(void) +{ + int i,j ; + + for (i=0,j=0;i= 0) + cnodeid_map[j++] = i ; + } + return j ; +} + +/* + * Since efi_memmap_walk merges contiguous banks, this code will need + * to find all the nasids covered by the input memory descriptor. + */ +static int __init +build_nasid_map(unsigned long start, unsigned long end, void *arg) +{ + unsigned long vaddr = start; + int nasid = GetNasId(__pa(vaddr)); + + while (vaddr < end) { + if (nasid < MAXNASIDS) + nasid_map[nasid] = 0; + else + panic("build_nasid_map"); + vaddr = (unsigned long)__va((unsigned long)(++nasid) << + SN1_NODE_ADDR_SHIFT); + } + return 0; +} + +void __init +fix_nasid_map(void) +{ + int i ; + int j ; + + /* For every nasid */ + for (j=0;jbdata ; + printk("%d 0x%016lx 0x%016lx 0x%016lx\n", i, + bdata->node_boot_start, bdata->node_low_pfn, + (unsigned long)bdata->node_bootmem_map) ; + } +} + +void __init +sn1_discontig_mem_init(void) +{ + extern void setup_sn1_bootmem(int); + int maxnodes ; + + init_chunktonid() ; + init_nodeidmap() ; + init_cnodeidmap() ; + efi_memmap_walk(build_nasid_map, 0) ; + maxnodes = build_cnodeid_map() ; + fix_nasid_map() ; +#ifdef CONFIG_DISCONTIGMEM + setup_sn1_bootmem(maxnodes) ; +#endif + numnodes = maxnodes; + dump_bootmem_info() ; +} + +void +dump_node_data(void) +{ + int i; + + printk("NODE DATA ....\n") ; + printk("Node, Start, Size, MemMap, BitMap, StartP, Mapnr, Size, Id\n") ; + for (i=0;ivalid_addr_bitmap, + NODE_DATA(i)->node_start_paddr, + NODE_DATA(i)->node_start_mapnr, + NODE_DATA(i)->node_size, + NODE_DATA(i)->node_id) ; + } +} + diff -urN linux-2.4.0-test10/arch/ia64/sn/sn1/iomv.c linux-2.4.0-test10-lia/arch/ia64/sn/sn1/iomv.c --- linux-2.4.0-test10/arch/ia64/sn/sn1/iomv.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/sn1/iomv.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,40 @@ +/* + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Jack Steiner (steiner@sgi.com) + */ + +#include +#include + +void * +Xsn1_mk_io_addr(unsigned long port) +{ + if (!IS_RUNNING_ON_SIMULATOR()) { + return( (void *) (port | __IA64_UNCACHED_OFFSET)); + } else { + unsigned long io_base; + unsigned long addr; + + /* + * word align port, but need more than 10 bits + * for accessing registers in bedrock local block + * (so we don't do port&0xfff) + */ + if (port == 0x1f6 || port == 0x1f7 + || port == 0x3f6 || port == 0x3f7 + || port == 0x1f0 || port == 0x1f1 + || port == 0x1f3 || port == 0x1f4 + || port == 0x1f2 || port == 0x1f5) { + io_base = __IA64_UNCACHED_OFFSET | 0x00000FFFFC000000; + addr = io_base | ((port >> 2) << 12) | (port & 0xfff); + } else { + addr = __ia64_get_io_port_base() | ((port >> 2) << 2); + } + return(void *) addr; + } +} diff -urN linux-2.4.0-test10/arch/ia64/sn/sn1/irq.c linux-2.4.0-test10-lia/arch/ia64/sn/sn1/irq.c --- linux-2.4.0-test10/arch/ia64/sn/sn1/irq.c Fri Aug 11 19:09:06 2000 +++ linux-2.4.0-test10-lia/arch/ia64/sn/sn1/irq.c Wed Nov 15 19:11:39 2000 @@ -1,8 +1,55 @@ -#include +/* + * Platform dependent support for SGI SN1 + * + * Copyright (C) 2000 Silicon Graphics + * Copyright (C) 2000 Jack Steiner (steiner@sgi.com) + * Copyright (C) 2000 Alan Mayer (ajm@sgi.com) + */ + +#include #include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +int bit_pos_to_irq(int bit); +int irq_to_bit_pos(int irq); +void add_interrupt_randomness(int irq); +void * kmalloc(size_t size, int flags); +void kfree(const void *); +int sgi_pci_intr_support (unsigned int, device_desc_t *, devfs_handle_t *, pciio_intr_line_t *, devfs_handle_t *); +pciio_intr_t pciio_intr_alloc(devfs_handle_t, device_desc_t, pciio_intr_line_t, devfs_handle_t); +int ia64_request_irq(unsigned int, void (*)(int, void *, struct pt_regs *), unsigned long, const char *, void *); + +/* This should be dynamically allocated, at least part of it. */ +/* For the time being, though, we'll statically allocate it */ +/* because kmalloc hasn't been initiallized at the time this */ +/* array is initiallized. One way to do it would be to statically */ +/* allocate the data for node 0, then let other nodes, as they */ +/* need it, dynamically allocate their own data space. */ -#include +struct sn1_cnode_action_list *sn1_node_actions[MAX_COMPACT_NODES]; +struct sn1_cnode_action_list sn1_actions[MAX_COMPACT_NODES][256]; + + +extern int numnodes; static unsigned int sn1_startup_irq(unsigned int irq) @@ -25,20 +72,192 @@ { } +static void +sn1_ack_irq(unsigned int irq) +{ +} + +static void +sn1_end_irq(unsigned int irq) +{ +} + +static void +sn1_set_affinity_irq(unsigned int irq, unsigned long mask) +{ +} + + +static void +sn1_handle_irq(int irq, void *dummy, struct pt_regs *regs) +{ + int bit, cnode; + struct sn1_cnode_action_list *alp; + struct sn1_intr_action *ap; + void (*handler)(int, void *, struct pt_regs *); + unsigned long flags = 0; + int cpuid = smp_processor_id(); + + + bit = irq_to_bit_pos(irq); + LOCAL_HUB_CLR_INTR(bit); + cnode = cpuid_to_cnodeid(cpuid); + alp = sn1_node_actions[cnode]; + ap = alp[irq].action_list; + if (ap == NULL) { + return; + } + while (ap) { + flags |= ap->flags; + handler = ap->handler; + (*handler)(irq,ap->intr_arg,regs); + ap = ap->next; + } + if ((flags & SA_SAMPLE_RANDOM) != 0) + add_interrupt_randomness(irq); + + return; +} + struct hw_interrupt_type irq_type_sn1 = { "sn1_irq", sn1_startup_irq, sn1_shutdown_irq, sn1_enable_irq, - sn1_disable_irq + sn1_disable_irq, + sn1_ack_irq, + sn1_end_irq, + sn1_set_affinity_irq +}; + +struct irqaction sn1_irqaction = { + sn1_handle_irq, + 0, + 0, + NULL, + NULL, + NULL, }; void sn1_irq_init (void) { - int i; + int i,j; + + for (i = 0; i <= NR_IRQS; ++i) { + if (irq_desc[i].handler == &no_irq_type) { + irq_desc[i].handler = &irq_type_sn1; + if (i >=71 && i <= 181) { + irq_desc[i].action = &sn1_irqaction; + } + } + } + + for (i = 0; i < numnodes; i++) { + sn1_node_actions[i] = sn1_actions[i]; + memset(sn1_node_actions[i], 0, + sizeof(struct sn1_cnode_action_list) * + (IA64_MAX_VECTORED_IRQ + 1)); + for (j=0; jpi_irq; + cpuid = intr_handle->pi_cpu; + irq = bit_pos_to_irq(bit); + cnode = cpuid_to_cnodeid(cpuid); + new_ap = (struct sn1_intr_action *)kmalloc( + sizeof(struct sn1_intr_action), GFP_KERNEL); + irq_desc[irq].status = 0; + new_ap->handler = handler; + new_ap->intr_arg = dev_id; + new_ap->flags = irqflags; + new_ap->next = NULL; + alp = sn1_node_actions[cnode]; + + spin_lock(&alp[irq].action_list_lock); + ap = alp[irq].action_list; + /* check action list for "share" consistency */ + while (ap){ + if (!(ap->flags & irqflags & SA_SHIRQ) ) { + return(-EBUSY); + spin_unlock(&alp[irq].action_list_lock); + } + ap = ap->next; + } + ap = alp[irq].action_list; + if (ap) { + while (ap->next) { + ap = ap->next; + } + ap->next = new_ap; + } else { + alp[irq].action_list = new_ap; + } + ret = pciio_intr_connect(intr_handle, (intr_func_t)handler, dev_id, NULL); + if (ret) { /* connect failed, undo what we did. */ + new_ap = alp[irq].action_list; + if (new_ap == ap) { + alp[irq].action_list = NULL; + kfree(ap); + } else { + while (new_ap->next && new_ap->next != ap) { + new_ap = new_ap->next; + } + if (new_ap->next == ap) { + new_ap->next = ap->next; + kfree(ap); + } + } + } + + spin_unlock(&alp[irq].action_list_lock); + return(ret); + } else { + return(ia64_request_irq(requested_irq, handler, irqflags, devname, dev_id)); } +} + +#if !defined(CONFIG_IA64_SGI_IO) +void +sn1_pci_fixup(void) +{ +} +#endif + +int +bit_pos_to_irq(int bit) { +#define BIT_TO_IRQ 64 + + return bit + BIT_TO_IRQ; +} + +int +irq_to_bit_pos(int irq) { +#define IRQ_TO_BIT 64 + + return irq - IRQ_TO_BIT; } diff -urN linux-2.4.0-test10/arch/ia64/sn/sn1/llsc4.c linux-2.4.0-test10-lia/arch/ia64/sn/sn1/llsc4.c --- linux-2.4.0-test10/arch/ia64/sn/sn1/llsc4.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/sn1/llsc4.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,929 @@ +/* + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Jack Steiner (steiner@sgi.com) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern void bringup_set_led_bits(u8 bits, u8 mask); + +#include "llsc4.h" + + +#ifdef STANDALONE +#include "lock.h" +#endif + +#ifdef INTTEST +static int inttest=0; +#endif + + +/* + * Test parameter table for AUTOTEST + */ +typedef struct { + int passes; + int linecount; + int linepad; +} autotest_table_t; + +autotest_table_t autotest_table[] = { + {1000000, 2, 0x2b4 }, + {1000000, 16, 0, }, + {1000000, 16, 4, }, + {1000000, 128, 0x44 }, + {1000000, 128, 0x84 }, + {1000000, 128, 0x200 }, + {1000000, 128, 0x204 }, + {1000000, 128, 0x2b4 }, + {1000000, 2, 8*MB+0x2b4 }, + {1000000, 16, 8*MB+0 }, + {1000000, 16, 8*MB+4 }, + {1000000, 128, 8*MB+0x44 }, + {1000000, 128, 8*MB+0x84 }, + {1000000, 128, 8*MB+0x200 }, + {1000000, 128, 8*MB+0x204 }, + {1000000, 128, 8*MB+0x2b4 }, + {0}}; + +/* + * Array of virtual addresses available for test purposes. + */ + +typedef struct { + long vstart; + long vend; + long nextaddr; + int wrapcount; +} memmap_t; + +memmap_t memmap[MAXCHUNKS]; +int memmapx=0; + +typedef struct { + void *addr; + long data[16]; + long data_fc[16]; +} capture_line_t; + +typedef struct { + int size; + void *blockaddr; + void *shadaddr; + long blockdata[16]; + long shaddata[16]; + long blockdata_fc[16]; + long shaddata_fc[16]; + long synerr; +} capture_t; + +/* + * PORTING NOTE: revisit this statement. On hardware we put mbase at 0 and + * the rest of the tables have to start at 1MB to skip PROM tables. + */ +#define THREADPRIVATE(t) ((threadprivate_t*)(((long)mbase)+1024*1024+t*((sizeof(threadprivate_t)+511)/512*512))) + +#define k_capture mbase->sk_capture +#define k_go mbase->sk_go +#define k_linecount mbase->sk_linecount +#define k_passes mbase->sk_passes +#define k_napticks mbase->sk_napticks +#define k_stop_on_error mbase->sk_stop_on_error +#define k_verbose mbase->sk_verbose +#define k_threadprivate mbase->sk_threadprivate +#define k_blocks mbase->sk_blocks +#define k_iter_msg mbase->sk_iter_msg +#define k_vv mbase->sk_vv +#define k_linepad mbase->sk_linepad +#define k_options mbase->sk_options +#define k_testnumber mbase->sk_testnumber +#define k_currentpass mbase->sk_currentpass + +static long blocks[MAX_LINECOUNT]; /* addresses of data blocks */ +static control_t *mbase; +static vint initialized=0; + +static unsigned int ran_conf_llsc(int); +static int rerr(capture_t *, char *, void *, void *, int, int, int, int, int, int); +static void dumpline(void *, char *, char *, void *, void *, int); +static int checkstop(int, int, uint); +static void spin(int); +static void capturedata(capture_t *, uint, void *, void *, int); +static int randn(uint max, uint *seed); +static uint zrandom (uint *zranseed); +static int set_lock(uint *, uint); +static int clr_lock(uint *, uint); +static void Speedo(void); + +int autotest_enabled=0; +static int autotest_explicit_flush=0; +static int llsctest_number=-1; +static int errstop_enabled=0; +static int fail_enabled=0; +static int selective_trigger=0; + +static int __init autotest_enable(char *str) +{ + autotest_enabled = 1; + return 1; +} +static int __init set_llscxflush(char *str) +{ + autotest_explicit_flush = 1; + return 1; +} +static int __init set_llscselt(char *str) +{ + selective_trigger = 1; + return 1; +} +static int __init set_llsctest(char *str) +{ + llsctest_number = simple_strtol(str, &str, 10); + if (llsctest_number < 0 || llsctest_number > 15) + llsctest_number = -1; + return 1; +} +static int __init set_llscerrstop(char *str) +{ + errstop_enabled = 1; + return 1; +} +static int __init set_llscfail(char *str) +{ + fail_enabled = 8; + return 1; +} + +static void print_params(void) +{ + printk ("********* Enter AUTOTEST facility on master cpu *************\n"); + printk (" Test options:\n"); + printk (" llsctest=\t%d\tTest number to run (all = -1)\n", llsctest_number); + printk (" llscerrstop \t%s\tStop on error\n", errstop_enabled ? "on" : "off"); + printk (" llscxflush \t%s\tEnable explicit FC in test\n", autotest_explicit_flush ? "on" : "off"); + printk (" llscfail \t%s\tForce a failure to test the trigger & error messages\n", fail_enabled ? "on" : "off"); + printk (" llscselt \t%s\tSelective triger on failures\n", selective_trigger ? "on" : "off"); + printk ("\n"); +} +__setup("autotest", autotest_enable); +__setup("llsctest=", set_llsctest); +__setup("llscerrstop", set_llscerrstop); +__setup("llscxflush", set_llscxflush); +__setup("llscfail", set_llscfail); +__setup("llscselt", set_llscselt); + + +extern inline void +flush_buddy(void *p) +{ + long lp; + + if (autotest_explicit_flush) { + lp = (long)p; + lp ^= 0x40; + asm volatile ("fc %0" :: "r"(lp) : "memory"); + ia64_sync_i(); + ia64_srlz_d(); + } +} + +static int +set_lock(uint *lock, uint id) +{ + uint old; + flush_buddy(lock); + old = cmpxchg_acq(lock, 0, id); + return (old == 0); +} + +static int +clr_lock(uint *lock, uint id) +{ + uint old; + flush_buddy(lock); + old = cmpxchg_rel(lock, id, 0); + return (old == id); +} + +static void +zero_lock(uint *lock) +{ + flush_buddy(lock); + *lock = 0; +} + +/*------------------------------------------------------------------------+ +| Routine : ran_conf_llsc - ll/sc shared data test | +| Description: This test checks the coherency of shared data | ++------------------------------------------------------------------------*/ +static unsigned int +ran_conf_llsc(int thread) +{ + private_t pval; + share_t sval, sval2; + uint vv, linei, slinei, sharei, pass; + long t; + lock_t lockpat; + share_t *sharecopy; + long verbose, napticks, passes, linecount, lcount; + dataline_t *linep, *slinep; + int s, seed; + threadprivate_t *tp; + uint iter_msg, iter_msg_i=0; + int vv_mask; + int correct_errors; + int errs=0; + int stillbad; + capture_t capdata; + private_t *privp; + share_t *sharep; + + + linecount = k_linecount; + napticks = k_napticks; + verbose = k_verbose; + passes = k_passes; + iter_msg = k_iter_msg; + seed = (thread + 1) * 647; + tp = THREADPRIVATE(thread); + vv_mask = (k_vv>>((thread%16)*4)) & 0xf; + correct_errors = k_options&0xff; + + memset (&tp->private, 0, sizeof(tp->private)); + memset (&capdata, 0, sizeof(capdata)); + + for (pass = 1; passes == 0 || pass < passes; pass++) { + lockpat = (pass & 0x0fffffff) + (thread <<28); + tp->threadpasses = pass; + if (checkstop(thread, pass, lockpat)) + return 0; + iter_msg_i++; + if (iter_msg && iter_msg_i > iter_msg) { + printk("Thread %d, Pass %d\n", thread, pass); + iter_msg_i = 0; + } + lcount = 0; + + /* + * Select line to perform operations on. + */ + linei = randn(linecount, &seed); + sharei = randn(2, &seed); + slinei = (linei + (linecount/2))%linecount; /* I dont like this - fix later */ + + linep = (dataline_t *)blocks[linei]; + slinep = (dataline_t *)blocks[slinei]; + if (sharei == 0) + sharecopy = &slinep->share0; + else + sharecopy = &slinep->share1; + + + vv = randn(4, &seed); + if ((vv_mask & (1<private[thread]; + sharep = &linep->share[sharei]; + + switch(vv) { + case 0: + /* Read and verify private count on line. */ + pval = *privp; + if (verbose) + printk("Line:%3d, Thread:%d:%d. Val: %x\n", linei, thread, vv, tp->private[linei]); + if (pval != tp->private[linei]) { + capturedata(&capdata, pass, privp, NULL, sizeof(*privp)); + stillbad = (*privp != tp->private[linei]); + if (rerr(&capdata, "Private count", linep, slinep, thread, pass, linei, tp->private[linei], pval, stillbad)) { + return 1; + } + if (correct_errors) { + flush_buddy(privp); + tp->private[linei] = *privp; + } + errs++; + } + break; + + case 1: + /* Read, verify, and increment private count on line. */ + pval = *privp; + if (verbose) + printk("Line:%3d, Thread:%d:%d. Val: %x\n", linei, thread, vv, tp->private[linei]); + if (pval != tp->private[linei]) { + capturedata(&capdata, pass, privp, NULL, sizeof(*privp)); + stillbad = (*privp != tp->private[linei]); + if (rerr(&capdata, "Private count & inc", linep, slinep, thread, pass, linei, tp->private[linei], pval, stillbad)) { + return 1; + } + errs++; + } + pval++; + flush_buddy(privp); + *privp = pval; + tp->private[linei] = pval; + break; + + case 2: + /* Lock line, read and verify shared data. */ + if (verbose) + printk("Line:%3d, Thread:%d:%d. Val: %x\n", linei, thread, vv, *sharecopy); + lcount = 0; + while (LOCK(sharei) != 1) { + if (checkstop(thread, pass, lockpat)) + return 0; + if (lcount++>1000000) { + capturedata(&capdata, pass, LOCKADDR(sharei), NULL, sizeof(lock_t)); + stillbad = (GETLOCK(sharei) != 0); + rerr(&capdata, "Shared data lock", linep, slinep, thread, pass, linei, 0, GETLOCK(sharei), stillbad); + return 1; + } + if ((lcount&0x3fff) == 0) + udelay(1000); + } + + sval = *sharep; + sval2 = *sharecopy; + if (pass > 12 && thread == 0 && fail_enabled == 1) + sval++; + if (sval != sval2) { + capturedata(&capdata, pass, sharep, sharecopy, sizeof(*sharecopy)); + stillbad = (*sharep != *sharecopy); + if (!stillbad && *sharep != sval && *sharecopy == sval2) + stillbad = 2; + if (rerr(&capdata, "Shared data", linep, slinep, thread, pass, linei, sval2, sval, stillbad)) { + return 1; + } + if (correct_errors) + *sharep = *sharecopy; + errs++; + } + + + if ( (s=UNLOCK(sharei)) != 1) { + capturedata(&capdata, pass, LOCKADDR(sharei), NULL, 4); + stillbad = (GETLOCK(sharei) != lockpat); + if (rerr(&capdata, "Shared data unlock", linep, slinep, thread, pass, linei, lockpat, GETLOCK(sharei), stillbad)) + return 1; + if (correct_errors) + ZEROLOCK(sharei); + errs++; + } + break; + + case 3: + /* Lock line, read and verify shared data, modify shared data. */ + if (verbose) + printk("Line:%3d, Thread:%d:%d. Val: %x\n", linei, thread, vv, *sharecopy); + lcount = 0; + while (LOCK(sharei) != 1) { + if (checkstop(thread, pass, lockpat)) + return 0; + if (lcount++>1000000) { + capturedata(&capdata, pass, LOCKADDR(sharei), NULL, sizeof(lock_t)); + stillbad = (GETLOCK(sharei) != 0); + rerr(&capdata, "Shared data lock & inc", linep, slinep, thread, pass, linei, 0, GETLOCK(sharei), stillbad); + return 1; + } + if ((lcount&0x3fff) == 0) + udelay(1000); + } + sval = *sharep; + sval2 = *sharecopy; + if (sval != sval2) { + capturedata(&capdata, pass, sharep, sharecopy, sizeof(*sharecopy)); + stillbad = (*sharep != *sharecopy); + if (!stillbad && *sharep != sval && *sharecopy == sval2) + stillbad = 2; + if (rerr(&capdata, "Shared data & inc", linep, slinep, thread, pass, linei, sval2, sval, stillbad)) { + return 1; + } + errs++; + } + + flush_buddy(sharep); + *sharep = lockpat; + flush_buddy(sharecopy); + *sharecopy = lockpat; + + + if ( (s=UNLOCK(sharei)) != 1) { + capturedata(&capdata, pass, LOCKADDR(sharei), NULL, 4); + stillbad = (GETLOCK(sharei) != lockpat); + if (rerr(&capdata, "Shared data & inc unlock", linep, slinep, thread, pass, linei, thread, GETLOCK(sharei), stillbad)) + return 1; + if (correct_errors) + ZEROLOCK(sharei); + errs++; + } + break; + } + } + + return (errs > 0); +} + +static void +trigger_la(long val) +{ + long *p; + + p = (long*)0xc0000a0001000020L; /* PI_CPU_NUM */ + *p = val; +} + +static long +getsynerr(void) +{ + long err, *errp; + + errp = (long*)0xc0000e0000000340L; /* SYN_ERR */ + err = *errp; + if (err) + *errp = -1L; + return (err & ~0x60); +} + +static int +rerr(capture_t *cap, char *msg, void *lp, void *slp, int thread, int pass, int linei, int exp, int found, int stillbad) +{ + int cpu; + long synerr; + int selt; + + + selt = selective_trigger && stillbad > 1 && + memcmp(cap->blockdata, cap->blockdata_fc, 128) != 0 && + memcmp(cap->shaddata, cap->shaddata_fc, 128) == 0; + if (selt) { + trigger_la(pass); + } else if (selective_trigger) { + k_go = ST_STOP; + return k_stop_on_error;; + } + + spin(1); + printk ("\nDataError!: %-20s, test %ld, thread %d, line:%d, pass %d (0x%x), time %ld, expected:%x, found:%x\n", + msg, k_testnumber, thread, linei, pass, pass, jiffies/100, exp, found); + + dumpline (lp, "Corrupted data", "D ", cap->blockaddr, cap->blockdata, cap->size); + if (memcmp(cap->blockdata, cap->blockdata_fc, 128)) + dumpline (lp, "Corrupted data", "DF", cap->blockaddr, cap->blockdata_fc, cap->size); + + if (cap->shadaddr) { + dumpline (slp, "Shadow data", "S ", cap->shadaddr, cap->shaddata, cap->size); + if (memcmp(cap->shaddata, cap->shaddata_fc, 128)) + dumpline (slp, "Shadow data", "SF", cap->shadaddr, cap->shaddata_fc, cap->size); + } + + printk("Threadpasses: "); + for (cpu=0; cputhreadpasses) + printk(" %d:0x%x", cpu, k_threadprivate[cpu]->threadpasses); + + + printk("\nData was %sfixed by flushcache\n", (stillbad == 1 ? "**** NOT **** " : " ")); + synerr = getsynerr(); + if (synerr) + printk("SYNERR: Thread %d, Synerr: 0x%lx\n", thread, synerr); + spin(2); + printk("\n\n"); + + if (errstop_enabled) { + local_irq_disable(); + while(1); + } + return k_stop_on_error; +} + + +static void +dumpline(void *lp, char *str1, char *str2, void *addr, void *data, int size) +{ + long *p; + int i, off; + + printk("%s at 0x%lx, size %d, block starts at 0x%lx\n", str1, (long)addr, size, (long)lp); + p = (long*) data; + for (i=0; i<16; i++, p++) { + if (i==0) printk("%2s", str2); + if (i==8) printk(" "); + printk(" %016lx", *p); + if ((i&7)==7) printk("\n"); + } + printk(" "); + off = (((long)addr) ^ size) & 63L; + for (i=0; i=off) ? "--" : " "); + if ((i%8) == 7) + printk(" "); + } + + off = ((long)addr) & 127; + printk(" (line %d)\n", off/64+1); +} + + +static int +randn(uint max, uint *seedp) +{ + if (max == 1) + return(0); + else + return((int)(zrandom(seedp)>>10) % max); +} + + +static int +checkstop(int thread, int pass, uint lockpat) +{ + long synerr; + + if (k_go == ST_RUN) + return 0; + if (k_go == ST_STOP) + return 1; + + if (errstop_enabled) { + local_irq_disable(); + while(1); + } + synerr = getsynerr(); + spin(2); + if (k_go == ST_STOP) + return 1; + if (synerr) + printk("SYNERR: Thread %d, Synerr: 0x%lx\n", thread, synerr); + return 1; +} + + +static void +spin(int j) +{ + udelay(j * 500000); +} + +static void +capturedata(capture_t *cap, uint pass, void *blockaddr, void *shadaddr, int size) +{ + + if (!selective_trigger) + trigger_la (pass); + + memcpy (cap->blockdata, CACHEALIGN(blockaddr), 128); + if (shadaddr) + memcpy (cap->shaddata, CACHEALIGN(shadaddr), 128); + + if (k_stop_on_error) { + k_go = ST_ERRSTOP; + } + + cap->size = size; + cap->blockaddr = blockaddr; + cap->shadaddr = shadaddr; + + asm volatile ("fc %0" :: "r"(blockaddr) : "memory"); + ia64_sync_i(); + ia64_srlz_d(); + memcpy (cap->blockdata_fc, CACHEALIGN(blockaddr), 128); + + if (shadaddr) { + asm volatile ("fc %0" :: "r"(shadaddr) : "memory"); + ia64_sync_i(); + ia64_srlz_d(); + memcpy (cap->shaddata_fc, CACHEALIGN(shadaddr), 128); + } +} + +int zranmult = 0x48c27395; + +static uint +zrandom (uint *seedp) +{ + *seedp = (*seedp * zranmult) & 0x7fffffff; + return (*seedp); +} + + +void +set_autotest_params(void) +{ + static int testnumber=-1; + + if (llsctest_number >= 0) { + testnumber = llsctest_number; + } else { + testnumber++; + if (autotest_table[testnumber].passes == 0) + testnumber = 0; + } + k_passes = autotest_table[testnumber].passes; + k_linepad = autotest_table[testnumber].linepad; + k_linecount = autotest_table[testnumber].linecount; + k_testnumber = testnumber; + + if (IS_RUNNING_ON_SIMULATOR()) { + printk ("llsc start test %ld\n", k_testnumber); + k_passes = 1000; + } +} + + +static void +set_leds(int errs) +{ + unsigned char leds=0; + + /* + * Leds are: + * ppppeee- + * where + * pppp = test number + * eee = error count but top bit is stick + */ + + leds = ((errs&7)<<1) | ((k_testnumber&15)<<4) | (errs ? 0x08 : 0); + bringup_set_led_bits(leds, 0xfe); +} + +static void +setup_block_addresses(void) +{ + int i, stride, memmapi; + + stride = LINESTRIDE; + memmapi = 0; + for (i=0; i= memmap[memmapi].vend) { + memmap[memmapi].wrapcount++; + memmap[memmapi].nextaddr = memmap[memmapi].vstart + + memmap[memmapi].wrapcount * sizeof(dataline_t); + } + + memset((void*)blocks[i], 0, sizeof(dataline_t)); + + if (stride > 16384) { + memmapi++; + if (memmapi == memmapx) + memmapi = 0; + } + } + +} + +static void +set_thread_state(int cpuid, int state) +{ + if (k_threadprivate[cpuid]->threadstate == TS_KILLED) { + bringup_set_led_bits(0xfe, 0xfe); + while(1); + } + k_threadprivate[cpuid]->threadstate = state; +} + +static int +build_mem_map(unsigned long start, unsigned long end, void *arg) +{ + /* + * HACK - skip the kernel on the first node + */ + if (memmapx == 0) + start += 16*MB; + + memmap[memmapx].vstart = start; + memmap[memmapx].vend = end; + memmapx++; + return 0; +} + +void int_test(void); + +int +llsc_main (int cpuid, long mbasex) +{ + int i, cpu, is_master, repeatcnt=0; + unsigned int preverr=0, errs=0, pass=0; + int automode=0; + +#ifdef INTTEST + if (inttest) + int_test(); +#endif + + if (!autotest_enabled) + return 0; + +#ifdef CONFIG_SMP + is_master = !smp_processor_id(); +#else + is_master = 1; +#endif + + + if (is_master) { + print_params(); + if(!IS_RUNNING_ON_SIMULATOR()) + spin(10); + mbase = (control_t*)mbasex; + k_currentpass = 0; + k_go = ST_IDLE; + k_passes = DEF_PASSES; + k_napticks = DEF_NAPTICKS; + k_stop_on_error = DEF_STOP_ON_ERROR; + k_verbose = DEF_VERBOSE; + k_linecount = DEF_LINECOUNT; + k_iter_msg = DEF_ITER_MSG; + k_vv = DEF_VV; + k_linepad = DEF_LINEPAD; + k_blocks = (void*)blocks; + efi_memmap_walk(build_mem_map, 0); + +#ifdef CONFIG_IA64_SGI_AUTOTEST + automode = 1; +#endif + + for (i=0; i 5) { + set_autotest_params(); + repeatcnt = 0; + } + } else { + while (k_go == ST_IDLE); + } + + k_go = ST_INIT; + if (k_linecount > MAX_LINECOUNT) k_linecount = MAX_LINECOUNT; + k_linecount = k_linecount & ~1; + setup_block_addresses(); + + k_currentpass = pass++; + k_go = ST_RUN; + if (fail_enabled) + fail_enabled--; + + } else { + while (k_go != ST_RUN || k_currentpass != pass); + pass++; + } + + + set_leds(errs); + set_thread_state(cpuid, TS_RUNNING); + + errs += ran_conf_llsc(cpuid); + preverr = (k_go == ST_ERRSTOP); + + set_leds(errs); + set_thread_state(cpuid, TS_STOPPED); + + if (is_master) { + Speedo(); + for (i=0, cpu=0; cputhreadstate == TS_RUNNING) { + i++; + if (i == 10000) { + k_go = ST_STOP; + printk (" llsc master stopping test number %ld\n", k_testnumber); + } + if (i > 100000) { + k_threadprivate[cpu]->threadstate = TS_KILLED; + printk (" llsc: master killing cpuid %d, running test number %ld\n", + cpu, k_testnumber); + } + udelay(1000); + } + } + } + + goto loop; +} + + +static void +Speedo(void) +{ + static int i = 0; + + switch (++i%4) { + case 0: + printk("|\b"); + break; + case 1: + printk("\\\b"); + break; + case 2: + printk("-\b"); + break; + case 3: + printk("/\b"); + break; + } +} + +#ifdef INTTEST + +/* ======================================================================================================== + * + * Some test code to verify that interrupts work + * + * Add the following to the arch/ia64/kernel/smp.c after the comment "Reschedule callback" + * if (zzzprint_resched) printk(" cpu %d got interrupt\n", smp_processor_id()); + * + * Enable the code in arch/ia64/sn/sn1/smp.c to print sending IPIs. + * + */ + +static int __init set_inttest(char *str) +{ + inttest = 1; + autotest_enabled = 1; + + return 1; +} + +__setup("inttest=", set_inttest); + +int zzzprint_resched=0; + +void +int_test() { + int mycpu, cpu; + static volatile int control_cpu=0; + + mycpu = smp_processor_id(); + zzzprint_resched = 2; + + printk("Testing cross interrupts\n"); + + while (control_cpu != smp_num_cpus) { + if (mycpu == cpu_logical_map(control_cpu)) { + for (cpu=0; cpulock[(i)] +#define LOCK(i) set_lock(LOCKADDR(i), lockpat) +#define UNLOCK(i) clr_lock(LOCKADDR(i), lockpat) +#define GETLOCK(i) *LOCKADDR(i) +#define ZEROLOCK(i) zero_lock(LOCKADDR(i)) + +#define CACHEALIGN(a) ((void*)((long)(a) & ~127L)) + +typedef uint lock_t; +typedef uint share_t; +typedef uint private_t; + +typedef struct { + lock_t lock[2]; + share_t share[2]; + private_t private[MAXCPUS]; + share_t share0; + share_t share1; +} dataline_t ; + + +#define LINEPAD k_linepad +#define LINESTRIDE (((sizeof(dataline_t)+CACHELINE-1)/CACHELINE)*CACHELINE + LINEPAD) + + +typedef struct { + vint threadstate; + uint threadpasses; + private_t private[MAX_LINECOUNT]; +} threadprivate_t; + +typedef struct { + vlong sk_go; /* 0=idle, 1=init, 2=run */ + long sk_linecount; + long sk_passes; + long sk_napticks; + long sk_stop_on_error; + long sk_verbose; + long sk_iter_msg; + long sk_vv; + long sk_linepad; + long sk_options; + long sk_testnumber; + vlong sk_currentpass; + void *sk_blocks; + threadprivate_t *sk_threadprivate[MAXCPUS]; +} control_t; + +/* Run state (k_go) constants */ +#define ST_IDLE 0 +#define ST_INIT 1 +#define ST_RUN 2 +#define ST_STOP 3 +#define ST_ERRSTOP 4 + + +/* Threadstate constants */ +#define TS_STOPPED 0 +#define TS_RUNNING 1 +#define TS_KILLED 2 + + + +int llsc_main (int cpuid, long mbasex); + diff -urN linux-2.4.0-test10/arch/ia64/sn/sn1/machvec.c linux-2.4.0-test10-lia/arch/ia64/sn/sn1/machvec.c --- linux-2.4.0-test10/arch/ia64/sn/sn1/machvec.c Fri Aug 11 19:09:06 2000 +++ linux-2.4.0-test10-lia/arch/ia64/sn/sn1/machvec.c Wed Nov 15 19:11:39 2000 @@ -1,2 +1,18 @@ #define MACHVEC_PLATFORM_NAME sn1 #include +#include +#include +void* +sn1_mk_io_addr_MACRO + +dma_addr_t +sn1_pci_map_single_MACRO + +int +sn1_pci_map_sg_MACRO + +unsigned long +sn1_virt_to_phys_MACRO + +void * +sn1_phys_to_virt_MACRO diff -urN linux-2.4.0-test10/arch/ia64/sn/sn1/mm.c linux-2.4.0-test10-lia/arch/ia64/sn/sn1/mm.c --- linux-2.4.0-test10/arch/ia64/sn/sn1/mm.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/sn1/mm.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,244 @@ +/* + * Copyright, 2000, Silicon Graphics. + * Copyright Srinivasa Thirumalachar (sprasad@engr.sgi.com) + * Copyright 2000 Kanoj Sarcar (kanoj@sgi.com) + */ + +#include +#include +#include +#include +#include + +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +# define MAX(a,b) ((a) > (b) ? (a) : (b)) + +extern int setup_node_bootmem(unsigned long,unsigned long,void *); + +struct nodemem_s { + u64 start ; + u64 end ; + u64 hole[SN1_MAX_BANK_PER_NODE] ; +} nodemem[MAXNODES] ; +static int nodemem_valid = 0; + +static int __init +free_unused_memmap_hole(int nid, unsigned long start, unsigned long end) +{ + struct page * page, *pageend; + unsigned long count = 0; + + printk("free hole : hstart=0x%lx, hend=0x%lx\n", (u64)start, (u64)end) ; + + if (start >= end) + return 0 ; + + /* + * Get the memmap ptrs to the start and end of the holes. + * virt_to_page(start) will panic, if start is in hole. + * Can we do virt_to_page(end), if end is on the next node? + */ + + page = virt_to_page(start-1); + page++ ; + pageend = virt_to_page(end) ; + + printk("hpage=0x%lx, hpageend=0x%lx\n", (u64)page, (u64)pageend) ; + free_bootmem_node(nid, __pa(page), (u64)pageend - (u64)page); + + return count ; +} + +void +free_unused_memmap_node(int nid) +{ + u64 i = 0 ; + u64 holestart = -1 ; + + do { + holestart = nodemem[nid].hole[i] ; + i++ ; + while ((i < SN1_MAX_BANK_PER_NODE) && + (nodemem[nid].hole[i] == (u64)-1)) + i++ ; + if (i < SN1_MAX_BANK_PER_NODE) + free_unused_memmap_hole(nid, holestart, + nodemem[nid].start + (i<> PAGE_SHIFT; + + bank0size = nodemem[nid].hole[0] - nodemem[nid].start ; + /* If nid == master node && no kernel text replication */ + bank0size -= 0xA00000 ; /* Kernel text + stuff */ + bank0size -= ((numpfn + 7) >> 3); + + if ((numpfn * sizeof(mem_map_t)) > bank0size) { + printk("nid = %d, ns=0x%lx, npfn=0x%lx, bank0size=0x%lx\n", + nid, nodesize, numpfn, bank0size) ; + return 0 ; + } + + return 1 ; +} + +static void __init +check_pgtbl_size(int nid) +{ + int bank = SN1_MAX_BANK_PER_NODE - 1 ; + + /* Find highest bank with valid memory */ + while ((nodemem[nid].hole[bank] == -1) && (bank)) + bank-- ; + + while (!pgtbl_size_ok(nid)) { + /* Remove that bank of memory */ + /* Collect some numbers later */ + printk("Ignoring node %d bank %d\n", nid, bank) ; + nodemem[nid].hole[bank--] = -1 ; + /* Get to the next populated bank */ + while ((nodemem[nid].hole[bank] == -1) && (bank)) + bank-- ; + printk("Using only upto bank %d on node %d\n", bank,nid) ; + nodemem[nid].end = nodemem[nid].hole[bank] ; + if (!bank) break ; + } +} + +void dump_nodemem_map(int) ; + +#ifdef CONFIG_DISCONTIGMEM +void +setup_sn1_bootmem(int maxnodes) +{ + int i; + + for (i=0;i \n") ; + for (j=0;j #include #include +#include +#include #include #include #include #include - /* * The format of "screen_info" is strange, and due to early i386-setup * code. This is just enough to make the console code think we're on a @@ -53,26 +54,41 @@ return MAP_NR_SN1(addr); } -void +void __init sn1_setup(char **cmdline_p) { - + extern void init_sn1_smp_config(void); ROOT_DEV = to_kdev_t(0x0301); /* default to first IDE drive */ + init_sn1_smp_config(); +#ifdef ZZZ #if !defined (CONFIG_IA64_SOFTSDV_HACKS) - /* - * Program the timer to deliver timer ticks. 0x40 is the I/O port - * address of PIT counter 0, 0x43 is the I/O port address of the - * PIT control word. - */ - request_region(0x40,0x20,"timer"); - outb(0x34, 0x43); /* Control word */ - outb(LATCH & 0xff , 0x40); /* LSB */ - outb(LATCH >> 8, 0x40); /* MSB */ - printk("PIT: LATCH at 0x%x%x for %d HZ\n", LATCH >> 8, LATCH & 0xff, HZ); + /* + * Program the timer to deliver timer ticks. 0x40 is the I/O port + * address of PIT counter 0, 0x43 is the I/O port address of the + * PIT control word. + */ + request_region(0x40,0x20,"timer"); + outb(0x34, 0x43); /* Control word */ + outb(LATCH & 0xff , 0x40); /* LSB */ + outb(LATCH >> 8, 0x40); /* MSB */ + printk("PIT: LATCH at 0x%x%x for %d HZ\n", LATCH >> 8, LATCH & 0xff, HZ); +#endif #endif #ifdef CONFIG_SMP init_smp_config(); #endif screen_info = sn1_screen_info; +} + +int +IS_RUNNING_ON_SIMULATOR(void) +{ +#ifdef CONFIG_IA64_SGI_SN1_SIM + long sn; + asm("mov %0=cpuid[%1]" : "=r"(sn) : "r"(2)); + return(sn == SNMAGIC); +#else + return(0); +#endif } diff -urN linux-2.4.0-test10/arch/ia64/sn/sn1/smp.c linux-2.4.0-test10-lia/arch/ia64/sn/sn1/smp.c --- linux-2.4.0-test10/arch/ia64/sn/sn1/smp.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/sn1/smp.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,186 @@ +/* + * SN1 Platform specific SMP Support + * + * Copyright (C) 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 Jack Steiner + */ + + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + + + +/* + * The following structure is used to pass params thru smp_call_function + * to other cpus for flushing TLB ranges. + */ +typedef struct { + unsigned long start; + unsigned long end; + unsigned long nbits; +} ptc_params_t; + + +/* + * The following table/struct is for remembering PTC coherency domains. It + * is also used to translate sapicid into cpuids. We dont want to start + * cpus unless we know their cache domain. + */ +#ifdef PTC_NOTYET +sn_sapicid_info_t sn_sapicid_info[NR_CPUS]; +#endif + + + +#ifdef PTC_NOTYET +/* + * NOTE: This is probably not good enough, but I dont want to try to make + * it better until I get some statistics on a running system. + * At a minimum, we should only send IPIs to 1 processor in each TLB domain + * & have it issue a ptc.g on it's own FSB. Also, serialize per FSB, not + * globally. + * + * More likely, we will have to do some work to reduce the frequency of calls to + * this routine. + */ + +static void +sn1_ptc_local(void *arg) +{ + ptc_params_t *params = arg; + unsigned long start, end, nbits; + + start = params->start; + end = params->end; + nbits = params->nbits; + + do { + __asm__ __volatile__ ("ptc.l %0,%1" :: "r"(start), "r"(nbits<<2) : "memory"); + start += (1UL << nbits); + } while (start < end); +} + + +void +sn1_ptc_global (unsigned long start, unsigned long end, unsigned long nbits) +{ + ptc_params_t params; + + params.start = start; + params.end = end; + params.nbits = nbits; + + if (smp_call_function(sn1_ptc_local, ¶ms, 1, 0) != 0) + panic("Unable to do ptc_global - timed out"); + + sn1_ptc_local(¶ms); +} +#endif + + + + +void +sn1_send_IPI(int cpuid, int vector, int delivery_mode, int redirect) +{ + long *p, nasid, slice; + static int off[4] = {0x1800080, 0x1800088, 0x1a00080, 0x1a00088}; + + /* + * ZZZ - Replace with standard macros when available. + */ + nasid = cpuid_to_nasid(cpuid); + slice = cpuid_to_slice(cpuid); + p = (long*)(0xc0000a0000000000LL | (nasid<<33) | off[slice]); + +#if defined(ZZZBRINGUP) + { + static int count=0; + if (count++ < 10) printk("ZZ sendIPI 0x%x->0x%x, vec %d, nasid 0x%lx, slice %ld, adr 0x%lx\n", + smp_processor_id(), cpuid, vector, nasid, slice, (long)p); + } +#endif + mb(); + *p = (delivery_mode << 8) | (vector & 0xff); + +} + + +#ifdef CONFIG_SMP + +static void __init +process_sal_ptc_domain_info(ia64_sal_ptc_domain_info_t *di, int domain) +{ +#ifdef PTC_NOTYET + ia64_sal_ptc_domain_proc_entry_t *pe; + int i, sapicid, cpuid; + + pe = __va(di->proc_list); + for (i=0; iproc_count; i++, pe++) { + sapicid = id_eid_to_sapicid(pe->id, pe->eid); + cpuid = cpu_logical_id(sapicid); + sn_sapicid_info[cpuid].domain = domain; + sn_sapicid_info[cpuid].sapicid = sapicid; + } +#endif +} + + +static void __init +process_sal_desc_ptc(ia64_sal_desc_ptc_t *ptc) +{ + ia64_sal_ptc_domain_info_t *di; + int i; + + di = __va(ptc->domain_info); + for (i=0; inum_domains; i++, di++) { + process_sal_ptc_domain_info(di, i); + } +} + + +void __init +init_sn1_smp_config(void) +{ + + if (!ia64_ptc_domain_info) { + printk("SMP: Can't find PTC domain info. Forcing UP mode\n"); + smp_num_cpus = 1; + return; + } + +#ifdef PTC_NOTYET + memset (sn_sapicid_info, -1, sizeof(sn_sapicid_info)); + process_sal_desc_ptc(ia64_ptc_domain_info); +#endif + +} + +#else /* CONFIG_SMP */ + +void __init +init_sn1_smp_config(void) +{ + +#ifdef PTC_NOTYET + sn_sapicid_info[0].sapicid = hard_processor_sapicid(); +#endif +} + +#endif /* CONFIG_SMP */ diff -urN linux-2.4.0-test10/arch/ia64/sn/sn1/sn1_asm.S linux-2.4.0-test10-lia/arch/ia64/sn/sn1/sn1_asm.S --- linux-2.4.0-test10/arch/ia64/sn/sn1/sn1_asm.S Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/sn1/sn1_asm.S Wed Nov 15 19:11:39 2000 @@ -0,0 +1,27 @@ + +/* + * Copyright (C) 2000 Silicon Graphics + * Copyright (C) 2000 Jack Steiner (steiner@sgi.com) + */ + +#include + +#ifdef CONFIG_IA64_SGI_SYNERGY_1_0_HACKS +// Code to work around a SYNERGY 1.0 bug. + + .align 16 + .global enable_fsb_hack + .proc enable_fsb_hack +enable_fsb_hack: + movl r16=0xe000000000000000 + movl r17=0x4ffffffff0000000 /* only trap 0-256MB: covered by DTR0 */ + mov r20=0 + mov r21=1 + ;; + mov dbr[r20]=r16 + mov dbr[r21]=r17 + ;; + srlz.d + br.ret.sptk.few rp + .endp enable_fsb_hack +#endif /* CONFIG_IA64_SGI_SYNERGY_1_0_HACKS */ diff -urN linux-2.4.0-test10/arch/ia64/sn/sn1/synergy.c linux-2.4.0-test10-lia/arch/ia64/sn/sn1/synergy.c --- linux-2.4.0-test10/arch/ia64/sn/sn1/synergy.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/sn1/synergy.c Wed Nov 15 19:11:39 2000 @@ -0,0 +1,203 @@ + +/* + * SN1 Platform specific synergy Support + * + * Copyright (C) 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 Alan Mayer (ajm@sgi.com) + */ + + + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +int bit_pos_to_irq(int bit); +void setclear_mask_b(int irq, int cpuid, int set); +void setclear_mask_a(int irq, int cpuid, int set); +void * kmalloc(size_t size, int flags); + +extern struct sn1_cnode_action_list *sn1_node_actions[]; + + +void +synergy_intr_alloc(int bit, int cpuid) { + return; +} + +int +synergy_intr_connect(int bit, + int cpuid) +{ + int irq; + unsigned is_b; + + irq = bit_pos_to_irq(bit); + + /* always send the interrupt to cpu A (from the synergy */ + /* point of view). */ + is_b = (cpuid_to_slice(cpuid) & 1); + if (is_b) { + setclear_mask_b(irq,cpuid,1); + setclear_mask_a(irq,cpuid, 0); + } else { + setclear_mask_a(irq, cpuid, 1); + setclear_mask_b(irq, cpuid, 0); + } + return 0; +} +void +setclear_mask_a(int irq, int cpuid, int set) +{ + int synergy; + int nasid; + int reg_num; + unsigned long mask; + unsigned long addr; + unsigned long reg; + unsigned long val; + int my_cnode, my_synergy; + int target_cnode, target_synergy; + + /* + * Perform some idiot checks .. + */ + if ( (irq < 0) || (irq > 255) || + (cpuid < 0) || (cpuid > 512) ) { + printk("clear_mask_a: Invalid parameter irq %d cpuid %d\n", irq, cpuid); + return; + } + + target_cnode = cpuid_to_cnodeid(cpuid); + target_synergy = cpuid_to_synergy(cpuid); + my_cnode = cpuid_to_cnodeid(smp_processor_id()); + my_synergy = cpuid_to_synergy(smp_processor_id()); + + reg_num = irq / 64; + mask = 1; + mask <<= (irq % 64); + switch (reg_num) { + case 0: + reg = VEC_MASK0A; + addr = VEC_MASK0A_ADDR; + break; + case 1: + reg = VEC_MASK1A; + addr = VEC_MASK1A_ADDR; + break; + case 2: + reg = VEC_MASK2A; + addr = VEC_MASK2A_ADDR; + break; + case 3: + reg = VEC_MASK3A; + addr = VEC_MASK3A_ADDR; + break; + default: + reg = addr = 0; + break; + } + if (my_cnode == target_cnode && my_synergy == target_synergy) { + // local synergy + val = READ_LOCAL_SYNERGY_REG(addr); + if (set) { + val |= mask; + } else { + val &= ~mask; + } + WRITE_LOCAL_SYNERGY_REG(addr, val); + } else { /* remote synergy */ + synergy = cpuid_to_synergy(cpuid); + nasid = cpuid_to_nasid(cpuid); + val = REMOTE_SSPEC_L(nasid, synergy, reg); + if (set) { + val |= mask; + } else { + val &= ~mask; + } + REMOTE_SSPEC_S(nasid, synergy, reg, val); + } +} + +void +setclear_mask_b(int irq, int cpuid, int set) +{ + int synergy; + int nasid; + int reg_num; + unsigned long mask; + unsigned long addr; + unsigned long reg; + unsigned long val; + int my_cnode, my_synergy; + int target_cnode, target_synergy; + + /* + * Perform some idiot checks .. + */ + if ( (irq < 0) || (irq > 255) || + (cpuid < 0) || (cpuid > 512) ) { + printk("clear_mask_b: Invalid parameter irq %d cpuid %d\n", irq, cpuid); + return; + } + + target_cnode = cpuid_to_cnodeid(cpuid); + target_synergy = cpuid_to_synergy(cpuid); + my_cnode = cpuid_to_cnodeid(smp_processor_id()); + my_synergy = cpuid_to_synergy(smp_processor_id()); + + reg_num = irq / 64; + mask = 1; + mask <<= (irq % 64); + switch (reg_num) { + case 0: + reg = VEC_MASK0B; + addr = VEC_MASK0B_ADDR; + break; + case 1: + reg = VEC_MASK1B; + addr = VEC_MASK1B_ADDR; + break; + case 2: + reg = VEC_MASK2B; + addr = VEC_MASK2B_ADDR; + break; + case 3: + reg = VEC_MASK3B; + addr = VEC_MASK3B_ADDR; + break; + default: + reg = addr = 0; + break; + } + if (my_cnode == target_cnode && my_synergy == target_synergy) { + // local synergy + val = READ_LOCAL_SYNERGY_REG(addr); + if (set) { + val |= mask; + } else { + val &= ~mask; + } + WRITE_LOCAL_SYNERGY_REG(addr, val); + } else { /* remote synergy */ + synergy = cpuid_to_synergy(cpuid); + nasid = cpuid_to_nasid(cpuid); + val = REMOTE_SSPEC_L(nasid, synergy, reg); + if (set) { + val |= mask; + } else { + val &= ~mask; + } + REMOTE_SSPEC_S(nasid, synergy, reg, val); + } +} diff -urN linux-2.4.0-test10/arch/ia64/sn/tools/make_textsym linux-2.4.0-test10-lia/arch/ia64/sn/tools/make_textsym --- linux-2.4.0-test10/arch/ia64/sn/tools/make_textsym Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/arch/ia64/sn/tools/make_textsym Wed Nov 15 19:11:39 2000 @@ -0,0 +1,138 @@ +#!/bin/sh +# Build a textsym file for use in the Arium ITP probe. + +help() { +cat < []] + If no input file is specified, it defaults to vmlinux. + If no output file name is specified, it defaults to "textsym". +END +exit 1 +} + +err () { + echo "ERROR - $*" >&2 + exit 1 +} + + +OPTS="H" +while getopts "$OPTS" c ; do + case $c in + H) help;; + \?) help;; + esac + +done +shift `expr $OPTIND - 1` + +LINUX=${1:-vmlinux} +TEXTSYM=${2:-${LINUX}.sym} + +[ -f $VMLINUX ] || help + + +# pipe everything thru sort +echo "TEXTSYM V1.0" +(cat <&2 +echo " $LINUX --> $TEXTSYM" >&2 +echo " Found $N symbols" >&2 diff -urN linux-2.4.0-test10/arch/ia64/tools/print_offsets.c linux-2.4.0-test10-lia/arch/ia64/tools/print_offsets.c --- linux-2.4.0-test10/arch/ia64/tools/print_offsets.c Fri Jul 14 16:08:12 2000 +++ linux-2.4.0-test10-lia/arch/ia64/tools/print_offsets.c Wed Nov 15 18:10:14 2000 @@ -149,7 +149,7 @@ { "IA64_SWITCH_STACK_AR_UNAT_OFFSET", offsetof (struct switch_stack, ar_unat) }, { "IA64_SWITCH_STACK_AR_RNAT_OFFSET", offsetof (struct switch_stack, ar_rnat) }, { "IA64_SWITCH_STACK_AR_BSPSTORE_OFFSET", offsetof (struct switch_stack, ar_bspstore) }, - { "IA64_SWITCH_STACK_PR_OFFSET", offsetof (struct switch_stack, b0) }, + { "IA64_SWITCH_STACK_PR_OFFSET", offsetof (struct switch_stack, pr) }, { "IA64_SIGCONTEXT_AR_BSP_OFFSET", offsetof (struct sigcontext, sc_ar_bsp) }, { "IA64_SIGCONTEXT_AR_RNAT_OFFSET", offsetof (struct sigcontext, sc_ar_rnat) }, { "IA64_SIGCONTEXT_FLAGS_OFFSET", offsetof (struct sigcontext, sc_flags) }, diff -urN linux-2.4.0-test10/drivers/acpi/Makefile linux-2.4.0-test10-lia/drivers/acpi/Makefile --- linux-2.4.0-test10/drivers/acpi/Makefile Fri Sep 15 18:21:43 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/Makefile Wed Sep 27 16:37:59 2000 @@ -2,7 +2,7 @@ # Makefile for the Linux ACPI interpreter # -SUB_DIRS := +SUB_DIRS := MOD_SUB_DIRS := $(SUB_DIRS) MOD_IN_SUB_DIRS := ALL_SUB_DIRS := $(SUB_DIRS) @@ -12,7 +12,8 @@ M_OBJS := export ACPI_CFLAGS -ACPI_CFLAGS := -D_LINUX +#ACPI_CFLAGS := -D_LINUX -DCONFIG_ACPI_KERNEL_CONFIG_CBN_FIX -DCONFIG_ACPI_KERNEL_CONFIG_ONLY -DCONFIG_ACPI_KERNEL_CONFIG_DEBUG -DCONFIG_ACPI_KERNEL_CONFIG_BM_PROFILE +ACPI_CFLAGS := -D_LINUX -DCONFIG_ACPI_KERNEL_CONFIG_CBN_FIX -DCONFIG_ACPI_KERNEL_CONFIG_ONLY EXTRA_CFLAGS += -I./include @@ -20,12 +21,16 @@ # if the interpreter is used, it overrides arch/i386/kernel/acpi.c ifeq ($(CONFIG_ACPI_INTERPRETER),y) - SUB_DIRS += common dispatcher events hardware\ interpreter namespace parser resources tables - ACPI_OBJS := $(patsubst %,%.o,$(SUB_DIRS)) - ACPI_OBJS += $(patsubst %.c,%.o,$(wildcard *.c)) +# ACPI_OBJS += $(patsubst %.c,%.o,$(wildcard *.c)) + +ifdef CONFIG_ACPI_KERNEL_CONFIG + ACPI_OBJS += acpiconf.o osconf.o os.o +else + ACPI_OBJS += driver.o ec.o cpu.o os.o sys.o table.o +endif O_OBJS += $(ACPI_OBJS) endif diff -urN linux-2.4.0-test10/drivers/acpi/acpiconf.c linux-2.4.0-test10-lia/drivers/acpi/acpiconf.c --- linux-2.4.0-test10/drivers/acpi/acpiconf.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/drivers/acpi/acpiconf.c Thu Oct 26 18:04:05 2000 @@ -0,0 +1,398 @@ +/* + * acpiconf.c - ACPI based kernel configuration + * + * Copyright (C) 2000 Intel Corp. + * Copyright (C) 2000 J.I. Lee + * + * revision history: + * 9/15/2000 J.I. + * Major revision: for new ACPI initialization requirements + * for ACPI CA label 915 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include "acpi.h" +#include "osconf.h" +#include "acpiconf.h" + + +static int acpi_cf_initialized __initdata = 0; + +ACPI_STATUS __init +acpi_cf_init ( + void * rsdp + ) +{ + ACPI_STATUS status; + ACPI_INIT_DATA acpi_init_data; + + acpi_os_bind_osd(ACPI_CF_PHASE_BOOTTIME); + + acpi_init_data.RSDP_physical_address = rsdp; + status = acpi_initialize_subsystem (&acpi_init_data); + if (ACPI_FAILURE(status)) { + printk ("Acpi cfg:initialize_subsystem error=0x%x\n", status); + return status; + } + dprintk(("Acpi cfg:initializ_subsysteme pass\n")); + + status = acpi_load_firmware_tables (); + if (ACPI_FAILURE(status)) { + printk ("Acpi cfg:load firmware tables error=0x%x\n", status); + acpi_terminate(); + return status; + } + dprintk(("Acpi cfg:load firmware tables pass\n")); + + status = acpi_enable_subsystem (ACPI_FULL_INITIALIZATION); + if (ACPI_FAILURE(status)) { + printk ("Acpi cfg:enable_subsystem error=0x%x\n", status); + acpi_terminate(); + return status; + } + dprintk(("Acpi cfg:enable_subsystem pass\n")); + + acpi_cf_initialized++; + + return AE_OK; +} + + +ACPI_STATUS __init +acpi_cf_terminate ( void ) +{ + ACPI_STATUS status; + + if (! ACPI_CF_INITIALIZED()) + return AE_ERROR; + + status = acpi_disable (); + if (ACPI_FAILURE(status)) { + printk ("Acpi cfg:disable fail=0x%x\n", status); + /* fall thru...*/ + } + + status = acpi_terminate (); + if (ACPI_FAILURE(status)) { + printk ("Acpi cfg:acpi terminate error=0x%x\n", status); + /* fall thru...*/ + } + + acpi_cf_cleanup(); + acpi_os_bind_osd(ACPI_CF_PHASE_RUNTIME); + + acpi_cf_initialized--; + + return status; +} + + +ACPI_STATUS __init +acpi_cf_get_pci_vectors ( + struct pci_vector_struct **vectors, + int *num_pci_vectors + ) +{ + ACPI_STATUS status; + void *prts; + + if (! ACPI_CF_INITIALIZED()) { + status = acpi_cf_init((void *)efi.acpi); + if (ACPI_FAILURE (status)) + return status; + } + + *vectors = NULL; + *num_pci_vectors = 0; + + status = acpi_cf_get_prt (&prts); + if (ACPI_FAILURE (status)) { + printk("Acpi Cfg: get prt fail\n"); + return status; + } + + status = acpi_cf_convert_prt_to_vectors (prts, vectors, num_pci_vectors); +#ifdef CONFIG_ACPI_KERNEL_CONFIG_DEBUG + if (ACPI_SUCCESS(status)) { + acpi_cf_print_pci_vectors (*vectors, *num_pci_vectors); + } +#endif + printk("Acpi Cfg: get PRT %s\n", (ACPI_SUCCESS(status))?"pass":"fail"); + + return status; +} + + +static PCI_ROUTING_TABLE *pci_routing_tables[PCI_MAX_BUS] __initdata = {NULL}; +static struct pci_vector_struct *vectors_to_free __initdata = NULL; + + +static ACPI_STATUS __init +acpi_cf_get_prt ( + void **prts + ) +{ + ACPI_STATUS status; + + status = acpi_walk_namespace ( ACPI_TYPE_DEVICE, + ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, + acpi_cf_get_prt_callback, + NULL, + NULL ); + + if (ACPI_FAILURE(status)) { + printk("Acpi cfg:walk namespace error=0x%x\n", status); + } + + *prts = (void *)pci_routing_tables; + + return status; +} + + +static ACPI_STATUS __init +acpi_cf_get_prt_callback ( + ACPI_HANDLE handle, + UINT32 Level, + void *context, + void **retval + ) +{ + ACPI_BUFFER acpi_buffer; + PCI_ROUTING_TABLE *prt; + NATIVE_UINT busnum = 0; + static NATIVE_UINT next_busnum = 0; + ACPI_STATUS status; + + ACPI_BUFFER ret_buf; + ACPI_OBJECT *ext_obj; + UINT8 buf[PATHNAME_MAX]; + + + acpi_buffer.length = 0; + acpi_buffer.pointer = NULL; + + status = acpi_get_irq_routing_table (handle, &acpi_buffer); + + switch (status) { + case AE_BUFFER_OVERFLOW: + dprintk(("Acpi Cfg: _PRT found. Need %d bytes\n", acpi_buffer.length)); + break; /* found */ + case AE_NOT_FOUND: + return AE_OK; /* let acpi_walk_namespace continue. */ + default: + printk("Acpi cfg:get irq routing table fail=0x%x\n", status); + return AE_ERROR; + } + + prt = (PCI_ROUTING_TABLE *) acpi_os_callocate (acpi_buffer.length); + if (prt == NULL) { + printk("Acpi cfg:callocate %d bytes Fail\n", acpi_buffer.length); + return AE_ERROR; + } + acpi_buffer.pointer = (void *) prt; + + status = acpi_get_irq_routing_table (handle, &acpi_buffer); + if (ACPI_FAILURE(status)) { + printk("Acpi cfg:get irq routing table Fail=0x%x\n", status); + acpi_os_free(prt); + return AE_OK; + } + +#ifdef CONFIG_ACPI_KERNEL_CONFIG_DEBUG + ret_buf.length = PATHNAME_MAX; + ret_buf.pointer = (void *) buf; + + status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf); + if (ACPI_SUCCESS(status)) { + printk("Acpi cfg:path=[%s]\n", (char *)ret_buf.pointer); + } +#endif + + ret_buf.length = PATHNAME_MAX; + ret_buf.pointer = (void *) buf; + + status = acpi_evaluate_object(handle, METHOD_NAME__BBN, NULL, &ret_buf); + if (ACPI_FAILURE(status)) { + if (status == AE_NOT_FOUND) { + printk("Acpi cfg:_BBN not found for _PRT %ld: set busnum to %ld\n", next_busnum, next_busnum); + } else { + printk("Acpi cfg:_BBN fail=0x%x for _PRT %ld: set busnum to %ld\n", status, next_busnum, next_busnum); + } + if (next_busnum) + printk("Acpi cfg: Warning: Invalid or unimplemented _BBNs for PRTs may cause incorrect PCI vector configuration. Check AML\n"); + busnum = next_busnum++; + } else { + ext_obj = (ACPI_OBJECT *) ret_buf.pointer; + + switch (ext_obj->type) { + case ACPI_TYPE_NUMBER: + busnum = (NATIVE_UINT) ext_obj->number.value; + next_busnum = busnum + 1; + dprintk(("Acpi cfg:_BBN busnum is %ld\n ", busnum)); + break; + default: + printk("Acpi cfg:_BBN object type incorrect: set busnum to %ld\n ", next_busnum); + printk("Acpi cfg: Warning: Invalid _BBN for PRT may cause incorrect PCI vector configuration. Check AML\n"); + busnum = next_busnum++; + break; + } + + /* + * Placeholder for PCI SEG when PAL supports it, + * status = acpi_evaluate_object(handle, "_SEG", NULL, &ret_buf); + */ + } + + + ret_buf.length = PATHNAME_MAX; + ret_buf.pointer = (void *) buf; + + status = acpi_evaluate_object(handle, METHOD_NAME__STA, NULL, &ret_buf); + if (ACPI_FAILURE(status)) { + if (status == AE_NOT_FOUND) + dprintk(("Acpi cfg:no _STA: pci bus %ld exist\n", busnum)); + else + printk("Acpi cfg:_STA fail=0x%x: pci bus %ld exist. Check AML\n", status, busnum); + } else { + ext_obj = (ACPI_OBJECT *) ret_buf.pointer; + + switch (ext_obj->type) { + case ACPI_TYPE_NUMBER: + if((NATIVE_UINT) ext_obj->number.value & ACPI_STA_DEVICE_PRESENT) { + dprintk(("Acpi cfg:_STA: pci bus %ld exist\n", busnum)); + } else { + printk("Acpi cfg:_STA: pci bus %ld not exist. Discarding the _PRT\n", busnum); + next_busnum--; + acpi_os_free(prt); + return AE_OK; + } + break; + default: + printk("Acpi cfg:_STA object type incorrect: pci bus %ld exist. Check AML\n", busnum); + break; + } + } + + + acpi_cf_add_to_pci_routing_tables (busnum, prt); + + return AE_OK; +} + + +static void __init +acpi_cf_add_to_pci_routing_tables ( + NATIVE_UINT busnum, + PCI_ROUTING_TABLE *prt + ) +{ + if ( busnum >= PCI_MAX_BUS ) { + printk("Acpi cfg:invalid pci bus number %ld\n", busnum); + acpi_os_free(prt); + return; + } + + if (pci_routing_tables[busnum]) { + printk("Acpi cfg:duplicate PRT for pci bus %ld. overiding...\n", busnum); + acpi_os_free(pci_routing_tables[busnum]); + /* override... */ + } + + pci_routing_tables[busnum] = prt; +} + + +#define DUMPVECTOR(pv) printk("PCI bus=0x%x id=0x%x pin=0x%x irq=0x%x\n", pv->bus, pv->pci_id, pv->pin, pv->irq); + +static ACPI_STATUS __init +acpi_cf_convert_prt_to_vectors ( + void *prts, + struct pci_vector_struct **vectors, + int *num_pci_vectors + ) +{ + struct pci_vector_struct *pvec; + PCI_ROUTING_TABLE **pprts, *prt, *prtf; + int nvec = 0; + int i; + + + pprts = (PCI_ROUTING_TABLE **)prts; + + for ( i = 0; i < PCI_MAX_BUS; i++) { + prt = *pprts++; + if (prt) { + for ( ; prt->length > 0; nvec++) { + prt = (PCI_ROUTING_TABLE *) ((NATIVE_UINT)prt + (NATIVE_UINT)prt->length); + prt = ROUND_PTR_UP_TO_4(prt, PCI_ROUTING_TABLE); + } + } + } + + *num_pci_vectors = nvec; + *vectors = acpi_os_callocate (sizeof(struct pci_vector_struct) * nvec); + if (*vectors == NULL) { + printk("Acpi cfg:callocate error\n"); + return AE_NO_MEMORY; + } + + pvec = *vectors; + pprts = (PCI_ROUTING_TABLE **)prts; + + for ( i = 0; i < PCI_MAX_BUS; i++) { + prt = prtf = *pprts++; + if (prt) { + for ( ; prt->length > 0; pvec++) { + pvec->bus = (UINT16)i; + pvec->pci_id = prt->data.address; + pvec->pin = (UINT8)prt->data.pin; + pvec->irq = (UINT8)prt->data.source_index; + + prt = (PCI_ROUTING_TABLE *) ((NATIVE_UINT)prt + (NATIVE_UINT)prt->length); + prt = ROUND_PTR_UP_TO_4(prt, PCI_ROUTING_TABLE); + } + acpi_os_free((void *)prtf); + } + } + + vectors_to_free = *vectors; + + return AE_OK; +} + + +void __init +acpi_cf_cleanup ( void ) +{ + /* nothing to free, pci_vectors are used by the kernel */ +} + + +#ifdef CONFIG_ACPI_KERNEL_CONFIG_DEBUG +void __init +acpi_cf_print_pci_vectors ( + struct pci_vector_struct *vectors, + int num_pci_vectors + ) +{ + struct pci_vector_struct *pvec; + int i; + + printk("number of PCI interrupt vectors = %d\n", num_pci_vectors); + + pvec = vectors; + for (i = 0; i < num_pci_vectors; i++) { + DUMPVECTOR(pvec); + pvec++; + } +} +#endif diff -urN linux-2.4.0-test10/drivers/acpi/acpiconf.h linux-2.4.0-test10-lia/drivers/acpi/acpiconf.h --- linux-2.4.0-test10/drivers/acpi/acpiconf.h Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/drivers/acpi/acpiconf.h Wed Nov 1 23:44:13 2000 @@ -0,0 +1,59 @@ +/* + * acpiconf.h - ACPI based kernel configuration + * + * Copyright (C) 2000 Intel Corp. + * Copyright (C) 2000 J.I. Lee + */ + +#include + +#define PCI_MAX_BUS 0x100 +#define ACPI_STA_DEVICE_PRESENT 0x01 + +#ifdef CONFIG_ACPI_KERNEL_CONFIG_DEBUG +#define ACPI_CF_INITIALIZED() (acpi_cf_initialized > 0) +#undef dprintk +#define dprintk(a) printk a +#else +#define ACPI_CF_INITIALIZED() 1 +#undef dprintk +#define dprintk(a) +#endif + + +static ACPI_STATUS __init acpi_cf_get_prt (void **prts); + +extern void __init +acpi_os_bind_osd(int acpi_phase); + + +static +ACPI_STATUS __init +acpi_cf_get_prt_callback ( + ACPI_HANDLE handle, + UINT32 level, + void *context, + void **retval + ); + + +static +void __init +acpi_cf_add_to_pci_routing_tables ( + NATIVE_UINT busnum, + PCI_ROUTING_TABLE *prt + ); + + +static +ACPI_STATUS __init +acpi_cf_convert_prt_to_vectors ( + void *prts, + struct pci_vector_struct **vectors, + int *num_pci_vectors + ); + + +void __init +acpi_cf_cleanup ( void ); + diff -urN linux-2.4.0-test10/drivers/acpi/common/cmdelete.c linux-2.4.0-test10-lia/drivers/acpi/common/cmdelete.c --- linux-2.4.0-test10/drivers/acpi/common/cmdelete.c Fri Sep 15 14:30:29 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/common/cmdelete.c Fri Sep 15 16:38:45 2000 @@ -1,9 +1,9 @@ -/****************************************************************************** +/******************************************************************************* * * Module Name: cmdelete - object deletion and reference count utilities - * $Revision: 53 $ + * $Revision: 55 $ * - *****************************************************************************/ + ******************************************************************************/ /* * Copyright (C) 2000 R. Byron Moore @@ -34,7 +34,7 @@ MODULE_NAME ("cmdelete") -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_cm_delete_internal_obj * @@ -120,6 +120,31 @@ break; + case ACPI_TYPE_REGION: + + + if (object->region.extra) { + /* Free the Context block if it exists */ + + /* TBD: [Investigate] what if this is a user-installed context? + * (versus the Pci_context allocated in Acpi_ev_pci_config_region_setup) + */ + obj_pointer = object->region.extra->extra.region_context; + + /* Now we can free the Extra object */ + + acpi_cm_delete_object_desc (object->region.extra); + } + break; + + + case ACPI_TYPE_FIELD_UNIT: + + if (object->field_unit.extra) { + acpi_cm_delete_object_desc (object->field_unit.extra); + } + break; + default: break; } @@ -148,7 +173,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_cm_delete_internal_object_list * @@ -197,7 +222,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_cm_update_ref_count * @@ -287,7 +312,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_cm_update_object_reference * @@ -397,9 +422,8 @@ * these are simply ignored */ - status = - acpi_cm_create_update_state_and_push (object->package.elements[i], - action, &state_list); + status = acpi_cm_create_update_state_and_push ( + object->package.elements[i], action, &state_list); if (ACPI_FAILURE (status)) { return (status); } @@ -409,9 +433,9 @@ case ACPI_TYPE_FIELD_UNIT: - status = - acpi_cm_create_update_state_and_push (object->field_unit.container, - action, &state_list); + status = acpi_cm_create_update_state_and_push ( + object->field_unit.container, action, &state_list); + if (ACPI_FAILURE (status)) { return (status); } @@ -420,9 +444,8 @@ case INTERNAL_TYPE_DEF_FIELD: - status = - acpi_cm_create_update_state_and_push (object->field.container, - action, &state_list); + status = acpi_cm_create_update_state_and_push ( + object->field.container, action, &state_list); if (ACPI_FAILURE (status)) { return (status); } @@ -431,16 +454,14 @@ case INTERNAL_TYPE_BANK_FIELD: - status = - acpi_cm_create_update_state_and_push (object->bank_field.bank_select, - action, &state_list); + status = acpi_cm_create_update_state_and_push ( + object->bank_field.bank_select, action, &state_list); if (ACPI_FAILURE (status)) { return (status); } - status = - acpi_cm_create_update_state_and_push (object->bank_field.container, - action, &state_list); + status = acpi_cm_create_update_state_and_push ( + object->bank_field.container, action, &state_list); if (ACPI_FAILURE (status)) { return (status); } @@ -449,8 +470,6 @@ case ACPI_TYPE_REGION: - acpi_cm_update_ref_count (object->region.method, action); - /* TBD: [Investigate] Acpi_cm_update_ref_count (Object->Region.Addr_handler, Action); */ @@ -490,7 +509,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_cm_add_reference * @@ -528,7 +547,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_cm_remove_reference * @@ -553,6 +572,9 @@ if (!acpi_cm_valid_internal_object (object)) { return; } + + + /* * Decrement the reference count, and only actually delete the object diff -urN linux-2.4.0-test10/drivers/acpi/common/cmglobal.c linux-2.4.0-test10-lia/drivers/acpi/common/cmglobal.c --- linux-2.4.0-test10/drivers/acpi/common/cmglobal.c Fri Sep 15 14:30:29 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/common/cmglobal.c Fri Sep 15 16:38:45 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: cmglobal - Global variables for the ACPI subsystem - * $Revision: 99 $ + * $Revision: 102 $ * *****************************************************************************/ @@ -52,7 +52,7 @@ /* Debug switch - layer (component) mask */ -u32 acpi_dbg_layer = ALL_COMPONENTS; +u32 acpi_dbg_layer = COMPONENT_DEFAULT; u32 acpi_gbl_nesting_level = 0; @@ -144,7 +144,8 @@ NSP_LOCAL, /* 31 Def_any */ NSP_NORMAL, /* 32 Method Arg */ NSP_NORMAL, /* 33 Method Local */ - NSP_NORMAL /* 34 Invalid */ + NSP_NORMAL, /* 34 Extra */ + NSP_NORMAL /* 35 Invalid */ }; @@ -171,7 +172,8 @@ /* RSDT 6 */ {RSDT_SIG, RSDT_SIG, sizeof (RSDT_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, NULL}, /* SSDT 7 */ {SSDT_SIG, SSDT_SIG, sizeof (SSDT_SIG)-1, ACPI_TABLE_MULTIPLE, AE_OK, NULL}, /* SBST 8 */ {SBST_SIG, SBST_SIG, sizeof (SBST_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, (void **) &acpi_gbl_SBST}, - /* BOOT 9 */ {BOOT_SIG, BOOT_SIG, sizeof (BOOT_SIG)-1, ACPI_TABLE_SINGLE, AE_SUPPORT, NULL} + /* SPIC 9 */ {SPIC_SIG, SPIC_SIG, sizeof (SPIC_SIG)-1, ACPI_TABLE_MULTIPLE, AE_OK, NULL}, + /* BOOT 10 */{BOOT_SIG, BOOT_SIG, sizeof (BOOT_SIG)-1, ACPI_TABLE_SINGLE, AE_SUPPORT, NULL} }; ACPI_INIT_DATA acpi_gbl_acpi_init_data; @@ -352,7 +354,7 @@ /* ACPI table structure */ - for (i = 0; i < ACPI_TABLE_MAX; i++) { + for (i = 0; i < NUM_ACPI_TABLES; i++) { acpi_gbl_acpi_tables[i].prev = &acpi_gbl_acpi_tables[i]; acpi_gbl_acpi_tables[i].next = &acpi_gbl_acpi_tables[i]; acpi_gbl_acpi_tables[i].pointer = NULL; @@ -364,7 +366,7 @@ /* Address Space handler array */ - for (i = 0; i < ACPI_MAX_ADDRESS_SPACE; i++) { + for (i = 0; i < ACPI_NUM_ADDRESS_SPACES; i++) { acpi_gbl_address_spaces[i].handler = NULL; acpi_gbl_address_spaces[i].context = NULL; } diff -urN linux-2.4.0-test10/drivers/acpi/common/cminit.c linux-2.4.0-test10-lia/drivers/acpi/common/cminit.c --- linux-2.4.0-test10/drivers/acpi/common/cminit.c Fri Sep 15 14:30:29 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/common/cminit.c Fri Sep 15 16:38:45 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: cminit - Common ACPI subsystem initialization - * $Revision: 79 $ + * $Revision: 81 $ * *****************************************************************************/ @@ -63,207 +63,70 @@ /****************************************************************************** * - * FUNCTION: Acpi_cm_hardware_initialize + * FUNCTION: Acpi_cm_validate_facp * * PARAMETERS: None * - * RETURN: Status + * RETURN: void * - * DESCRIPTION: Initialize and validate various ACPI registers + * DESCRIPTION: Validate various ACPI registers in the FACP * ******************************************************************************/ -ACPI_STATUS -acpi_cm_hardware_initialize (void) +void +acpi_cm_validate_facp ( + void) { - ACPI_STATUS status = AE_OK; - u32 index; - - - /* Are we running on the actual hardware */ - if (!acpi_gbl_acpi_hardware_present) { - /* No, just return */ - - return (AE_OK); + /* + * Verify Fixed ACPI Description Table fields, + * but don't abort on any problems, just display error + */ + + if (acpi_gbl_FACP->pm1_evt_len < 4) { + acpi_cm_facp_register_error ("PM1_EVT_LEN", + (u32) acpi_gbl_FACP->pm1_evt_len); } - /* We must have the ACPI tables by the time we get here */ - - if (!acpi_gbl_FACP) { - acpi_gbl_restore_acpi_chipset = FALSE; - - return (AE_NO_ACPI_TABLES); + if (!acpi_gbl_FACP->pm1_cnt_len) { + acpi_cm_facp_register_error ("PM1_CNT_LEN", + (u32) acpi_gbl_FACP->pm1_cnt_len); } - /* Must support *some* mode! */ -/* - if (!(System_flags & SYS_MODES_MASK)) { - Restore_acpi_chipset = FALSE; - - return (AE_ERROR); + if (!acpi_gbl_FACP->pm1a_evt_blk) { + acpi_cm_facp_register_error ("PM1a_EVT_BLK", acpi_gbl_FACP->pm1a_evt_blk); } -*/ - - - switch (acpi_gbl_system_flags & SYS_MODES_MASK) - { - /* Identify current ACPI/legacy mode */ - - case (SYS_MODE_ACPI): - - acpi_gbl_original_mode = SYS_MODE_ACPI; - break; - - - case (SYS_MODE_LEGACY): - - acpi_gbl_original_mode = SYS_MODE_LEGACY; - break; - + if (!acpi_gbl_FACP->pm1a_cnt_blk) { + acpi_cm_facp_register_error ("PM1a_CNT_BLK", acpi_gbl_FACP->pm1a_cnt_blk); + } - case (SYS_MODE_ACPI | SYS_MODE_LEGACY): + if (!acpi_gbl_FACP->pm_tmr_blk) { + acpi_cm_facp_register_error ("PM_TMR_BLK", acpi_gbl_FACP->pm_tmr_blk); + } - if (acpi_hw_get_mode () == SYS_MODE_ACPI) { - acpi_gbl_original_mode = SYS_MODE_ACPI; - } - else { - acpi_gbl_original_mode = SYS_MODE_LEGACY; - } + if (acpi_gbl_FACP->pm2_cnt_blk && !acpi_gbl_FACP->pm2_cnt_len) { + acpi_cm_facp_register_error ("PM2_CNT_LEN", + (u32) acpi_gbl_FACP->pm2_cnt_len); + } - break; + if (acpi_gbl_FACP->pm_tm_len < 4) { + acpi_cm_facp_register_error ("PM_TM_LEN", + (u32) acpi_gbl_FACP->pm_tm_len); } + /* length of GPE blocks must be a multiple of 2 */ - if (acpi_gbl_system_flags & SYS_MODE_ACPI) { - /* Target system supports ACPI mode */ - /* - * The purpose of this block of code is to save the initial state - * of the ACPI event enable registers. An exit function will be - * registered which will restore this state when the application - * exits. The exit function will also clear all of the ACPI event - * status bits prior to restoring the original mode. - * - * The location of the PM1a_evt_blk enable registers is defined as the - * base of PM1a_evt_blk + PM1a_evt_blk_length / 2. Since the spec further - * fully defines the PM1a_evt_blk to be a total of 4 bytes, the offset - * for the enable registers is always 2 from the base. It is hard - * coded here. If this changes in the spec, this code will need to - * be modified. The PM1b_evt_blk behaves as expected. - */ - - acpi_gbl_pm1_enable_register_save = - acpi_os_in16 ((acpi_gbl_FACP->pm1a_evt_blk + 2)); - if (acpi_gbl_FACP->pm1b_evt_blk) { - acpi_gbl_pm1_enable_register_save |= - acpi_os_in16 ((acpi_gbl_FACP->pm1b_evt_blk + 2)); - } - - - /* - * The GPEs behave similarly, except that the length of the register - * block is not fixed, so the buffer must be allocated with malloc - */ - - if (acpi_gbl_FACP->gpe0blk && acpi_gbl_FACP->gpe0blk_len) { - /* GPE0 specified in FACP */ - - acpi_gbl_gpe0enable_register_save = - acpi_cm_allocate (DIV_2 (acpi_gbl_FACP->gpe0blk_len)); - if (!acpi_gbl_gpe0enable_register_save) { - return (AE_NO_MEMORY); - } - - /* Save state of GPE0 enable bits */ - - for (index = 0; index < DIV_2 (acpi_gbl_FACP->gpe0blk_len); index++) { - acpi_gbl_gpe0enable_register_save[index] = - acpi_os_in8 (acpi_gbl_FACP->gpe0blk + - DIV_2 (acpi_gbl_FACP->gpe0blk_len)); - } - } - - else { - acpi_gbl_gpe0enable_register_save = NULL; - } - - if (acpi_gbl_FACP->gpe1_blk && acpi_gbl_FACP->gpe1_blk_len) { - /* GPE1 defined */ - - acpi_gbl_gpe1_enable_register_save = - acpi_cm_allocate (DIV_2 (acpi_gbl_FACP->gpe1_blk_len)); - if (!acpi_gbl_gpe1_enable_register_save) { - return (AE_NO_MEMORY); - } - - /* save state of GPE1 enable bits */ - - for (index = 0; index < DIV_2 (acpi_gbl_FACP->gpe1_blk_len); index++) { - acpi_gbl_gpe1_enable_register_save[index] = - acpi_os_in8 (acpi_gbl_FACP->gpe1_blk + - DIV_2 (acpi_gbl_FACP->gpe1_blk_len)); - } - } - - else { - acpi_gbl_gpe1_enable_register_save = NULL; - } - - - /* - * Verify Fixed ACPI Description Table fields, - * but don't abort on any problems, just display error - */ - - if (acpi_gbl_FACP->pm1_evt_len < 4) { - acpi_cm_facp_register_error ("PM1_EVT_LEN", - (u32) acpi_gbl_FACP->pm1_evt_len); - } - - if (!acpi_gbl_FACP->pm1_cnt_len) { - acpi_cm_facp_register_error ("PM1_CNT_LEN", - (u32) acpi_gbl_FACP->pm1_cnt_len); - } - - if (!acpi_gbl_FACP->pm1a_evt_blk) { - acpi_cm_facp_register_error ("PM1a_EVT_BLK", acpi_gbl_FACP->pm1a_evt_blk); - } - - if (!acpi_gbl_FACP->pm1a_cnt_blk) { - acpi_cm_facp_register_error ("PM1a_CNT_BLK", acpi_gbl_FACP->pm1a_cnt_blk); - } - - if (!acpi_gbl_FACP->pm_tmr_blk) { - acpi_cm_facp_register_error ("PM_TMR_BLK", acpi_gbl_FACP->pm_tmr_blk); - } - - if (acpi_gbl_FACP->pm2_cnt_blk && !acpi_gbl_FACP->pm2_cnt_len) { - acpi_cm_facp_register_error ("PM2_CNT_LEN", - (u32) acpi_gbl_FACP->pm2_cnt_len); - } - - if (acpi_gbl_FACP->pm_tm_len < 4) { - acpi_cm_facp_register_error ("PM_TM_LEN", - (u32) acpi_gbl_FACP->pm_tm_len); - } - - /* length not multiple of 2 */ - if (acpi_gbl_FACP->gpe0blk && (acpi_gbl_FACP->gpe0blk_len & 1)) { - acpi_cm_facp_register_error ("GPE0_BLK_LEN", - (u32) acpi_gbl_FACP->gpe0blk_len); - } - - /* length not multiple of 2 */ - if (acpi_gbl_FACP->gpe1_blk && (acpi_gbl_FACP->gpe1_blk_len & 1)) { - acpi_cm_facp_register_error ("GPE1_BLK_LEN", - (u32) acpi_gbl_FACP->gpe1_blk_len); - } + if (acpi_gbl_FACP->gpe0blk && (acpi_gbl_FACP->gpe0blk_len & 1)) { + acpi_cm_facp_register_error ("GPE0_BLK_LEN", + (u32) acpi_gbl_FACP->gpe0blk_len); } - - return (status); + if (acpi_gbl_FACP->gpe1_blk && (acpi_gbl_FACP->gpe1_blk_len & 1)) { + acpi_cm_facp_register_error ("GPE1_BLK_LEN", + (u32) acpi_gbl_FACP->gpe1_blk_len); + } } diff -urN linux-2.4.0-test10/drivers/acpi/common/cmxface.c linux-2.4.0-test10-lia/drivers/acpi/common/cmxface.c --- linux-2.4.0-test10/drivers/acpi/common/cmxface.c Fri Sep 15 14:30:29 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/common/cmxface.c Fri Sep 22 18:15:13 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: cmxface - External interfaces for "global" ACPI functions - * $Revision: 43 $ + * $Revision: 47 $ * *****************************************************************************/ @@ -39,7 +39,7 @@ /******************************************************************************* * - * FUNCTION: Acpi_initialize + * FUNCTION: Acpi_initialize_subsystem * * PARAMETERS: None * @@ -51,7 +51,8 @@ ******************************************************************************/ ACPI_STATUS -acpi_initialize (ACPI_INIT_DATA *init_data) +acpi_initialize_subsystem ( + ACPI_INIT_DATA *init_data) { ACPI_STATUS status; @@ -76,6 +77,18 @@ return (status); } + /* + * Initialize the namespace manager and + * the root of the namespace tree + */ + + status = acpi_ns_root_initialize (); + if (ACPI_FAILURE (status)) { + REPORT_ERROR ("Namespace initialization failure"); + return (status); + } + + /* If configured, initialize the AML debugger */ DEBUGGER_EXEC (acpi_db_initialize ()); @@ -86,6 +99,102 @@ /******************************************************************************* * + * FUNCTION: Acpi_enable_subsystem + * + * PARAMETERS: Flags - Init/enable Options + * + * RETURN: Status + * + * DESCRIPTION: Completes the subsystem initialization including hardware. + * Puts system into ACPI mode if it isn't already. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_enable_subsystem ( + u32 flags) +{ + ACPI_STATUS status = AE_OK; + + + /* This simply sanity checks the FACP, and prints error messages */ + + acpi_cm_validate_facp (); + + /* + * Install the default Op_region handlers. These are + * installed unless other handlers have already been + * installed via the Install_address_space_handler interface + */ + + if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { + acpi_ev_install_default_address_space_handlers (); + } + + /* + * We must initialize the hardware before we can enable ACPI. + */ + + if (!(flags & ACPI_NO_HARDWARE_INIT)) { + status = acpi_hw_initialize (); + if (ACPI_FAILURE(status)) + acpi_os_printf("ACPI: acpi_hw_initialize fail 0x%x\n", status); + } + + /* + * Note: + * We must have the hardware AND events initialized before we can execute + * ANY control methods SAFELY. Any control method can require ACPI hardware + * support, so the hardware MUST be initialized before execution! + */ + + if (!(flags & ACPI_NO_EVENT_INIT)) { + status = acpi_ev_initialize (); + if (ACPI_FAILURE(status)) + acpi_os_printf("ACPI: acpi_ev_initialize fail 0x%x\n", status); + } + + + /* + * Enable ACPI on this platform + */ + + if (!(flags & ACPI_NO_ACPI_ENABLE)) { + acpi_enable (); + } + + + /* + * Initialize all device objects in the namespace + * This runs the _STA, _INI, and _HID methods, and detects + * the PCI root bus(es) + */ + + if (!(flags & ACPI_NO_DEVICE_INIT)) { + status = acpi_ns_initialize_devices (flags & ACPI_NO_PCI_INIT); + if (ACPI_FAILURE(status)) + acpi_os_printf("ACPI: acpi_ns_initialize_devices fail 0x%x\n", status); + } + + + /* + * Initialize the objects that remain unitialized. This + * runs the executable AML that is part of the declaration of Op_regions + * and Fields. + */ + + if (!(flags & ACPI_NO_OBJECT_INIT)) { + status = acpi_ns_initialize_objects (); + if (ACPI_FAILURE(status)) + acpi_os_printf("ACPI: acpi_ns_initialize_objects fail 0x%x\n", status); + } + + return (status); +} + + +/******************************************************************************* + * * FUNCTION: Acpi_terminate * * PARAMETERS: None @@ -202,7 +311,7 @@ /* Current status of the ACPI tables, per table type */ info_ptr->num_table_types = NUM_ACPI_TABLES; - for (i = 0; i < NUM_ACPI_TABLES; i++); { + for (i = 0; i < NUM_ACPI_TABLES; i++) { info_ptr->table_info[i].count = acpi_gbl_acpi_tables[i].count; } diff -urN linux-2.4.0-test10/drivers/acpi/dispatcher/dsobject.c linux-2.4.0-test10-lia/drivers/acpi/dispatcher/dsobject.c --- linux-2.4.0-test10/drivers/acpi/dispatcher/dsobject.c Fri Sep 15 14:30:29 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/dispatcher/dsobject.c Fri Sep 15 16:38:45 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: dsobject - Dispatcher object management routines - * $Revision: 43 $ + * $Revision: 45 $ * *****************************************************************************/ @@ -64,9 +64,11 @@ { OBJECT_TYPE_INTERNAL type; ACPI_STATUS status; - INIT_WALK_INFO *info = (INIT_WALK_INFO *) context; + ACPI_INIT_WALK_INFO *info = (ACPI_INIT_WALK_INFO *) context; + info->object_count++; + /* * We are only interested in objects owned by the table that * was just loaded @@ -154,11 +156,12 @@ ACPI_NAMESPACE_NODE *start_node) { ACPI_STATUS status; - INIT_WALK_INFO info; + ACPI_INIT_WALK_INFO info; info.method_count = 0; info.op_region_count = 0; + info.object_count = 0; info.table_desc = table_desc; diff -urN linux-2.4.0-test10/drivers/acpi/dispatcher/dsopcode.c linux-2.4.0-test10-lia/drivers/acpi/dispatcher/dsopcode.c --- linux-2.4.0-test10/drivers/acpi/dispatcher/dsopcode.c Fri Sep 15 14:30:29 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/dispatcher/dsopcode.c Fri Sep 15 16:38:45 2000 @@ -2,7 +2,7 @@ * * Module Name: dsopcode - Dispatcher Op Region support and handling of * "control" opcodes - * $Revision: 17 $ + * $Revision: 19 $ * *****************************************************************************/ @@ -40,9 +40,117 @@ /***************************************************************************** * + * FUNCTION: Acpi_ds_get_field_unit_arguments + * + * PARAMETERS: Obj_desc - A valid Field_unit object + * + * RETURN: Status. + * + * DESCRIPTION: Get Field_unit Buffer and Index. This implements the late + * evaluation of these field attributes. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_get_field_unit_arguments ( + ACPI_OPERAND_OBJECT *obj_desc) +{ + ACPI_OPERAND_OBJECT *extra_desc; + ACPI_NAMESPACE_NODE *node; + ACPI_PARSE_OBJECT *op; + ACPI_PARSE_OBJECT *field_op; + ACPI_STATUS status; + ACPI_TABLE_DESC *table_desc; + + + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { + return (AE_OK); + } + + + /* Get the AML pointer (method object) and Field_unit node */ + + extra_desc = obj_desc->field_unit.extra; + node = obj_desc->field_unit.node; + + + /* + * Allocate a new parser op to be the root of the parsed + * Op_region tree + */ + + op = acpi_ps_alloc_op (AML_SCOPE_OP); + if (!op) { + return (AE_NO_MEMORY); + } + + /* Save the Node for use in Acpi_ps_parse_aml */ + + op->node = acpi_ns_get_parent_object (node); + + /* Get a handle to the parent ACPI table */ + + status = acpi_tb_handle_to_object (node->owner_id, &table_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Pass1: Parse the entire Field_unit declaration */ + + status = acpi_ps_parse_aml (op, extra_desc->extra.pcode, + extra_desc->extra.pcode_length, 0, + NULL, NULL, NULL, acpi_ds_load1_begin_op, acpi_ds_load1_end_op); + if (ACPI_FAILURE (status)) { + acpi_ps_delete_parse_tree (op); + return (status); + } + + + /* Get and init the actual Fiel_unit_op created above */ + + field_op = op->value.arg; + op->node = node; + + + field_op = op->value.arg; + field_op->node = node; + acpi_ps_delete_parse_tree (op); + + /* Acpi_evaluate the address and length arguments for the Op_region */ + + op = acpi_ps_alloc_op (AML_SCOPE_OP); + if (!op) { + return (AE_NO_MEMORY); + } + + op->node = acpi_ns_get_parent_object (node); + + status = acpi_ps_parse_aml (op, extra_desc->extra.pcode, + extra_desc->extra.pcode_length, + ACPI_PARSE_EXECUTE | ACPI_PARSE_DELETE_TREE, + NULL /*Method_desc*/, NULL, NULL, + acpi_ds_exec_begin_op, acpi_ds_exec_end_op); + /* All done with the parse tree, delete it */ + + acpi_ps_delete_parse_tree (op); + + + /* + * The pseudo-method object is no longer needed since the region is + * now initialized + */ + acpi_cm_remove_reference (obj_desc->field_unit.extra); + obj_desc->field_unit.extra = NULL; + + return (status); +} + + +/***************************************************************************** + * * FUNCTION: Acpi_ds_get_region_arguments * - * PARAMETERS: Rgn_desc - A valid region object + * PARAMETERS: Obj_desc - A valid region object * * RETURN: Status. * @@ -53,9 +161,9 @@ ACPI_STATUS acpi_ds_get_region_arguments ( - ACPI_OPERAND_OBJECT *rgn_desc) + ACPI_OPERAND_OBJECT *obj_desc) { - ACPI_OPERAND_OBJECT *method_desc; + ACPI_OPERAND_OBJECT *extra_desc = NULL; ACPI_NAMESPACE_NODE *node; ACPI_PARSE_OBJECT *op; ACPI_PARSE_OBJECT *region_op; @@ -63,14 +171,15 @@ ACPI_TABLE_DESC *table_desc; - if (rgn_desc->region.flags & AOPOBJ_DATA_VALID) { + if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { return (AE_OK); } - method_desc = rgn_desc->region.method; - node = rgn_desc->region.node; + /* Get the AML pointer (method object) and region node */ + extra_desc = obj_desc->region.extra; + node = obj_desc->region.node; /* * Allocate a new parser op to be the root of the parsed @@ -95,8 +204,8 @@ /* Parse the entire Op_region declaration, creating a parse tree */ - status = acpi_ps_parse_aml (op, method_desc->method.pcode, - method_desc->method.pcode_length, 0, + status = acpi_ps_parse_aml (op, extra_desc->extra.pcode, + extra_desc->extra.pcode_length, 0, NULL, NULL, NULL, acpi_ds_load1_begin_op, acpi_ds_load1_end_op); if (ACPI_FAILURE (status)) { @@ -107,8 +216,8 @@ /* Get and init the actual Region_op created above */ -/* Region_op = Op->Value.Arg; - Op->Node = Node;*/ + region_op = op->value.arg; + op->node = node; region_op = op->value.arg; @@ -124,8 +233,8 @@ op->node = acpi_ns_get_parent_object (node); - status = acpi_ps_parse_aml (op, method_desc->method.pcode, - method_desc->method.pcode_length, + status = acpi_ps_parse_aml (op, extra_desc->extra.pcode, + extra_desc->extra.pcode_length, ACPI_PARSE_EXECUTE | ACPI_PARSE_DELETE_TREE, NULL /*Method_desc*/, NULL, NULL, acpi_ds_exec_begin_op, acpi_ds_exec_end_op); @@ -138,6 +247,18 @@ acpi_ps_delete_parse_tree (op); + + /* + * The pseudo-method object is no longer needed since the field is + * now initialized + */ + +/* ALWAYS KEEP THIS! + Acpi_cm_remove_reference (Obj_desc->Region.Method); + Obj_desc->Region.Method = NULL; +*/ + + return (status); } @@ -174,6 +295,252 @@ /***************************************************************************** * + * FUNCTION: Acpi_ds_eval_field_unit_operands + * + * PARAMETERS: Op - A valid Field_unit Op object + * + * RETURN: Status + * + * DESCRIPTION: Get Field_unit Buffer and Index + * Called from Acpi_ds_exec_end_op during Field_unit parse tree walk + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_eval_field_unit_operands ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *field_desc; + ACPI_NAMESPACE_NODE *node; + ACPI_PARSE_OBJECT *next_op; + u32 offset; + u32 bit_offset; + u16 bit_count; + + + ACPI_OPERAND_OBJECT *res_desc = NULL; + ACPI_OPERAND_OBJECT *cnt_desc = NULL; + ACPI_OPERAND_OBJECT *off_desc = NULL; + ACPI_OPERAND_OBJECT *src_desc = NULL; + u32 num_operands = 3; + + + /* + * This is where we evaluate the address and length fields of the Op_field_unit declaration + */ + + node = op->node; + + /* Next_op points to the op that holds the Buffer */ + next_op = op->value.arg; + + /* Acpi_evaluate/create the address and length operands */ + + status = acpi_ds_create_operands (walk_state, next_op); + if (ACPI_FAILURE (status)) { + return (status); + } + + field_desc = acpi_ns_get_attached_object (node); + if (!field_desc) { + return (AE_NOT_EXIST); + } + + + /* Resolve the operands */ + + status = acpi_aml_resolve_operands (op->opcode, WALK_OPERANDS, walk_state); + + /* Get the operands */ + + status |= acpi_ds_obj_stack_pop_object (&res_desc, walk_state); + if (AML_CREATE_FIELD_OP == op->opcode) { + num_operands = 4; + status |= acpi_ds_obj_stack_pop_object (&cnt_desc, walk_state); + } + + status |= acpi_ds_obj_stack_pop_object (&off_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&src_desc, walk_state); + + if (ACPI_FAILURE (status)) { + /* Invalid parameters on object stack */ + + goto cleanup; + } + + + offset = off_desc->number.value; + + + /* + * If Res_desc is a Name, it will be a direct name pointer after + * Acpi_aml_resolve_operands() + */ + + if (!VALID_DESCRIPTOR_TYPE (res_desc, ACPI_DESC_TYPE_NAMED)) { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + + /* + * Setup the Bit offsets and counts, according to the opcode + */ + + switch (op->opcode) + { + + /* Def_create_bit_field */ + + case AML_BIT_FIELD_OP: + + /* Offset is in bits, Field is a bit */ + + bit_offset = offset; + bit_count = 1; + break; + + + /* Def_create_byte_field */ + + case AML_BYTE_FIELD_OP: + + /* Offset is in bytes, field is a byte */ + + bit_offset = 8 * offset; + bit_count = 8; + break; + + + /* Def_create_word_field */ + + case AML_WORD_FIELD_OP: + + /* Offset is in bytes, field is a word */ + + bit_offset = 8 * offset; + bit_count = 16; + break; + + + /* Def_create_dWord_field */ + + case AML_DWORD_FIELD_OP: + + /* Offset is in bytes, field is a dword */ + + bit_offset = 8 * offset; + bit_count = 32; + break; + + + /* Def_create_field */ + + case AML_CREATE_FIELD_OP: + + /* Offset is in bits, count is in bits */ + + bit_offset = offset; + bit_count = (u16) cnt_desc->number.value; + break; + + + default: + + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + + /* + * Setup field according to the object type + */ + + switch (src_desc->common.type) + { + + /* Source_buff := Term_arg=>Buffer */ + + case ACPI_TYPE_BUFFER: + + if (bit_offset + (u32) bit_count > + (8 * (u32) src_desc->buffer.length)) + { + status = AE_AML_BUFFER_LIMIT; + goto cleanup; + } + + + /* Construct the remainder of the field object */ + + field_desc->field_unit.access = (u8) ACCESS_ANY_ACC; + field_desc->field_unit.lock_rule = (u8) GLOCK_NEVER_LOCK; + field_desc->field_unit.update_rule = (u8) UPDATE_PRESERVE; + field_desc->field_unit.length = bit_count; + field_desc->field_unit.bit_offset = (u8) (bit_offset % 8); + field_desc->field_unit.offset = DIV_8 (bit_offset); + field_desc->field_unit.container = src_desc; + + /* Reference count for Src_desc inherits Field_desc count */ + + src_desc->common.reference_count = (u16) (src_desc->common.reference_count + + field_desc->common.reference_count); + + break; + + + /* Improper object type */ + + default: + + if ((src_desc->common.type > (u8) INTERNAL_TYPE_REFERENCE) || + !acpi_cm_valid_object_type (src_desc->common.type)) + + + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + + if (AML_CREATE_FIELD_OP == op->opcode) { + /* Delete object descriptor unique to Create_field */ + + acpi_cm_remove_reference (cnt_desc); + cnt_desc = NULL; + } + + +cleanup: + + /* Always delete the operands */ + + acpi_cm_remove_reference (off_desc); + acpi_cm_remove_reference (src_desc); + + if (AML_CREATE_FIELD_OP == op->opcode) { + acpi_cm_remove_reference (cnt_desc); + } + + /* On failure, delete the result descriptor */ + + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (res_desc); /* Result descriptor */ + } + + else { + /* Now the address and length are valid for this op_field_unit */ + + field_desc->field_unit.flags |= AOPOBJ_DATA_VALID; + } + + return (status); +} + + +/***************************************************************************** + * * FUNCTION: Acpi_ds_eval_region_operands * * PARAMETERS: Op - A valid region Op object @@ -192,7 +559,7 @@ { ACPI_STATUS status; ACPI_OPERAND_OBJECT *obj_desc; - ACPI_OPERAND_OBJECT *region_desc; + ACPI_OPERAND_OBJECT *operand_desc; ACPI_NAMESPACE_NODE *node; ACPI_PARSE_OBJECT *next_op; @@ -216,31 +583,31 @@ return (status); } - region_desc = acpi_ns_get_attached_object (node); - if (!region_desc) { + obj_desc = acpi_ns_get_attached_object (node); + if (!obj_desc) { return (AE_NOT_EXIST); } /* Get the length and save it */ /* Top of stack */ - obj_desc = walk_state->operands[walk_state->num_operands - 1]; + operand_desc = walk_state->operands[walk_state->num_operands - 1]; - region_desc->region.length = obj_desc->number.value; - acpi_cm_remove_reference (obj_desc); + obj_desc->region.length = operand_desc->number.value; + acpi_cm_remove_reference (operand_desc); /* Get the address and save it */ /* Top of stack - 1 */ - obj_desc = walk_state->operands[walk_state->num_operands - 2]; + operand_desc = walk_state->operands[walk_state->num_operands - 2]; - region_desc->region.address = obj_desc->number.value; - acpi_cm_remove_reference (obj_desc); + obj_desc->region.address = operand_desc->number.value; + acpi_cm_remove_reference (operand_desc); /* Now the address and length are valid for this opregion */ - region_desc->region.flags |= AOPOBJ_DATA_VALID; + obj_desc->region.flags |= AOPOBJ_DATA_VALID; return (status); } diff -urN linux-2.4.0-test10/drivers/acpi/dispatcher/dswexec.c linux-2.4.0-test10-lia/drivers/acpi/dispatcher/dswexec.c --- linux-2.4.0-test10/drivers/acpi/dispatcher/dswexec.c Fri Sep 15 14:30:29 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/dispatcher/dswexec.c Fri Sep 15 16:38:45 2000 @@ -2,7 +2,7 @@ * * Module Name: dswexec - Dispatcher method execution callbacks; * dispatch to interpreter. - * $Revision: 42 $ + * $Revision: 44 $ * *****************************************************************************/ @@ -236,7 +236,6 @@ case OPTYPE_RECONFIGURATION: case OPTYPE_INDEX: case OPTYPE_MATCH: - case OPTYPE_CREATE_FIELD: case OPTYPE_FATAL: @@ -341,14 +340,6 @@ break; - case OPTYPE_CREATE_FIELD: - - /* 3 or 4 Operands, 0 External_result, 0 Internal_result */ - - status = acpi_aml_exec_create_field (opcode, walk_state); - break; - - case OPTYPE_FATAL: /* 3 Operands, 0 External_result, 0 Internal_result */ @@ -400,17 +391,17 @@ * the method Node pointer */ /* Next_op points to the op that holds the method name */ + next_op = first_arg; node = next_op->node; /* Next_op points to first argument op */ - next_op = next_op->next; + next_op = next_op->next; /* * Get the method's arguments and put them on the operand stack */ - status = acpi_ds_create_operands (walk_state, next_op); if (ACPI_FAILURE (status)) { break; @@ -428,43 +419,37 @@ break; } - /* Open new scope on the scope stack */ -/* - Status = Acpi_ns_scope_stack_push_entry (Node); - if (ACPI_FAILURE (Status)) { - break; - } -*/ + /* + * Tell the walk loop to preempt this running method and + * execute the new method + */ + status = AE_CTRL_TRANSFER; - /* Tell the walk loop to preempt this running method and - execute the new method */ + /* + * Return now; we don't want to disturb anything, + * especially the operand count! + */ + return (status); + break; - status = AE_CTRL_TRANSFER; - /* Return now; we don't want to disturb anything, - especially the operand count! */ + case OPTYPE_CREATE_FIELD: - return (status); + status = acpi_ds_load2_end_op (walk_state, op); + if (ACPI_FAILURE (status)) { + break; + } + + status = acpi_ds_eval_field_unit_operands (walk_state, op); break; case OPTYPE_NAMED_OBJECT: - status = acpi_ds_load2_end_op (walk_state, op); if (ACPI_FAILURE (status)) { break; } -/* - if ((Walk_state->Origin->Opcode == AML_METHOD_OP) && - (Walk_state->Origin != Op)) - { - Status = Acpi_ds_load2_end_op (Walk_state, Op); - if (ACPI_FAILURE (Status)) { - break; - } - } -*/ switch (op->opcode) { diff -urN linux-2.4.0-test10/drivers/acpi/dispatcher/dswload.c linux-2.4.0-test10-lia/drivers/acpi/dispatcher/dswload.c --- linux-2.4.0-test10/drivers/acpi/dispatcher/dswload.c Fri Sep 15 14:30:29 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/dispatcher/dswload.c Fri Sep 15 16:38:45 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: dswload - Dispatcher namespace load callbacks - * $Revision: 19 $ + * $Revision: 22 $ * *****************************************************************************/ @@ -438,6 +438,11 @@ case AML_WORD_FIELD_OP: case AML_DWORD_FIELD_OP: + /* + * Create the field object, but the field buffer and index must + * be evaluated later during the execution phase + */ + /* Get the Name_string argument */ if (op->opcode == AML_CREATE_FIELD_OP) { @@ -468,15 +473,22 @@ op->node = new_node; /* - * If this is NOT a control method, we need to evaluate this opcode now. + * If there is no object attached to the node, this node was just created and + * we need to create the field object. Otherwise, this was a lookup of an + * existing node and we don't want to create the field object again. */ - - /* THIS WON"T WORK. Must execute all operands like Add(). => Must do an execute pass - if (!Walk_state->Method_desc) { - Status = Acpi_ds_exec_end_op (Walk_state, Op); + if (!new_node->object) { + /* + * The Field definition is not fully parsed at this time. + * (We must save the address of the AML for the buffer and index operands) + */ + status = acpi_aml_exec_create_field (((ACPI_PARSE2_OBJECT *) op)->data, + ((ACPI_PARSE2_OBJECT *) op)->length, + new_node, walk_state); } - */ } + + break; @@ -639,7 +651,15 @@ case AML_NAME_OP: - status = acpi_ds_create_node (walk_state, node, op); + /* + * Because of the execution pass through the non-control-method + * parts of the table, we can arrive here twice. Only init + * the named object node the first time through + */ + + if (!node->object) { + status = acpi_ds_create_node (walk_state, node, op); + } break; @@ -661,4 +681,5 @@ acpi_ds_obj_stack_pop (1, walk_state); return (status); } + diff -urN linux-2.4.0-test10/drivers/acpi/driver.c linux-2.4.0-test10-lia/drivers/acpi/driver.c --- linux-2.4.0-test10/drivers/acpi/driver.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/driver.c Thu Oct 19 18:07:35 2000 @@ -29,6 +29,7 @@ #include #include #include +#include #include "acpi.h" #include "driver.h" @@ -105,7 +106,7 @@ acpi_event(void *context) { unsigned long flags; - int event = (int) context; + int event = (int)(long)context; int mask = 0; switch (event) { @@ -207,6 +208,58 @@ } /* + * Output important ACPI tables to proc + */ +static int +acpi_do_table(ctl_table * ctl, + int write, + struct file *file, + void *buffer, + size_t * len) +{ + u32 table_type; + size_t size; + ACPI_BUFFER buf; + u8* data; + + table_type = (u32)(NATIVE_UINT)ctl->data; + size = 0; + buf.length = 0; + buf.pointer = NULL; + + /* determine what buffer size we will need */ + if (acpi_get_table(table_type, 1, &buf) != AE_BUFFER_OVERFLOW) { + return 0; + } + + buf.pointer = kmalloc(buf.length, GFP_KERNEL); + if (!buf.pointer) { + return 0; + } + + /* get the table for real */ + if (!ACPI_SUCCESS(acpi_get_table(table_type, 1, &buf))) { + kfree(buf.pointer); + return 0; + } + + if (file->f_pos < buf.length) { + data = buf.pointer + file->f_pos; + size = buf.length - file->f_pos; + if (size > *len) + size = *len; + if (copy_to_user(buffer, data, size)) + return -EFAULT; + } + + kfree(buf.pointer); + + *len = size; + file->f_pos += size; + return 0; +} + +/* * Run queued callback */ static void @@ -266,6 +319,10 @@ {ACPI_EVENT, "event", NULL, 0, 0400, NULL, &acpi_do_event}, + {ACPI_FACP, "facp", (void *) ACPI_TABLE_FACP, sizeof(int), 0444, NULL, &acpi_do_table}, + + {ACPI_DSDT, "dsdt", (void *) ACPI_TABLE_DSDT, sizeof(int), 0444, NULL, &acpi_do_table}, + {0} }; @@ -281,6 +338,10 @@ static int acpi_thread(void *context) { +#ifdef __ia64__ + ACPI_INIT_DATA acpi_init_data; +#endif + /* * initialize */ @@ -288,8 +349,14 @@ daemonize(); strcpy(current->comm, "acpi"); - if (!ACPI_SUCCESS(acpi_initialize(NULL))) { - printk(KERN_ERR "ACPI: initialize failed\n"); +#ifdef __ia64__ + acpi_init_data.RSDP_physical_address = efi.acpi; + if (!ACPI_SUCCESS(acpi_initialize_subsystem(&acpi_init_data))) +#else + if (!ACPI_SUCCESS(acpi_initialize_subsystem(NULL))) +#endif + { + printk(KERN_ERR "ACPI: initialize_subsystem failed\n"); return -ENODEV; } @@ -304,14 +371,16 @@ pm_active = 1; - if (!ACPI_SUCCESS(acpi_enable())) { - printk(KERN_ERR "ACPI: enable failed\n"); + if (!ACPI_SUCCESS(acpi_enable_subsystem(ACPI_FULL_INITIALIZATION))) { + printk(KERN_ERR "ACPI: enable_subsystem failed\n"); acpi_terminate(); return -ENODEV; } acpi_cpu_init(); + acpi_sys_init(); + acpi_ec_init(); if (!ACPI_SUCCESS(acpi_install_fixed_event_handler( @@ -320,6 +389,7 @@ (void *) ACPI_EVENT_POWER_BUTTON))) { printk(KERN_ERR "ACPI: power button enable failed\n"); } + if (!ACPI_SUCCESS(acpi_install_fixed_event_handler( ACPI_EVENT_SLEEP_BUTTON, acpi_event, diff -urN linux-2.4.0-test10/drivers/acpi/ec.c linux-2.4.0-test10-lia/drivers/acpi/ec.c --- linux-2.4.0-test10/drivers/acpi/ec.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/ec.c Mon Sep 18 20:13:38 2000 @@ -1,21 +1,21 @@ /* - * ec.c - Embedded controller support + * ec.c - Embedded controller support * - * Copyright (C) 2000 Andrew Henroid + * Copyright (C) 2000 Andrew Henroid * - * 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 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. + * 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 + * 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 @@ -74,9 +74,9 @@ static void acpi_ec_wait_control(void) { - udelay(1); - while(inb(acpi_ec_status) & ACPI_EC_IBF) - udelay(10); + udelay(1); + while(inb(acpi_ec_status) & ACPI_EC_IBF) + udelay(10); } /* @@ -88,12 +88,12 @@ if (!acpi_ec_data || !acpi_ec_status) return -1; - outb(ACPI_EC_READ, acpi_ec_status); - acpi_ec_wait_control(); - outb(addr, acpi_ec_data); - acpi_ec_wait_control(); - interruptible_sleep_on(&acpi_ec_wait); - *value = inb(acpi_ec_data); + outb(ACPI_EC_READ, acpi_ec_status); + acpi_ec_wait_control(); + outb(addr, acpi_ec_data); + acpi_ec_wait_control(); + interruptible_sleep_on(&acpi_ec_wait); + *value = inb(acpi_ec_data); return 0; } @@ -107,13 +107,13 @@ if (!acpi_ec_data || !acpi_ec_status) return -1; - outb(ACPI_EC_WRITE, acpi_ec_status); - acpi_ec_wait_control(); - outb(addr, acpi_ec_data); - acpi_ec_wait_control(); - outb(value, acpi_ec_data); - acpi_ec_wait_control(); - interruptible_sleep_on(&acpi_ec_wait); + outb(ACPI_EC_WRITE, acpi_ec_status); + acpi_ec_wait_control(); + outb(addr, acpi_ec_data); + acpi_ec_wait_control(); + outb(value, acpi_ec_data); + acpi_ec_wait_control(); + interruptible_sleep_on(&acpi_ec_wait); return 0; } @@ -164,7 +164,7 @@ gpe = (int) obj.number.value; printk(KERN_INFO "ACPI: found EC @ (0x%02x,0x%02x,%d)\n", - acpi_ec_data, acpi_ec_status, gpe); + acpi_ec_data, acpi_ec_status, gpe); if (!ACPI_SUCCESS(acpi_install_gpe_handler( gpe, @@ -172,7 +172,6 @@ | ACPI_EVENT_EDGE_TRIGGERED), acpi_ec_gpe, NULL))) { - DEBUG_PRINT(ACPI_ERROR, ("Could not install GPE handler for EC.\n")); return AE_OK; } diff -urN linux-2.4.0-test10/drivers/acpi/events/evevent.c linux-2.4.0-test10-lia/drivers/acpi/events/evevent.c --- linux-2.4.0-test10/drivers/acpi/events/evevent.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/events/evevent.c Thu Sep 21 13:38:14 2000 @@ -2,7 +2,7 @@ * * Module Name: evevent - Fixed and General Purpose Acpi_event * handling and dispatch - * $Revision: 13 $ + * $Revision: 15 $ * *****************************************************************************/ @@ -34,6 +34,80 @@ MODULE_NAME ("evevent") +/************************************************************************** + * + * FUNCTION: Acpi_ev_initialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Ensures that the system control interrupt (SCI) is properly + * configured, disables SCI event sources, installs the SCI + * handler + * + *************************************************************************/ + +ACPI_STATUS +acpi_ev_initialize ( + void) +{ + ACPI_STATUS status; + + + /* Make sure we've got ACPI tables */ + + if (!acpi_gbl_DSDT) { + return (AE_NO_ACPI_TABLES); + } + + + /* Make sure the BIOS supports ACPI mode */ + + if (SYS_MODE_LEGACY == acpi_hw_get_mode_capabilities()) { + return (AE_ERROR); + } + + + acpi_gbl_original_mode = acpi_hw_get_mode(); + + /* + * Initialize the Fixed and General Purpose Acpi_events prior. This is + * done prior to enabling SCIs to prevent interrupts from occuring + * before handers are installed. + */ + + status = acpi_ev_fixed_event_initialize (); + if (ACPI_FAILURE (status)) { + return (status); + } + + status = acpi_ev_gpe_initialize (); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Install the SCI handler */ + + status = acpi_ev_install_sci_handler (); + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* Install handlers for control method GPE handlers (_Lxx, _Exx) */ + + acpi_ev_init_gpe_control_methods (); + + /* Install the handler for the Global Lock */ + + status = acpi_ev_init_global_lock_handler (); + + + return (status); +} + + /****************************************************************************** * * FUNCTION: Acpi_ev_fixed_event_initialize @@ -553,7 +627,7 @@ acpi_ev_asynch_execute_gpe_method ( void *context) { - u32 gpe_number = (u32) context; + u32 gpe_number = (u32) (NATIVE_UINT)context; ACPI_GPE_LEVEL_INFO gpe_info; diff -urN linux-2.4.0-test10/drivers/acpi/events/evregion.c linux-2.4.0-test10-lia/drivers/acpi/events/evregion.c --- linux-2.4.0-test10/drivers/acpi/events/evregion.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/events/evregion.c Wed Sep 20 19:20:10 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: evregion - ACPI Address_space / Op_region handler dispatch - * $Revision: 76 $ + * $Revision: 80 $ * *****************************************************************************/ @@ -34,202 +34,6 @@ MODULE_NAME ("evregion") -#define PCI_ROOT_HID_STRING "PNP0A03" -#define PCI_ROOT_HID_VALUE 0x030AD041 /* EISAID("PNP0A03") */ - - -/****************************************************************************** - * - * FUNCTION: Acpi_ev_find_one_pci_root_bus - * - * PARAMETERS: - * - * RETURN: None - * - * DESCRIPTION: - * - *****************************************************************************/ - -ACPI_STATUS -acpi_ev_find_one_pci_root_bus ( - ACPI_HANDLE obj_handle, - u32 nesting_level, - void *context, - void **return_value) -{ - ACPI_NAMESPACE_NODE *node; - ACPI_OPERAND_OBJECT *obj_desc; - ACPI_STATUS status; - - - node = (ACPI_NAMESPACE_NODE *) obj_handle; - obj_desc = ((ACPI_NAMESPACE_NODE *) obj_handle)->object; - - - /* - * We are looking for all valid _HID objects. - */ - - if (STRNCMP ((NATIVE_CHAR *) &node->name, METHOD_NAME__HID, ACPI_NAME_SIZE) || - (!obj_desc)) - { - return (AE_OK); - } - - - /* - * Found an _HID object. - * Now we need a HID with the value EISAID("PNP0A03") - * HID can be either a number or a string. - */ - - switch (obj_desc->common.type) - { - case ACPI_TYPE_NUMBER: - - if (obj_desc->number.value != PCI_ROOT_HID_VALUE) { - return (AE_OK); - } - - break; - - case ACPI_TYPE_STRING: - - if (STRNCMP (obj_desc->string.pointer, PCI_ROOT_HID_STRING, - sizeof (PCI_ROOT_HID_STRING))) - { - return (AE_OK); - } - - break; - - default: - - return (AE_OK); - } - - - /* - * We found a valid PCI_ROOT_HID. - * The parent of the HID entry is the PCI device; Install the default PCI - * handler for this PCI device. - */ - - status = acpi_install_address_space_handler (acpi_ns_get_parent_object (node), - ADDRESS_SPACE_PCI_CONFIG, - ACPI_DEFAULT_HANDLER, NULL, NULL); - - return (AE_OK); -} - - -/****************************************************************************** - * - * FUNCTION: Acpi_ev_find_pci_root_buses - * - * PARAMETERS: - * - * RETURN: None - * - * DESCRIPTION: - * - *****************************************************************************/ - -ACPI_STATUS -acpi_ev_find_pci_root_buses ( - void) -{ - - acpi_ns_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, - FALSE, acpi_ev_find_one_pci_root_bus, NULL, NULL); - - return (AE_OK); -} - -/****************************************************************************** - * - * FUNCTION: Acpi_ev_init_one_device - * - * PARAMETERS: The usual "I'm a namespace callback" stuff - * - * RETURN: ACPI_STATUS - * - * DESCRIPTION: This is called once per device soon after ACPI is enabled - * to initialize each device. It determines if the device is - * present, and if so, calls _INI. - * - *****************************************************************************/ - -ACPI_STATUS -acpi_ev_init_one_device ( - ACPI_HANDLE obj_handle, - u32 nesting_level, - void *context, - void **return_value) -{ - ACPI_STATUS status; - ACPI_OPERAND_OBJECT *ret_obj; - - - /* - * Run _STA to determine if we can run _INI on the device. - */ - status = acpi_ns_evaluate_relative(obj_handle, "_STA", NULL, &ret_obj); - if (AE_NOT_FOUND == status) { - /* No _STA means device is present */ - } - else if (ACPI_FAILURE (status)) { - return (status); - } - else if (ret_obj) { - if (ACPI_TYPE_NUMBER != ret_obj->common.type) { - status = AE_AML_OPERAND_TYPE; - goto cleanup; - } - - /* - * if _STA "present" bit not set, we're done. - */ - if (!(ret_obj->number.value & 1)) { - goto cleanup; - } - } - - /* - * The device is present. Run _INI. - */ - - status = acpi_ns_evaluate_relative(obj_handle, "_INI", NULL, NULL); - -cleanup: - - acpi_cm_remove_reference (ret_obj); - return (status); -} - -/****************************************************************************** - * - * FUNCTION: Acpi_ev_init_devices - * - * PARAMETERS: None - * - * RETURN: ACPI_STATUS - * - * DESCRIPTION: This initializes all ACPI devices. - * - *****************************************************************************/ - -ACPI_STATUS -acpi_ev_init_devices ( - void) -{ - acpi_ns_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, - FALSE, acpi_ev_init_one_device, NULL, NULL); - - return (AE_OK); -} - - /************************************************************************** * * FUNCTION: Acpi_ev_install_default_address_space_handlers @@ -250,32 +54,47 @@ /* - * NOTE: All address spaces (PCI Config, EC, SMBus) are scope dependent - * and registration must occur for a specific device. In the case - * system memory and IO address spaces there is currently no device - * associated with the address space. For these we use the root. + * All address spaces (PCI Config, EC, SMBus) are scope dependent + * and registration must occur for a specific device. In the case + * system memory and IO address spaces there is currently no device + * associated with the address space. For these we use the root. + * + * NOTE: We ignore AE_EXIST because this means that a handler has + * already been installed (via Acpi_install_address_space_handler) */ status = acpi_install_address_space_handler (acpi_gbl_root_node, ADDRESS_SPACE_SYSTEM_MEMORY, ACPI_DEFAULT_HANDLER, NULL, NULL); - if (ACPI_FAILURE (status)) { + if ((ACPI_FAILURE (status)) && + (status != AE_EXIST)) + { return (status); } status = acpi_install_address_space_handler (acpi_gbl_root_node, ADDRESS_SPACE_SYSTEM_IO, ACPI_DEFAULT_HANDLER, NULL, NULL); - if (ACPI_FAILURE (status)) { + if ((ACPI_FAILURE (status)) && + (status != AE_EXIST)) + { return (status); } + status = acpi_install_address_space_handler (acpi_gbl_root_node, + ADDRESS_SPACE_PCI_CONFIG, + ACPI_DEFAULT_HANDLER, NULL, NULL); + if ((ACPI_FAILURE (status)) && + (status != AE_EXIST)) + { + return (status); + } return (AE_OK); } -/* TBD: [Restructure] Move to the methods directory */ +/* TBD: [Restructure] Move elsewhere */ /************************************************************************** * @@ -301,7 +120,7 @@ ACPI_STATUS status; - if (region_obj->region.REGmethod == NULL) { + if (region_obj->region.extra->extra.method_REG == NULL) { return (AE_OK); } @@ -337,7 +156,7 @@ /* * Execute the method, no return value */ - status = acpi_ns_evaluate_by_handle (region_obj->region.REGmethod, params, NULL); + status = acpi_ns_evaluate_by_handle (region_obj->region.extra->extra.method_REG, params, NULL); return (status); } @@ -425,7 +244,7 @@ * Save the returned context for use in all accesses to * this particular region. */ - region_obj->region.region_context = region_context; + region_obj->region.extra->extra.region_context = region_context; } /* @@ -447,7 +266,7 @@ */ status = handler (function, address, bit_width, value, handler_desc->addr_handler.context, - region_obj->region.region_context); + region_obj->region.extra->extra.region_context); if (!(handler_desc->addr_handler.flags & ADDR_HANDLER_DEFAULT_INSTALLED)) { @@ -462,7 +281,7 @@ /****************************************************************************** * - * FUNCTION: Acpi_ev_disassociate_region_and_handler + * FUNCTION: Acpi_ev_disassociate_region_from_handler * * PARAMETERS: Handler_obj - Handler Object * Region_obj - Region Object @@ -482,7 +301,7 @@ ACPI_OPERAND_OBJECT *obj_desc; ACPI_OPERAND_OBJECT **last_obj_ptr; ADDRESS_SPACE_SETUP region_setup; - void *region_context = region_obj->region.region_context; + void *region_context = region_obj->region.extra->extra.region_context; ACPI_STATUS status; diff -urN linux-2.4.0-test10/drivers/acpi/events/evrgnini.c linux-2.4.0-test10-lia/drivers/acpi/events/evrgnini.c --- linux-2.4.0-test10/drivers/acpi/events/evrgnini.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/events/evrgnini.c Fri Sep 15 16:38:45 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: evrgnini- ACPI Address_space / Op_region init - * $Revision: 22 $ + * $Revision: 23 $ * *****************************************************************************/ @@ -135,7 +135,7 @@ * * DESCRIPTION: Do any prep work for region handling * - * MUTEX: Assumes namespace is locked + * MUTEX: Assumes namespace is not locked * ****************************************************************************/ @@ -197,8 +197,6 @@ node = acpi_ns_get_parent_object (region_obj->region.node); - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); - /* Acpi_evaluate the _ADR object */ status = acpi_cm_evaluate_numeric_object (METHOD_NAME__ADR, node, &temp); @@ -241,7 +239,6 @@ *region_context = pci_context; - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); region_obj->region.flags |= AOPOBJ_INITIALIZED; @@ -332,7 +329,7 @@ space_id = region_obj->region.space_id; region_obj->region.addr_handler = NULL; - region_obj->region.REGmethod = NULL; + region_obj->region.extra->extra.method_REG = NULL; region_obj->region.flags &= ~(AOPOBJ_INITIALIZED); /* @@ -346,7 +343,7 @@ * definition. This will be executed when the handler is attached * or removed */ - region_obj->region.REGmethod = method_node; + region_obj->region.extra->extra.method_REG = method_node; } /* diff -urN linux-2.4.0-test10/drivers/acpi/events/evxfevnt.c linux-2.4.0-test10-lia/drivers/acpi/events/evxfevnt.c --- linux-2.4.0-test10/drivers/acpi/events/evxfevnt.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/events/evxfevnt.c Fri Sep 15 16:38:45 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable - * $Revision: 19 $ + * $Revision: 22 $ * *****************************************************************************/ @@ -35,14 +35,6 @@ MODULE_NAME ("evxfevnt") -ACPI_STATUS -acpi_ev_find_pci_root_buses ( - void); - -ACPI_STATUS -acpi_ev_init_devices ( - void); - /************************************************************************** * * FUNCTION: Acpi_enable @@ -51,9 +43,7 @@ * * RETURN: Status * - * DESCRIPTION: Ensures that the system control interrupt (SCI) is properly - * configured, disables SCI event sources, installs the SCI - * handler, and transfers the system into ACPI mode. + * DESCRIPTION: Transfers the system into ACPI mode. * *************************************************************************/ @@ -69,84 +59,18 @@ return (AE_NO_ACPI_TABLES); } - /* Init the hardware */ - - /* - * With the advent of a 3-pass parser, we need to be - * prepared to execute on initialized HW before the - * namespace has completed its load. - */ - - status = acpi_cm_hardware_initialize (); - if (ACPI_FAILURE (status)) { - return (status); - } - - /* Make sure the BIOS supports ACPI mode */ if (SYS_MODE_LEGACY == acpi_hw_get_mode_capabilities()) { return (AE_ERROR); } - - acpi_gbl_original_mode = acpi_hw_get_mode(); - - /* - * Initialize the Fixed and General Purpose Acpi_events prior. This is - * done prior to enabling SCIs to prevent interrupts from occuring - * before handers are installed. - */ - - status = acpi_ev_fixed_event_initialize (); - if (ACPI_FAILURE (status)) { - return (status); - } - - status = acpi_ev_gpe_initialize (); - if (ACPI_FAILURE (status)) { - return (status); - } - - /* Install the SCI handler */ - - status = acpi_ev_install_sci_handler (); - if (ACPI_FAILURE (status)) { - return (status); - } - /* Transition to ACPI mode */ status = acpi_hw_set_mode (SYS_MODE_ACPI); if (ACPI_FAILURE (status)) { return (status); } - - /* Install handlers for control method GPE handlers (_Lxx, _Exx) */ - - acpi_ev_init_gpe_control_methods (); - - status = acpi_ev_init_global_lock_handler (); - - /* - * Perform additional initialization that may cause control methods - * to be executed - * - * It may be wise to move this code to a new interface - */ - - - /* - * Install PCI config space handler for all PCI root bridges. A PCI root - * bridge is found by searching for devices containing a HID with the value - * EISAID("PNP0A03") - */ - - acpi_ev_find_pci_root_buses (); - - /* Call _INI on all devices */ - - acpi_ev_init_devices (); return (status); } diff -urN linux-2.4.0-test10/drivers/acpi/hardware/hwacpi.c linux-2.4.0-test10-lia/drivers/acpi/hardware/hwacpi.c --- linux-2.4.0-test10/drivers/acpi/hardware/hwacpi.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/hardware/hwacpi.c Fri Sep 15 16:38:45 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: hwacpi - ACPI hardware functions - mode and timer - * $Revision: 22 $ + * $Revision: 24 $ * *****************************************************************************/ @@ -34,6 +34,154 @@ /****************************************************************************** * + * FUNCTION: Acpi_hw_initialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize and validate various ACPI registers + * + ******************************************************************************/ + +ACPI_STATUS +acpi_hw_initialize ( + void) +{ + ACPI_STATUS status = AE_OK; + u32 index; + + + /* We must have the ACPI tables by the time we get here */ + + if (!acpi_gbl_FACP) { + acpi_gbl_restore_acpi_chipset = FALSE; + + return (AE_NO_ACPI_TABLES); + } + + /* Must support *some* mode! */ +/* + if (!(System_flags & SYS_MODES_MASK)) { + Restore_acpi_chipset = FALSE; + + return (AE_ERROR); + } + +*/ + + + switch (acpi_gbl_system_flags & SYS_MODES_MASK) + { + /* Identify current ACPI/legacy mode */ + + case (SYS_MODE_ACPI): + + acpi_gbl_original_mode = SYS_MODE_ACPI; + break; + + + case (SYS_MODE_LEGACY): + + acpi_gbl_original_mode = SYS_MODE_LEGACY; + break; + + + case (SYS_MODE_ACPI | SYS_MODE_LEGACY): + + if (acpi_hw_get_mode () == SYS_MODE_ACPI) { + acpi_gbl_original_mode = SYS_MODE_ACPI; + } + else { + acpi_gbl_original_mode = SYS_MODE_LEGACY; + } + + break; + } + + + if (acpi_gbl_system_flags & SYS_MODE_ACPI) { + /* Target system supports ACPI mode */ + + /* + * The purpose of this block of code is to save the initial state + * of the ACPI event enable registers. An exit function will be + * registered which will restore this state when the application + * exits. The exit function will also clear all of the ACPI event + * status bits prior to restoring the original mode. + * + * The location of the PM1a_evt_blk enable registers is defined as the + * base of PM1a_evt_blk + PM1a_evt_blk_length / 2. Since the spec further + * fully defines the PM1a_evt_blk to be a total of 4 bytes, the offset + * for the enable registers is always 2 from the base. It is hard + * coded here. If this changes in the spec, this code will need to + * be modified. The PM1b_evt_blk behaves as expected. + */ + + acpi_gbl_pm1_enable_register_save = + acpi_os_in16 ((acpi_gbl_FACP->pm1a_evt_blk + 2)); + if (acpi_gbl_FACP->pm1b_evt_blk) { + acpi_gbl_pm1_enable_register_save |= + acpi_os_in16 ((acpi_gbl_FACP->pm1b_evt_blk + 2)); + } + + + /* + * The GPEs behave similarly, except that the length of the register + * block is not fixed, so the buffer must be allocated with malloc + */ + + if (acpi_gbl_FACP->gpe0blk && acpi_gbl_FACP->gpe0blk_len) { + /* GPE0 specified in FACP */ + + acpi_gbl_gpe0enable_register_save = + acpi_cm_allocate (DIV_2 (acpi_gbl_FACP->gpe0blk_len)); + if (!acpi_gbl_gpe0enable_register_save) { + return (AE_NO_MEMORY); + } + + /* Save state of GPE0 enable bits */ + + for (index = 0; index < DIV_2 (acpi_gbl_FACP->gpe0blk_len); index++) { + acpi_gbl_gpe0enable_register_save[index] = + acpi_os_in8 (acpi_gbl_FACP->gpe0blk + + DIV_2 (acpi_gbl_FACP->gpe0blk_len)); + } + } + + else { + acpi_gbl_gpe0enable_register_save = NULL; + } + + if (acpi_gbl_FACP->gpe1_blk && acpi_gbl_FACP->gpe1_blk_len) { + /* GPE1 defined */ + + acpi_gbl_gpe1_enable_register_save = + acpi_cm_allocate (DIV_2 (acpi_gbl_FACP->gpe1_blk_len)); + if (!acpi_gbl_gpe1_enable_register_save) { + return (AE_NO_MEMORY); + } + + /* save state of GPE1 enable bits */ + + for (index = 0; index < DIV_2 (acpi_gbl_FACP->gpe1_blk_len); index++) { + acpi_gbl_gpe1_enable_register_save[index] = + acpi_os_in8 (acpi_gbl_FACP->gpe1_blk + + DIV_2 (acpi_gbl_FACP->gpe1_blk_len)); + } + } + + else { + acpi_gbl_gpe1_enable_register_save = NULL; + } + } + + return (status); +} + + +/****************************************************************************** + * * FUNCTION: Acpi_hw_set_mode * * PARAMETERS: Mode - SYS_MODE_ACPI or SYS_MODE_LEGACY @@ -78,8 +226,7 @@ /****************************************************************************** * - * FUNCTION: Acpi_hw - + * FUNCTION: Acpi_hw_get_mode * * PARAMETERS: none * diff -urN linux-2.4.0-test10/drivers/acpi/include/accommon.h linux-2.4.0-test10-lia/drivers/acpi/include/accommon.h --- linux-2.4.0-test10/drivers/acpi/include/accommon.h Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/include/accommon.h Fri Sep 15 16:38:45 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: accommon.h -- prototypes for the common (subsystem-wide) procedures - * $Revision: 74 $ + * $Revision: 76 $ * *****************************************************************************/ @@ -51,7 +51,7 @@ /* - * Acpi_cm_init - miscellaneous initialization and shutdown + * Cm_init - miscellaneous initialization and shutdown */ ACPI_STATUS @@ -62,8 +62,12 @@ acpi_cm_subsystem_shutdown ( void); +void +acpi_cm_validate_facp ( + void); + /* - * Acpi_cm_global - Global data structures and procedures + * Cm_global - Global data structures and procedures */ NATIVE_CHAR * @@ -84,7 +88,7 @@ /* - * Acpi_cm_clib - Local implementations of C library functions + * Cm_clib - Local implementations of C library functions */ NATIVE_UINT @@ -161,7 +165,7 @@ /* - * Acpi_cm_copy - Object construction and conversion interfaces + * Cm_copy - Object construction and conversion interfaces */ ACPI_STATUS @@ -204,7 +208,7 @@ /* - * Acpi_cm_create - Object creation + * Cm_create - Object creation */ ACPI_STATUS @@ -221,7 +225,7 @@ /* - * Acpi_cm_debug - Debug interfaces + * Cm_debug - Debug interfaces */ u32 @@ -341,7 +345,7 @@ /* - * Acpi_cm_delete - Object deletion + * Cm_delete - Object deletion */ void @@ -362,7 +366,7 @@ /* - * Acpi_cm_eval - object evaluation + * Cm_eval - object evaluation */ /* Method name strings */ @@ -399,7 +403,7 @@ /* - * Acpi_cm_error - exception interfaces + * Cm_error - exception interfaces */ NATIVE_CHAR * @@ -408,7 +412,7 @@ /* - * Acpi_cm_mutex - mutual exclusion interfaces + * Cm_mutex - mutual exclusion interfaces */ ACPI_STATUS @@ -437,7 +441,7 @@ /* - * Acpi_cm_object - internal object create/delete/cache routines + * Cm_object - internal object create/delete/cache routines */ void * @@ -459,7 +463,7 @@ /* - * Acpi_cm_ref_cnt - Object reference count management + * Cm_ref_cnt - Object reference count management */ void @@ -471,7 +475,7 @@ ACPI_OPERAND_OBJECT *object); /* - * Acpi_cm_size - Object size routines + * Cm_size - Object size routines */ ACPI_STATUS @@ -491,7 +495,7 @@ /* - * Acpi_cm_state - Generic state creation/cache routines + * Cm_state - Generic state creation/cache routines */ void @@ -536,7 +540,7 @@ void); /* - * Acpi_cmutils + * Cmutils */ u8 diff -urN linux-2.4.0-test10/drivers/acpi/include/acdebug.h linux-2.4.0-test10-lia/drivers/acpi/include/acdebug.h --- linux-2.4.0-test10/drivers/acpi/include/acdebug.h Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/include/acdebug.h Fri Sep 15 16:38:45 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acdebug.h - ACPI/AML debugger - * $Revision: 35 $ + * $Revision: 37 $ * *****************************************************************************/ @@ -205,6 +205,7 @@ void acpi_db_display_op ( + ACPI_WALK_STATE *walk_state, ACPI_PARSE_OBJECT *origin, u32 num_opcodes); @@ -218,7 +219,12 @@ void acpi_db_display_opcode ( + ACPI_WALK_STATE *walk_state, ACPI_PARSE_OBJECT *op); + +void +acpi_db_decode_internal_object ( + ACPI_OPERAND_OBJECT *obj_desc); /* diff -urN linux-2.4.0-test10/drivers/acpi/include/acdispat.h linux-2.4.0-test10-lia/drivers/acpi/include/acdispat.h --- linux-2.4.0-test10/drivers/acpi/include/acdispat.h Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/include/acdispat.h Fri Sep 15 16:38:45 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acdispat.h - dispatcher (parser to interpreter interface) - * $Revision: 29 $ + * $Revision: 30 $ * *****************************************************************************/ @@ -61,7 +61,11 @@ ACPI_WALK_STATE *walk_state); -/* dsregion - Op region support */ +/* dsopcode - support for late evaluation */ + +ACPI_STATUS +acpi_ds_get_field_unit_arguments ( + ACPI_OPERAND_OBJECT *obj_desc); ACPI_STATUS acpi_ds_get_region_arguments ( @@ -145,6 +149,18 @@ ACPI_WALK_STATE *state, ACPI_PARSE_OBJECT *op); +ACPI_STATUS +acpi_ds_load3_begin_op ( + u16 opcode, + ACPI_PARSE_OBJECT *op, + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT **out_op); + +ACPI_STATUS +acpi_ds_load3_end_op ( + ACPI_WALK_STATE *state, + ACPI_PARSE_OBJECT *op); + /* dsmthdat - method data (locals/args) */ @@ -282,6 +298,11 @@ /* dsregn - Parser/Interpreter interface - Op Region parsing */ + +ACPI_STATUS +acpi_ds_eval_field_unit_operands ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op); ACPI_STATUS acpi_ds_eval_region_operands ( diff -urN linux-2.4.0-test10/drivers/acpi/include/acenv.h linux-2.4.0-test10-lia/drivers/acpi/include/acenv.h --- linux-2.4.0-test10/drivers/acpi/include/acenv.h Fri Sep 15 21:37:23 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/include/acenv.h Thu Oct 26 18:50:20 2000 @@ -71,6 +71,7 @@ #ifdef _LINUX +#include #include #include #include @@ -247,8 +248,7 @@ #define halt() ia64_pal_halt_light() /* PAL_HALT */ -#define safe_halt() ia64_pal_halt(1) - +#define safe_halt() ia64_pal_halt_light() #define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \ do { \ __asm__ volatile ("1: ld4 r29=%1\n" \ @@ -271,7 +271,7 @@ ";;\n" \ "(p8) mov %0=-1\n" \ "(p9) mov %0=r0\n" \ - :"=r"(Acq):"m" __atomic_fool_gcc((GLptr)):"r2","r29","r30","memory"); \ + :"=r"(Acq):"m"(GLptr):"r2","r29","r30","memory"); \ } while (0) #define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \ @@ -288,7 +288,7 @@ "(p7) br.dpnt.few 1b\n" \ "and %0=1,r2\n" \ ";;\n" \ - :"=r"(Acq):"m" __atomic_fool_gcc((GLptr)):"r2","r29","r30","memory"); \ + :"=r"(Acq):"m"(GLptr):"r2","r29","r30","memory"); \ } while (0) /*! [End] no source code translation !*/ diff -urN linux-2.4.0-test10/drivers/acpi/include/acevents.h linux-2.4.0-test10-lia/drivers/acpi/include/acevents.h --- linux-2.4.0-test10/drivers/acpi/include/acevents.h Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/include/acevents.h Fri Sep 15 16:38:45 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acevents.h - Event subcomponent prototypes and defines - * $Revision: 56 $ + * $Revision: 58 $ * *****************************************************************************/ @@ -25,6 +25,11 @@ #ifndef __ACEVENTS_H__ #define __ACEVENTS_H__ + + +ACPI_STATUS +acpi_ev_initialize ( + void); /* diff -urN linux-2.4.0-test10/drivers/acpi/include/achware.h linux-2.4.0-test10-lia/drivers/acpi/include/achware.h --- linux-2.4.0-test10/drivers/acpi/include/achware.h Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/include/achware.h Fri Sep 15 16:38:45 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: achware.h -- hardware specific interfaces - * $Revision: 41 $ + * $Revision: 42 $ * *****************************************************************************/ @@ -31,15 +31,15 @@ ACPI_STATUS -acpi_hw_initialize( +acpi_hw_initialize ( void); ACPI_STATUS -acpi_hw_shutdown( +acpi_hw_shutdown ( void); ACPI_STATUS -acpi_hw_initialize_system_info( +acpi_hw_initialize_system_info ( void); ACPI_STATUS diff -urN linux-2.4.0-test10/drivers/acpi/include/acinterp.h linux-2.4.0-test10-lia/drivers/acpi/include/acinterp.h --- linux-2.4.0-test10/drivers/acpi/include/acinterp.h Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/include/acinterp.h Fri Sep 22 21:06:47 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acinterp.h - Interpreter subcomponent prototypes and defines - * $Revision: 79 $ + * $Revision: 80 $ * *****************************************************************************/ @@ -120,7 +120,9 @@ ACPI_STATUS acpi_aml_exec_create_field ( - u16 opcode, + u8 *aml_ptr, + u32 aml_length, + ACPI_NAMESPACE_NODE *node, ACPI_WALK_STATE *walk_state); ACPI_STATUS diff -urN linux-2.4.0-test10/drivers/acpi/include/aclocal.h linux-2.4.0-test10-lia/drivers/acpi/include/aclocal.h --- linux-2.4.0-test10/drivers/acpi/include/aclocal.h Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/include/aclocal.h Fri Sep 15 16:38:45 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: aclocal.h - Internal data types used across the ACPI subsystem - * $Revision: 77 $ + * $Revision: 81 $ * *****************************************************************************/ @@ -125,7 +125,7 @@ /* TBD: [Restructure] get rid of the need for this! */ -#define TABLE_ID_DSDT (ACPI_OWNER_ID) 0xD1D1 +#define TABLE_ID_DSDT (ACPI_OWNER_ID) 0x8000 /***************************************************************************** * @@ -157,8 +157,8 @@ { u8 data_type; u8 type; /* Type associated with this name */ - u32 name; /* ACPI Name, always 4 chars per ACPI spec */ u16 owner_id; + u32 name; /* ACPI Name, always 4 chars per ACPI spec */ void *object; /* Pointer to attached ACPI object (optional) */ @@ -543,8 +543,9 @@ #define NEXT_OP_DOWNWARD 1 #define NEXT_OP_UPWARD 2 -#define WALK_METHOD 1 #define WALK_NON_METHOD 0 +#define WALK_METHOD 1 +#define WALK_METHOD_RESTART 2 typedef struct acpi_walk_state { @@ -607,13 +608,32 @@ /* Info used by Acpi_ps_init_objects */ -typedef struct init_walk_info +typedef struct acpi_init_walk_info { - u32 method_count; - u32 op_region_count; + u16 method_count; + u16 op_region_count; + u16 field_count; + u16 op_region_init; + u16 field_init; + u16 object_count; ACPI_TABLE_DESC *table_desc; -} INIT_WALK_INFO; +} ACPI_INIT_WALK_INFO; + + +/* Info used by TBD */ + +typedef struct acpi_device_walk_info +{ + u32 flags; + u16 device_count; + u16 num_STA; + u16 num_INI; + u16 num_HID; + u16 num_PCI; + ACPI_TABLE_DESC *table_desc; + +} ACPI_DEVICE_WALK_INFO; /* TBD: [Restructure] Merge with struct above */ @@ -633,16 +653,22 @@ ****************************************************************************/ +/* PCI */ + +#define PCI_ROOT_HID_STRING "PNP0A03" +#define PCI_ROOT_HID_VALUE 0x030AD041 /* EISAID("PNP0A03") */ + + /* Sleep states */ -#define SLWA_DEBUG_LEVEL 4 -#define GTS_CALL 0 -#define GTS_WAKE 1 +#define SLWA_DEBUG_LEVEL 4 +#define GTS_CALL 0 +#define GTS_WAKE 1 /* Cx States */ -#define MAX_CX_STATE_LATENCY 0xFFFFFFFF -#define MAX_CX_STATES 4 +#define MAX_CX_STATE_LATENCY 0xFFFFFFFF +#define MAX_CX_STATES 4 /* * The #define's and enum below establish an abstract way of identifying what @@ -650,17 +676,17 @@ * values as they are used in switch statements and offset calculations. */ -#define REGISTER_BLOCK_MASK 0xFF00 -#define BIT_IN_REGISTER_MASK 0x00FF -#define PM1_EVT 0x0100 -#define PM1_CONTROL 0x0200 -#define PM2_CONTROL 0x0300 -#define PM_TIMER 0x0400 -#define PROCESSOR_BLOCK 0x0500 -#define GPE0_STS_BLOCK 0x0600 -#define GPE0_EN_BLOCK 0x0700 -#define GPE1_STS_BLOCK 0x0800 -#define GPE1_EN_BLOCK 0x0900 +#define REGISTER_BLOCK_MASK 0xFF00 +#define BIT_IN_REGISTER_MASK 0x00FF +#define PM1_EVT 0x0100 +#define PM1_CONTROL 0x0200 +#define PM2_CONTROL 0x0300 +#define PM_TIMER 0x0400 +#define PROCESSOR_BLOCK 0x0500 +#define GPE0_STS_BLOCK 0x0600 +#define GPE0_EN_BLOCK 0x0700 +#define GPE1_STS_BLOCK 0x0800 +#define GPE1_EN_BLOCK 0x0900 enum { diff -urN linux-2.4.0-test10/drivers/acpi/include/acmacros.h linux-2.4.0-test10-lia/drivers/acpi/include/acmacros.h --- linux-2.4.0-test10/drivers/acpi/include/acmacros.h Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/include/acmacros.h Fri Sep 15 16:38:45 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acmacros.h - C macros for the entire subsystem. - * $Revision: 48 $ + * $Revision: 49 $ * *****************************************************************************/ @@ -142,6 +142,7 @@ #define ROUND_UP_TO_32_bITS(a) ROUND_UP(a,4) #define ROUND_UP_TO_NATIVE_WORD(a) ROUND_UP(a,ALIGNED_ADDRESS_BOUNDARY) +#define ROUND_PTR_UP_TO_4(a,b) ((b *)(((NATIVE_UINT)(a) + 3) & ~3)) #ifdef DEBUG_ASSERT #undef DEBUG_ASSERT diff -urN linux-2.4.0-test10/drivers/acpi/include/acnamesp.h linux-2.4.0-test10-lia/drivers/acpi/include/acnamesp.h --- linux-2.4.0-test10/drivers/acpi/include/acnamesp.h Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/include/acnamesp.h Fri Sep 15 16:38:45 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acnamesp.h - Namespace subcomponent prototypes and defines - * $Revision: 94 $ + * $Revision: 97 $ * *****************************************************************************/ @@ -62,6 +62,36 @@ ACPI_STATUS +acpi_ns_load_namespace ( + void); + +ACPI_STATUS +acpi_ns_initialize_objects ( + void); + +ACPI_STATUS +acpi_ns_initialize_devices ( + u32 flags); + + +/* Namespace init - nsxfinit */ + +ACPI_STATUS +acpi_ns_init_one_device ( + ACPI_HANDLE obj_handle, + u32 nesting_level, + void *context, + void **return_value); + +ACPI_STATUS +acpi_ns_init_one_object ( + ACPI_HANDLE obj_handle, + u32 level, + void *context, + void **return_value); + + +ACPI_STATUS acpi_ns_walk_namespace ( OBJECT_TYPE_INTERNAL type, ACPI_HANDLE start_object, @@ -85,6 +115,11 @@ /* Namespace loading - nsload */ + +ACPI_STATUS +acpi_ns_one_complete_parse ( + u32 pass_number, + ACPI_TABLE_DESC *table_desc); ACPI_STATUS acpi_ns_parse_table ( diff -urN linux-2.4.0-test10/drivers/acpi/include/acobject.h linux-2.4.0-test10-lia/drivers/acpi/include/acobject.h --- linux-2.4.0-test10/drivers/acpi/include/acobject.h Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/include/acobject.h Fri Sep 15 16:38:45 2000 @@ -2,7 +2,7 @@ /****************************************************************************** * * Name: acobject.h - Definition of ACPI_OPERAND_OBJECT (Internal object only) - * $Revision: 71 $ + * $Revision: 73 $ * *****************************************************************************/ @@ -58,7 +58,7 @@ */ -#define ACPI_OBJECT_COMMON_HEADER /* Two 32-bit fields, one pointer, 8-bit flag */\ +#define ACPI_OBJECT_COMMON_HEADER /* 32-bits plus 8-bit flag */\ u8 data_type; /* To differentiate various internal objs */\ u8 type; /* ACPI_OBJECT_TYPE */\ u16 reference_count; /* For object deletion management */\ @@ -74,7 +74,7 @@ /* * Common bitfield for the field objects */ -#define ACPI_COMMON_FIELD_INFO /* Three 32-bit values */\ +#define ACPI_COMMON_FIELD_INFO /* Three 32-bit values plus 8*/\ u8 granularity;\ u16 length; \ u32 offset; /* Byte offset within containing object */\ @@ -155,8 +155,9 @@ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO - u32 sequence; /* Container's sequence number */ + union acpi_operand_obj *extra; /* Pointer to executable AML (in field definition) */ + ACPI_NAMESPACE_NODE *node; /* containing object */ union acpi_operand_obj *container; /* Containing object (Buffer) */ } ACPI_OBJECT_FIELD_UNIT; @@ -219,15 +220,9 @@ u8 space_id; u32 length; u32 address; - void *region_context; /* Region Specific data (Handler->Context - optional things like PCI _ADR) */ - - /* TBD: [Restructure] This field can go away when Pass3 is implemented */ - union acpi_operand_obj *method; /* Associated control method */ - + union acpi_operand_obj *extra; /* Pointer to executable AML (in region definition) */ union acpi_operand_obj *addr_handler; /* Handler for system notifies */ - ACPI_NAMESPACE_NODE *REGmethod; /* _REG method for this region (if any) */ ACPI_NAMESPACE_NODE *node; /* containing object */ union acpi_operand_obj *next; @@ -372,6 +367,27 @@ } ACPI_OBJECT_REFERENCE; +/* + * Extra object is used as additional storage for types that + * have AML code in their declarations (Term_args) that must be + * evaluated at run time. + * + * Currently: Region and Field_unit types + */ + +typedef struct /* EXTRA */ +{ + ACPI_OBJECT_COMMON_HEADER + u8 byte_fill1; + u16 word_fill1; + u32 pcode_length; + u8 *pcode; + ACPI_NAMESPACE_NODE *method_REG; /* _REG method for this region (if any) */ + void *region_context; /* Region-specific data */ + +} ACPI_OBJECT_EXTRA; + + /****************************************************************************** * * ACPI_OPERAND_OBJECT Descriptor - a giant union of all of the above @@ -401,6 +417,7 @@ ACPI_OBJECT_REFERENCE reference; ACPI_OBJECT_NOTIFY_HANDLER notify_handler; ACPI_OBJECT_ADDR_HANDLER addr_handler; + ACPI_OBJECT_EXTRA extra; } ACPI_OPERAND_OBJECT; diff -urN linux-2.4.0-test10/drivers/acpi/include/acoutput.h linux-2.4.0-test10-lia/drivers/acpi/include/acoutput.h --- linux-2.4.0-test10/drivers/acpi/include/acoutput.h Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/include/acoutput.h Fri Sep 15 16:38:45 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acoutput.h -- debug output - * $Revision: 63 $ + * $Revision: 64 $ * *****************************************************************************/ @@ -59,6 +59,8 @@ #define DEBUGGER 0x00100000 #define ALL_COMPONENTS 0x001FFFFF + +#define COMPONENT_DEFAULT (ALL_COMPONENTS) /* Exception level -- used in the global "Debug_level" */ diff -urN linux-2.4.0-test10/drivers/acpi/include/acparser.h linux-2.4.0-test10-lia/drivers/acpi/include/acparser.h --- linux-2.4.0-test10/drivers/acpi/include/acparser.h Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/include/acparser.h Fri Sep 15 16:38:45 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: acparser.h - AML Parser subcomponent prototypes and defines - * $Revision: 46 $ + * $Revision: 47 $ * *****************************************************************************/ @@ -188,7 +188,8 @@ acpi_ps_pop_scope ( ACPI_PARSE_STATE *parser_state, ACPI_PARSE_OBJECT **op, - u32 *arg_list); + u32 *arg_list, + u32 *arg_count); ACPI_STATUS acpi_ps_push_scope ( diff -urN linux-2.4.0-test10/drivers/acpi/include/acpixf.h linux-2.4.0-test10-lia/drivers/acpi/include/acpixf.h --- linux-2.4.0-test10/drivers/acpi/include/acpixf.h Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/include/acpixf.h Fri Sep 15 16:38:45 2000 @@ -35,10 +35,14 @@ */ ACPI_STATUS -acpi_initialize ( +acpi_initialize_subsystem ( ACPI_INIT_DATA *init_data); ACPI_STATUS +acpi_enable_subsystem ( + u32 flags); + +ACPI_STATUS acpi_terminate ( void); @@ -92,10 +96,6 @@ /* * Namespace and name interfaces */ - -ACPI_STATUS -acpi_load_namespace ( - void); ACPI_STATUS acpi_walk_namespace ( diff -urN linux-2.4.0-test10/drivers/acpi/include/actables.h linux-2.4.0-test10-lia/drivers/acpi/include/actables.h --- linux-2.4.0-test10/drivers/acpi/include/actables.h Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/include/actables.h Fri Sep 15 16:38:45 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: actables.h - ACPI table management - * $Revision: 20 $ + * $Revision: 21 $ * *****************************************************************************/ @@ -107,8 +107,12 @@ acpi_tb_delete_acpi_table ( ACPI_TABLE_TYPE type); -ACPI_TABLE_DESC * +void acpi_tb_delete_single_table ( + ACPI_TABLE_DESC *table_desc); + +ACPI_TABLE_DESC * +acpi_tb_uninstall_table ( ACPI_TABLE_DESC *table_desc); void diff -urN linux-2.4.0-test10/drivers/acpi/include/actbl.h linux-2.4.0-test10-lia/drivers/acpi/include/actbl.h --- linux-2.4.0-test10/drivers/acpi/include/actbl.h Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/include/actbl.h Mon Sep 18 20:48:22 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: actbl.h - Table data structures defined in ACPI specification - * $Revision: 34 $ + * $Revision: 35 $ * *****************************************************************************/ @@ -40,6 +40,7 @@ #define RSDT_SIG "RSDT" /* Root System Description Table */ #define SSDT_SIG "SSDT" /* Secondary System Description Table */ #define SBST_SIG "SBST" /* Smart Battery Specification Table */ +#define SPIC_SIG "SPIC" /* iosapic table */ #define BOOT_SIG "BOOT" /* Boot table */ @@ -180,7 +181,7 @@ * Get the architecture-specific tables */ -#ifdef IA64 +#ifdef _IA64 #include "actbl64.h" #else #include "actbl32.h" diff -urN linux-2.4.0-test10/drivers/acpi/include/actypes.h linux-2.4.0-test10-lia/drivers/acpi/include/actypes.h --- linux-2.4.0-test10/drivers/acpi/include/actypes.h Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/include/actypes.h Fri Sep 22 21:14:07 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: actypes.h - Common data types for the entire ACPI subsystem - * $Revision: 131 $ + * $Revision: 135 $ * *****************************************************************************/ @@ -183,6 +183,15 @@ #define ACPI_ROOT_OBJECT (ACPI_HANDLE)(-1) +#define ACPI_FULL_INITIALIZATION 0x00 +#define ACPI_NO_ADDRESS_SPACE_INIT 0x01 +#define ACPI_NO_HARDWARE_INIT 0x02 +#define ACPI_NO_EVENT_INIT 0x04 +#define ACPI_NO_ACPI_ENABLE 0x08 +#define ACPI_NO_DEVICE_INIT 0x10 +#define ACPI_NO_PCI_INIT 0x20 +#define ACPI_NO_OBJECT_INIT 0x40 + /* * Sleep state constants @@ -212,9 +221,10 @@ #define ACPI_TABLE_RSDT (ACPI_TABLE_TYPE) 6 #define ACPI_TABLE_SSDT (ACPI_TABLE_TYPE) 7 #define ACPI_TABLE_SBST (ACPI_TABLE_TYPE) 8 -#define ACPI_TABLE_BOOT (ACPI_TABLE_TYPE) 9 -#define ACPI_TABLE_MAX 9 -#define NUM_ACPI_TABLES 10 +#define ACPI_TABLE_SPIC (ACPI_TABLE_TYPE) 9 +#define ACPI_TABLE_BOOT (ACPI_TABLE_TYPE) 10 +#define ACPI_TABLE_MAX 10 +#define NUM_ACPI_TABLES (ACPI_TABLE_MAX+1) /* @@ -281,10 +291,11 @@ #define INTERNAL_TYPE_DEF_ANY 31 /* 0x1F type is Any, suppress search of enclosing scopes */ #define INTERNAL_TYPE_METHOD_ARGUMENT 32 /* 0x20 */ #define INTERNAL_TYPE_METHOD_LOCAL_VAR 33 /* 0x21 */ +#define INTERNAL_TYPE_EXTRA 34 /* 0x22 */ -#define INTERNAL_TYPE_MAX 33 +#define INTERNAL_TYPE_MAX 34 -#define INTERNAL_TYPE_INVALID 34 +#define INTERNAL_TYPE_INVALID 35 #define ACPI_TYPE_NOT_FOUND 0xFF /* diff -urN linux-2.4.0-test10/drivers/acpi/interpreter/amconfig.c linux-2.4.0-test10-lia/drivers/acpi/interpreter/amconfig.c --- linux-2.4.0-test10/drivers/acpi/interpreter/amconfig.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/interpreter/amconfig.c Fri Sep 15 16:38:45 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: amconfig - Namespace reconfiguration (Load/Unload opcodes) - * $Revision: 23 $ + * $Revision: 24 $ * *****************************************************************************/ @@ -139,12 +139,17 @@ /* Add the table to the namespace */ - status = acpi_load_namespace (); - if (ACPI_FAILURE (status)) { + /* TBD: [Restructure] - change to whatever new interface is appropriate */ +/* + Status = Acpi_load_namespace (); + if (ACPI_FAILURE (Status)) { +*/ /* TBD: [Errors] Unload the table on failure ? */ - - goto cleanup; +/* + goto Cleanup; } +*/ + /* TBD: [Investigate] we need a pointer to the table desc */ @@ -219,7 +224,7 @@ /* Delete the table itself */ - acpi_tb_delete_single_table (table_info->installed_desc); + acpi_tb_uninstall_table (table_info->installed_desc); /* Delete the table descriptor (Ddb_handle) */ diff -urN linux-2.4.0-test10/drivers/acpi/interpreter/amcreate.c linux-2.4.0-test10-lia/drivers/acpi/interpreter/amcreate.c --- linux-2.4.0-test10/drivers/acpi/interpreter/amcreate.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/interpreter/amcreate.c Fri Sep 15 16:38:45 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: amcreate - Named object creation - * $Revision: 44 $ + * $Revision: 46 $ * *****************************************************************************/ @@ -66,8 +66,144 @@ * ******************************************************************************/ + ACPI_STATUS acpi_aml_exec_create_field ( + u8 *aml_ptr, + u32 aml_length, + ACPI_NAMESPACE_NODE *node, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_OPERAND_OBJECT *tmp_desc; + + + /* Create the region descriptor */ + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_FIELD_UNIT); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Construct the field object */ + + obj_desc->field_unit.access = (u8) ACCESS_ANY_ACC; + obj_desc->field_unit.lock_rule = (u8) GLOCK_NEVER_LOCK; + obj_desc->field_unit.update_rule = (u8) UPDATE_PRESERVE; + + /* + * Allocate a method object for this field unit + */ + + obj_desc->field_unit.extra = acpi_cm_create_internal_object ( + INTERNAL_TYPE_EXTRA); + if (!obj_desc->field_unit.extra) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* + * Remember location in AML stream of the field unit + * opcode and operands -- since the buffer and index + * operands must be evaluated. + */ + + obj_desc->field_unit.extra->extra.pcode = aml_ptr; + obj_desc->field_unit.extra->extra.pcode_length = aml_length; + obj_desc->field_unit.node = node; + + +/* + Status = Acpi_ns_attach_object (Node, Obj_desc, + (u8) ACPI_TYPE_FIELD_UNIT); + + if (ACPI_FAILURE (Status)) { + goto Cleanup; + } +*/ + + /* + * This operation is supposed to cause the destination Name to refer + * to the defined Field_unit -- it must not store the constructed + * Field_unit object (or its current value) in some location that the + * Name may already be pointing to. So, if the Name currently contains + * a reference which would cause Acpi_aml_exec_store() to perform an indirect + * store rather than setting the value of the Name itself, clobber that + * reference before calling Acpi_aml_exec_store(). + */ + + /* Type of Name's existing value */ + + switch (acpi_ns_get_type (node)) + { + + case ACPI_TYPE_FIELD_UNIT: + + case INTERNAL_TYPE_ALIAS: + case INTERNAL_TYPE_BANK_FIELD: + case INTERNAL_TYPE_DEF_FIELD: + case INTERNAL_TYPE_INDEX_FIELD: + + tmp_desc = acpi_ns_get_attached_object (node); + if (tmp_desc) { + /* + * There is an existing object here; delete it and zero out the + * object field within the Node + */ + + acpi_cm_remove_reference (tmp_desc); + acpi_ns_attach_object ((ACPI_NAMESPACE_NODE *) node, NULL, + ACPI_TYPE_ANY); + } + + /* Set the type to ANY (or the store below will fail) */ + + ((ACPI_NAMESPACE_NODE *) node)->type = ACPI_TYPE_ANY; + + break; + + + default: + + break; + } + + + /* Store constructed field descriptor in result location */ + + status = acpi_aml_exec_store (obj_desc, (ACPI_OPERAND_OBJECT *) node, walk_state); + + /* + * If the field descriptor was not physically stored (or if a failure + * above), we must delete it + */ + if (obj_desc->common.reference_count <= 1) { + acpi_cm_remove_reference (obj_desc); + } + + + return (AE_OK); + + +cleanup: + + /* Delete region object and method subobject */ + + if (obj_desc) { + /* Remove deletes both objects! */ + + acpi_cm_remove_reference (obj_desc); + obj_desc = NULL; + } + + return (status); +} + + +ACPI_STATUS +acpi_aml_exec_create_field_original ( u16 opcode, ACPI_WALK_STATE *walk_state) { @@ -227,7 +363,6 @@ field_desc->field_unit.bit_offset = (u8) (bit_offset % 8); field_desc->field_unit.offset = DIV_8 (bit_offset); field_desc->field_unit.container = src_desc; - field_desc->field_unit.sequence = src_desc->buffer.sequence; /* An additional reference for Src_desc */ @@ -547,7 +682,7 @@ ACPI_WALK_STATE *walk_state) { ACPI_STATUS status; - ACPI_OPERAND_OBJECT *obj_desc_region; + ACPI_OPERAND_OBJECT *obj_desc; ACPI_NAMESPACE_NODE *node; @@ -571,8 +706,8 @@ /* Create the region descriptor */ - obj_desc_region = acpi_cm_create_internal_object (ACPI_TYPE_REGION); - if (!obj_desc_region) { + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_REGION); + if (!obj_desc) { status = AE_NO_MEMORY; goto cleanup; } @@ -580,32 +715,34 @@ /* * Allocate a method object for this region. */ - obj_desc_region->region.method = acpi_cm_create_internal_object ( - ACPI_TYPE_METHOD); - if (!obj_desc_region->region.method) { + + obj_desc->region.extra = acpi_cm_create_internal_object ( + INTERNAL_TYPE_EXTRA); + if (!obj_desc->region.extra) { status = AE_NO_MEMORY; goto cleanup; } - /* Init the region from the operands */ - - obj_desc_region->region.space_id = (u8) region_space; - obj_desc_region->region.address = 0; - obj_desc_region->region.length = 0; - /* * Remember location in AML stream of address & length * operands since they need to be evaluated at run time. */ - obj_desc_region->region.method->method.pcode = aml_ptr; - obj_desc_region->region.method->method.pcode_length = aml_length; + + obj_desc->region.extra->extra.pcode = aml_ptr; + obj_desc->region.extra->extra.pcode_length = aml_length; + + /* Init the region from the operands */ + + obj_desc->region.space_id = (u8) region_space; + obj_desc->region.address = 0; + obj_desc->region.length = 0; /* Install the new region object in the parent Node */ - obj_desc_region->region.node = node; + obj_desc->region.node = node; - status = acpi_ns_attach_object (node, obj_desc_region, + status = acpi_ns_attach_object (node, obj_desc, (u8) ACPI_TYPE_REGION); if (ACPI_FAILURE (status)) { @@ -617,7 +754,7 @@ * Namespace is NOT locked at this point. */ - status = acpi_ev_initialize_region (obj_desc_region, FALSE); + status = acpi_ev_initialize_region (obj_desc, FALSE); if (ACPI_FAILURE (status)) { /* @@ -635,11 +772,11 @@ if (ACPI_FAILURE (status)) { /* Delete region object and method subobject */ - if (obj_desc_region) { + if (obj_desc) { /* Remove deletes both objects! */ - acpi_cm_remove_reference (obj_desc_region); - obj_desc_region = NULL; + acpi_cm_remove_reference (obj_desc); + obj_desc = NULL; } } diff -urN linux-2.4.0-test10/drivers/acpi/interpreter/amdump.c linux-2.4.0-test10-lia/drivers/acpi/interpreter/amdump.c --- linux-2.4.0-test10/drivers/acpi/interpreter/amdump.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/interpreter/amdump.c Fri Sep 15 16:38:45 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: amdump - Interpreter debug output routines - * $Revision: 90 $ + * $Revision: 91 $ * *****************************************************************************/ diff -urN linux-2.4.0-test10/drivers/acpi/interpreter/amfield.c linux-2.4.0-test10-lia/drivers/acpi/interpreter/amfield.c --- linux-2.4.0-test10/drivers/acpi/interpreter/amfield.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/interpreter/amfield.c Fri Sep 15 16:38:45 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: amfield - ACPI AML (p-code) execution - field manipulation - * $Revision: 70 $ + * $Revision: 71 $ * *****************************************************************************/ @@ -105,7 +105,7 @@ /* - * If the address and length have not been previously evaluated, + * If the Region Address and Length have not been previously evaluated, * evaluate them and save the results. */ if (!(rgn_desc->region.flags & AOPOBJ_DATA_VALID)) { @@ -114,6 +114,16 @@ if (ACPI_FAILURE (status)) { return (status); } + } + + + if ((obj_desc->common.type == ACPI_TYPE_FIELD_UNIT) && + (!(obj_desc->common.flags & AOPOBJ_DATA_VALID))) + { + /* + * Field Buffer and Index have not been previously evaluated, + */ + return (AE_AML_INTERNAL); } if (rgn_desc->region.length < diff -urN linux-2.4.0-test10/drivers/acpi/interpreter/ammisc.c linux-2.4.0-test10-lia/drivers/acpi/interpreter/ammisc.c --- linux-2.4.0-test10/drivers/acpi/interpreter/ammisc.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/interpreter/ammisc.c Fri Sep 15 16:38:45 2000 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: ammisc - ACPI AML (p-code) execution - specific opcodes - * $Revision: 67 $ + * $Revision: 68 $ * *****************************************************************************/ @@ -100,6 +100,7 @@ /* If we get back from the OS call, we might as well keep going. */ + REPORT_WARNING ("An AML Fatal_op was executed"); return (AE_OK); } diff -urN linux-2.4.0-test10/drivers/acpi/interpreter/amregion.c linux-2.4.0-test10-lia/drivers/acpi/interpreter/amregion.c --- linux-2.4.0-test10/drivers/acpi/interpreter/amregion.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/interpreter/amregion.c Fri Sep 22 21:18:02 2000 @@ -98,9 +98,9 @@ * 2) Address beyond the current mapping? */ - if (((u8 *) address < mem_info->mapped_physical_address) || - (((u8 *) address + length) > - (mem_info->mapped_physical_address + mem_info->mapped_length))) + if ((address < (NATIVE_UINT)mem_info->mapped_physical_address) || + ((address + length) > + ((NATIVE_UINT)mem_info->mapped_physical_address + mem_info->mapped_length))) { /* * The request cannot be resolved by the current memory mapping; @@ -118,13 +118,13 @@ /* Create a new mapping starting at the address given */ - status = acpi_os_map_memory ((void *) address, SYSMEM_REGION_WINDOW_SIZE, + status = acpi_os_map_memory ((void *)(NATIVE_UINT) address, SYSMEM_REGION_WINDOW_SIZE, (void **) &mem_info->mapped_logical_address); if (ACPI_FAILURE (status)) { return (status); } - mem_info->mapped_physical_address = (u8 *) address; + mem_info->mapped_physical_address = (u8 *)(NATIVE_UINT) address; mem_info->mapped_length = SYSMEM_REGION_WINDOW_SIZE; } @@ -135,7 +135,7 @@ */ logical_addr_ptr = mem_info->mapped_logical_address + - ((u8 *) address - mem_info->mapped_physical_address); + ((u8 *)(NATIVE_UINT) address - mem_info->mapped_physical_address); /* Perform the memory read or write */ diff -urN linux-2.4.0-test10/drivers/acpi/interpreter/amresolv.c linux-2.4.0-test10-lia/drivers/acpi/interpreter/amresolv.c --- linux-2.4.0-test10/drivers/acpi/interpreter/amresolv.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/interpreter/amresolv.c Fri Sep 15 16:38:46 2000 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: amresolv - AML Interpreter object resolution - * $Revision: 74 $ + * $Revision: 75 $ * *****************************************************************************/ @@ -69,18 +69,19 @@ status = AE_AML_NO_OPERAND; } - else if (!field_desc->field_unit.container) { + if (!(field_desc->common.flags & AOPOBJ_DATA_VALID)) { + status = acpi_ds_get_field_unit_arguments (field_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + if (!field_desc->field_unit.container) { status = AE_AML_INTERNAL; } else if (ACPI_TYPE_BUFFER != field_desc->field_unit.container->common.type) { status = AE_AML_OPERAND_TYPE; - } - - else if (field_desc->field_unit.sequence - != field_desc->field_unit.container->buffer.sequence) - { - status = AE_AML_INTERNAL; } else if (!result_desc) { diff -urN linux-2.4.0-test10/drivers/acpi/interpreter/amstoren.c linux-2.4.0-test10-lia/drivers/acpi/interpreter/amstoren.c --- linux-2.4.0-test10/drivers/acpi/interpreter/amstoren.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/interpreter/amstoren.c Fri Sep 15 16:38:46 2000 @@ -3,7 +3,7 @@ * * Module Name: amstoren - AML Interpreter object store support, * Store to Node (namespace object) - * $Revision: 21 $ + * $Revision: 22 $ * *****************************************************************************/ @@ -430,10 +430,20 @@ case ACPI_TYPE_FIELD_UNIT: + + /* + * If the Field Buffer and Index have not been previously evaluated, + * evaluate them and save the results. + */ + if (!(dest_desc->common.flags & AOPOBJ_DATA_VALID)) { + status = acpi_ds_get_field_unit_arguments (dest_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + } + if ((!dest_desc->field_unit.container || - ACPI_TYPE_BUFFER != dest_desc->field_unit.container->common.type || - dest_desc->field_unit.sequence != - dest_desc->field_unit.container->buffer.sequence)) + ACPI_TYPE_BUFFER != dest_desc->field_unit.container->common.type)) { status = AE_AML_INTERNAL; goto clean_up_and_bail_out; diff -urN linux-2.4.0-test10/drivers/acpi/namespace/nsaccess.c linux-2.4.0-test10-lia/drivers/acpi/namespace/nsaccess.c --- linux-2.4.0-test10/drivers/acpi/namespace/nsaccess.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/namespace/nsaccess.c Fri Sep 15 16:38:46 2000 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: nsaccess - Top-level functions for accessing ACPI namespace - * $Revision: 108 $ + * $Revision: 109 $ * ******************************************************************************/ @@ -467,21 +467,23 @@ * If 1) This is the last segment (Num_segments == 0) * 2) and looking for a specific type * (Not checking for TYPE_ANY) - * 3) which is not a local type (TYPE_DEF_ANY) - * 4) which is not a local type (TYPE_SCOPE) - * 5) which is not a local type (TYPE_INDEX_FIELD_DEFN) - * 6) and type of object is known (not TYPE_ANY) - * 7) and object does not match request + * 3) Which is not an alias + * 4) which is not a local type (TYPE_DEF_ANY) + * 5) which is not a local type (TYPE_SCOPE) + * 6) which is not a local type (TYPE_INDEX_FIELD_DEFN) + * 7) and type of object is known (not TYPE_ANY) + * 8) and object does not match request * * Then we have a type mismatch. Just warn and ignore it. */ if ((num_segments == 0) && (type_to_check_for != ACPI_TYPE_ANY) && + (type_to_check_for != INTERNAL_TYPE_ALIAS) && (type_to_check_for != INTERNAL_TYPE_DEF_ANY) && (type_to_check_for != INTERNAL_TYPE_SCOPE) && (type_to_check_for != INTERNAL_TYPE_INDEX_FIELD_DEFN) && - (this_node->type != ACPI_TYPE_ANY) && - (this_node->type != type_to_check_for)) + (this_node->type != ACPI_TYPE_ANY) && + (this_node->type != type_to_check_for)) { /* Complain about a type mismatch */ diff -urN linux-2.4.0-test10/drivers/acpi/namespace/nseval.c linux-2.4.0-test10-lia/drivers/acpi/namespace/nseval.c --- linux-2.4.0-test10/drivers/acpi/namespace/nseval.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/namespace/nseval.c Fri Sep 15 16:38:46 2000 @@ -2,7 +2,7 @@ * * Module Name: nseval - Object evaluation interfaces -- includes control * method lookup and execution. - * $Revision: 76 $ + * $Revision: 77 $ * ******************************************************************************/ @@ -99,7 +99,7 @@ /* Lookup the name in the namespace */ - scope_info.scope.node = prefix_node->child; + scope_info.scope.node = prefix_node; status = acpi_ns_lookup (&scope_info, internal_path, ACPI_TYPE_ANY, IMODE_EXECUTE, NS_NO_UPSEARCH, NULL, &node); diff -urN linux-2.4.0-test10/drivers/acpi/namespace/nsinit.c linux-2.4.0-test10-lia/drivers/acpi/namespace/nsinit.c --- linux-2.4.0-test10/drivers/acpi/namespace/nsinit.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/drivers/acpi/namespace/nsinit.c Wed Sep 27 14:39:33 2000 @@ -0,0 +1,380 @@ +/****************************************************************************** + * + * Module Name: nsinit - namespace initialization + * $Revision: 3 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 R. Byron Moore + * + * 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 "acpi.h" +#include "acnamesp.h" +#include "acdispat.h" + +#define _COMPONENT NAMESPACE + MODULE_NAME ("nsinit") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_initialize_objects + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Walk the entire namespace and perform any necessary + * initialization on the objects found therein + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_initialize_objects ( + void) +{ + ACPI_STATUS status; + ACPI_INIT_WALK_INFO info; + + + info.field_count = 0; + info.field_init = 0; + info.op_region_count = 0; + info.op_region_init = 0; + info.object_count = 0; + + + /* Walk entire namespace from the supplied root */ + + status = acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, acpi_ns_init_one_object, + &info, NULL); + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ns_initialize_devices + * + * PARAMETERS: None + * + * RETURN: ACPI_STATUS + * + * DESCRIPTION: Walk the entire namespace and initialize all ACPI devices. + * This means running _INI on all present devices. + * + * Also: Install PCI config space handler for all PCI root bridges. + * A PCI root bridge is found by searching for devices containing + * a HID with the value EISAID("PNP0A03") + * + *****************************************************************************/ + +ACPI_STATUS +acpi_ns_initialize_devices ( + u32 flags) +{ + ACPI_STATUS status; + ACPI_DEVICE_WALK_INFO info; + + + info.flags = flags; + info.device_count = 0; + info.num_STA = 0; + info.num_INI = 0; + info.num_HID = 0; + info.num_PCI = 0; + + + status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + FALSE, acpi_ns_init_one_device, &info, NULL); + + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_init_one_object + * + * PARAMETERS: Obj_handle - Node + * Level - Current nesting level + * Context - Points to a init info struct + * Return_value - Not used + * + * RETURN: Status + * + * DESCRIPTION: Callback from Acpi_walk_namespace. Invoked for every object + * within the namespace. + * + * Currently, the only objects that require initialization are: + * 1) Methods + * 2) Op Regions + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_init_one_object ( + ACPI_HANDLE obj_handle, + u32 level, + void *context, + void **return_value) +{ + OBJECT_TYPE_INTERNAL type; + ACPI_STATUS status; + ACPI_INIT_WALK_INFO *info = (ACPI_INIT_WALK_INFO *) context; + ACPI_NAMESPACE_NODE *node = (ACPI_NAMESPACE_NODE *) obj_handle; + ACPI_OPERAND_OBJECT *obj_desc; + + + info->object_count++; + + + /* And even then, we are only interested in a few object types */ + + type = acpi_ns_get_type (obj_handle); + obj_desc = node->object; + if (!obj_desc) { + return (AE_OK); + } + + switch (type) + { + + case ACPI_TYPE_REGION: + + info->op_region_count++; + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { + break; + } + + info->op_region_init++; + status = acpi_ds_get_region_arguments (obj_desc); + break; + + + case ACPI_TYPE_FIELD_UNIT: + + info->field_count++; + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { + break; + } + + info->field_init++; + status = acpi_ds_get_field_unit_arguments (obj_desc); + break; + + default: + break; + } + + /* + * We ignore errors from above, and always return OK, since + * we don't want to abort the walk on a single error. + */ + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ns_init_one_device + * + * PARAMETERS: The usual "I'm a namespace callback" stuff + * + * RETURN: ACPI_STATUS + * + * DESCRIPTION: This is called once per device soon after ACPI is enabled + * to initialize each device. It determines if the device is + * present, and if so, calls _INI. + * + *****************************************************************************/ + +ACPI_STATUS +acpi_ns_init_one_device ( + ACPI_HANDLE obj_handle, + u32 nesting_level, + void *context, + void **return_value) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *ret_obj = NULL; + ACPI_DEVICE_WALK_INFO *info = (ACPI_DEVICE_WALK_INFO *) context; + +#ifdef CONFIG_ACPI_KERNEL_CONFIG_DEBUG + ACPI_BUFFER ret_buf; + UINT8 buf[PATHNAME_MAX]; + ret_buf.length = PATHNAME_MAX; + ret_buf.pointer = (void *) buf; + acpi_get_name(obj_handle, ACPI_FULL_PATHNAME, &ret_buf); +#endif + + + info->device_count++; + + /* + * Run _STA to determine if we can run _INI on the device. + */ + + status = acpi_ns_evaluate_relative (obj_handle, "_STA", NULL, &ret_obj); + if (AE_NOT_FOUND == status) { + /* No _STA means device is present */ + } + + else if (ACPI_FAILURE (status)) { + acpi_os_printf("Acpi: int_one_device _STA fail=0x%x\n", status); + return (status); + } + + else if (ret_obj) { + if (ACPI_TYPE_NUMBER != ret_obj->common.type) { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + /* + * if _STA "present" bit not set, we're done. + */ + info->num_STA++; + if (!(ret_obj->number.value & 1)) { +#ifdef CONFIG_ACPI_KERNEL_CONFIG_CBN_FIX + /* + * We need this check since CBN_ has STA(0x08). + * J.I. + */ + if (!(ret_obj->number.value & 0x08)) +#endif + goto cleanup; + } + } + + + /* + * The device is present. Run _INI. + */ + + status = acpi_ns_evaluate_relative (obj_handle, "_INI", NULL, NULL); + if (AE_NOT_FOUND == status) { + /* No _INI means device requires no initialization */ + } + + else if (ACPI_FAILURE (status)) { + acpi_os_printf("Acpi: int_one_device _INI fail=0x%x\n", status); + return (status); + } + + else { + info->num_INI++; + } + + + /* + * Examine the HID of the device. _HID can be an executable + * control method -- it simply has to return a string or number + * containing the HID. + */ + + if (ret_obj) { + acpi_cm_remove_reference (ret_obj); + } + + ret_obj = NULL; + status = acpi_ns_evaluate_relative (obj_handle, "_HID", NULL, &ret_obj); + if (AE_NOT_FOUND == status) { + /* No _HID --> Can't be a PCI root bridge */ + + return (AE_OK); + } + + if (ACPI_FAILURE (status)) { + acpi_os_printf("Acpi: int_one_device _HID fail=0x%x\n", status); + return (status); + } + + info->num_HID++; + + + /* + * Found an _HID object. + * Check for a PCI Root Bridge. We need to install the PCI_CONFIG space + * handler on all PCI Root Bridges found within the namespace + * + * A PCI Root Bridge has an HID with the value EISAID("PNP0A03") + * The HID can be either a number or a string. + */ + + switch (ret_obj->common.type) + { + case ACPI_TYPE_NUMBER: + + if (ret_obj->number.value != PCI_ROOT_HID_VALUE) { + goto cleanup; + } + + break; + + case ACPI_TYPE_STRING: + + if (STRNCMP (ret_obj->string.pointer, PCI_ROOT_HID_STRING, + sizeof (PCI_ROOT_HID_STRING))) + { + goto cleanup; + } + + break; + + default: + acpi_os_printf("Acpi: int_one_device _HID invalid type\n"); + + goto cleanup; + } + + + /* + * We found a valid PCI_ROOT_HID. + * The parent of the HID entry is the PCI device; Install the default PCI + * handler for this PCI device. + */ + + info->num_PCI++; + + if (!(info->flags & ACPI_NO_PCI_INIT)) { + status = acpi_install_address_space_handler ( + obj_handle, + ADDRESS_SPACE_PCI_CONFIG, + ACPI_DEFAULT_HANDLER, NULL, NULL); + +#ifdef CONFIG_ACPI_KERNEL_CONFIG_DEBUG + acpi_os_printf("Acpi:binding pci handler to [%s] %s\n", (char *)ret_buf.pointer, status?"fail":"pass"); +#endif + } + +cleanup: + + if (ret_obj) { + acpi_cm_remove_reference (ret_obj); + } + + return (AE_OK); +} + + diff -urN linux-2.4.0-test10/drivers/acpi/namespace/nsload.c linux-2.4.0-test10-lia/drivers/acpi/namespace/nsload.c --- linux-2.4.0-test10/drivers/acpi/namespace/nsload.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/namespace/nsload.c Fri Sep 15 16:38:46 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: nsload - namespace loading/expanding/contracting procedures - * $Revision: 28 $ + * $Revision: 31 $ * *****************************************************************************/ @@ -37,6 +37,123 @@ MODULE_NAME ("nsload") +/****************************************************************************** + * + * FUNCTION: Acpi_load_namespace + * + * PARAMETERS: Display_aml_during_load + * + * RETURN: Status + * + * DESCRIPTION: Load the name space from what ever is pointed to by DSDT. + * (DSDT points to either the BIOS or a buffer.) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_load_namespace ( + void) +{ + ACPI_STATUS status; + + + /* There must be at least a DSDT installed */ + + if (acpi_gbl_DSDT == NULL) { + return (AE_NO_ACPI_TABLES); + } + + + /* + * Load the namespace. The DSDT is required, + * but the SSDT and PSDT tables are optional. + */ + + status = acpi_ns_load_table_by_type (ACPI_TABLE_DSDT); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Ignore exceptions from these */ + + acpi_ns_load_table_by_type (ACPI_TABLE_SSDT); + acpi_ns_load_table_by_type (ACPI_TABLE_PSDT); + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_one_parse_pass + * + * PARAMETERS: + * + * RETURN: Status + * + * DESCRIPTION: + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_one_complete_parse ( + u32 pass_number, + ACPI_TABLE_DESC *table_desc) +{ + ACPI_PARSE_DOWNWARDS descending_callback; + ACPI_PARSE_UPWARDS ascending_callback; + ACPI_PARSE_OBJECT *parse_root; + ACPI_STATUS status; + + + switch (pass_number) + { + case 1: + descending_callback = acpi_ds_load1_begin_op; + ascending_callback = acpi_ds_load1_end_op; + break; + + case 2: + descending_callback = acpi_ds_load2_begin_op; + ascending_callback = acpi_ds_load2_end_op; + break; + + case 3: + descending_callback = acpi_ds_exec_begin_op; + ascending_callback = acpi_ds_exec_end_op; + break; + + default: + return (AE_BAD_PARAMETER); + } + + /* Create and init a Root Node */ + + parse_root = acpi_ps_alloc_op (AML_SCOPE_OP); + if (!parse_root) { + return (AE_NO_MEMORY); + } + + ((ACPI_PARSE2_OBJECT *) parse_root)->name = ACPI_ROOT_NAME; + + + /* Pass 1: Parse everything except control method bodies */ + + status = acpi_ps_parse_aml (parse_root, + table_desc->aml_pointer, + table_desc->aml_length, + ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE, + NULL, NULL, NULL, + descending_callback, + ascending_callback); + + acpi_ps_delete_parse_tree (parse_root); + + return (status); +} + + /******************************************************************************* * * FUNCTION: Acpi_ns_parse_table @@ -69,32 +186,11 @@ * performs another complete parse of the AML.. */ - /* Create and init a Root Node */ - - acpi_gbl_parsed_namespace_root = acpi_ps_alloc_op (AML_SCOPE_OP); - if (!acpi_gbl_parsed_namespace_root) { - return (AE_NO_MEMORY); - } - - ((ACPI_PARSE2_OBJECT *) acpi_gbl_parsed_namespace_root)->name = ACPI_ROOT_NAME; - - - /* Pass 1: Parse everything except control method bodies */ - - status = acpi_ps_parse_aml (acpi_gbl_parsed_namespace_root, - table_desc->aml_pointer, - table_desc->aml_length, - ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE, - NULL, NULL, NULL, - acpi_ds_load1_begin_op, - acpi_ds_load1_end_op); - + status = acpi_ns_one_complete_parse (1, table_desc); if (ACPI_FAILURE (status)) { return (status); } - acpi_ps_delete_parse_tree (acpi_gbl_parsed_namespace_root); - /* * AML Parse, pass 2 @@ -106,31 +202,14 @@ * parse objects are all cached. */ - /* Create and init a Root Node */ - - acpi_gbl_parsed_namespace_root = acpi_ps_alloc_op (AML_SCOPE_OP); - if (!acpi_gbl_parsed_namespace_root) { - return (AE_NO_MEMORY); - } - - ((ACPI_PARSE2_OBJECT *) acpi_gbl_parsed_namespace_root)->name = ACPI_ROOT_NAME; - - - /* Pass 2: Resolve forward references */ - - status = acpi_ps_parse_aml (acpi_gbl_parsed_namespace_root, - table_desc->aml_pointer, - table_desc->aml_length, - ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE, - NULL, NULL, NULL, - acpi_ds_load2_begin_op, - acpi_ds_load2_end_op); - + status = acpi_ns_one_complete_parse (2, table_desc); if (ACPI_FAILURE (status)) { return (status); } - acpi_ps_delete_parse_tree (acpi_gbl_parsed_namespace_root); + + /* TBD: no longer needed, remove */ + acpi_gbl_parsed_namespace_root = NULL; @@ -147,8 +226,7 @@ * * RETURN: Status * - * DESCRIPTION: Mainline of the AML load/dump subsystem. Sets up the - * input engine, calls handler for outermost object type. + * DESCRIPTION: Load one ACPI table into the namespace * ****************************************************************************/ @@ -247,13 +325,6 @@ } table_desc->table_id = TABLE_ID_DSDT; - - /* Initialize the root of the namespace tree */ - - status = acpi_ns_root_initialize (); - if (ACPI_FAILURE (status)) { - goto unlock_and_exit; - } /* Now load the single DSDT */ diff -urN linux-2.4.0-test10/drivers/acpi/namespace/nsobject.c linux-2.4.0-test10-lia/drivers/acpi/namespace/nsobject.c --- linux-2.4.0-test10/drivers/acpi/namespace/nsobject.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/namespace/nsobject.c Fri Sep 15 16:38:46 2000 @@ -2,7 +2,7 @@ * * Module Name: nsobject - Utilities for objects attached to namespace * table entries - * $Revision: 44 $ + * $Revision: 45 $ * ******************************************************************************/ diff -urN linux-2.4.0-test10/drivers/acpi/namespace/nsxfname.c linux-2.4.0-test10-lia/drivers/acpi/namespace/nsxfname.c --- linux-2.4.0-test10/drivers/acpi/namespace/nsxfname.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/namespace/nsxfname.c Fri Sep 15 16:38:46 2000 @@ -2,7 +2,7 @@ * * Module Name: nsxfname - Public interfaces to the ACPI subsystem * ACPI Namespace oriented interfaces - * $Revision: 64 $ + * $Revision: 66 $ * *****************************************************************************/ @@ -38,60 +38,6 @@ MODULE_NAME ("nsxfname") -/****************************************************************************** - * - * FUNCTION: Acpi_load_namespace - * - * PARAMETERS: Display_aml_during_load - * - * RETURN: Status - * - * DESCRIPTION: Load the name space from what ever is pointed to by DSDT. - * (DSDT points to either the BIOS or a buffer.) - * - ******************************************************************************/ - -ACPI_STATUS -acpi_load_namespace ( - void) -{ - ACPI_STATUS status; - - - /* There must be at least a DSDT installed */ - - if (acpi_gbl_DSDT == NULL) { - return (AE_NO_ACPI_TABLES); - } - - - /* - * Load the namespace. The DSDT is required, - * but the SSDT and PSDT tables are optional. - */ - - status = acpi_ns_load_table_by_type (ACPI_TABLE_DSDT); - if (ACPI_FAILURE (status)) { - return (status); - } - - /* Ignore exceptions from these */ - - acpi_ns_load_table_by_type (ACPI_TABLE_SSDT); - acpi_ns_load_table_by_type (ACPI_TABLE_PSDT); - - - /* - * Install the default Op_region handlers, ignore the return - * code right now. - */ - - acpi_ev_install_default_address_space_handlers (); - - return (status); -} - - /**************************************************************************** * * FUNCTION: Acpi_get_handle @@ -253,14 +199,15 @@ * * RETURN: Status * - * DESCRIPTION: Returns information about an object as gleaned from running - * several standard control methods. + * DESCRIPTION: Returns information about an object as gleaned from the + * namespace node and possibly by running several standard + * control methods (Such as in the case of a device.) * ******************************************************************************/ ACPI_STATUS acpi_get_object_info ( - ACPI_HANDLE device, + ACPI_HANDLE handle, ACPI_DEVICE_INFO *info) { DEVICE_ID hid; @@ -268,27 +215,27 @@ ACPI_STATUS status; u32 device_status = 0; u32 address = 0; - ACPI_NAMESPACE_NODE *device_node; + ACPI_NAMESPACE_NODE *node; /* Parameter validation */ - if (!device || !info) { + if (!handle || !info) { return (AE_BAD_PARAMETER); } acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); - device_node = acpi_ns_convert_handle_to_entry (device); - if (!device_node) { + node = acpi_ns_convert_handle_to_entry (handle); + if (!node) { acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); return (AE_BAD_PARAMETER); } - info->type = device_node->type; - info->name = device_node->name; + info->type = node->type; + info->name = node->name; info->parent = acpi_ns_convert_entry_to_handle ( - acpi_ns_get_parent_object (device_node)); + acpi_ns_get_parent_object (node)); acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); @@ -300,13 +247,19 @@ } - /* Get extra info for ACPI devices */ + /* + * Get extra info for ACPI devices only. Run the + * _HID, _UID, _STA, and _ADR methods. Note: none + * of these methods are required, so they may or may + * not be present. The Info->Valid bits are used + * to indicate which methods ran successfully. + */ info->valid = 0; /* Execute the _HID method and save the result */ - status = acpi_cm_execute_HID (device_node, &hid); + status = acpi_cm_execute_HID (node, &hid); if (ACPI_SUCCESS (status)) { if (hid.type == STRING_PTR_DEVICE_ID) { STRCPY (info->hardware_id, hid.data.string_ptr); @@ -320,7 +273,7 @@ /* Execute the _UID method and save the result */ - status = acpi_cm_execute_UID (device_node, &uid); + status = acpi_cm_execute_UID (node, &uid); if (ACPI_SUCCESS (status)) { if (hid.type == STRING_PTR_DEVICE_ID) { STRCPY (info->unique_id, uid.data.string_ptr); @@ -337,7 +290,7 @@ * _STA is not always present */ - status = acpi_cm_execute_STA (device_node, &device_status); + status = acpi_cm_execute_STA (node, &device_status); if (ACPI_SUCCESS (status)) { info->current_status = device_status; info->valid |= ACPI_VALID_STA; @@ -349,7 +302,7 @@ */ status = acpi_cm_evaluate_numeric_object (METHOD_NAME__ADR, - device_node, &address); + node, &address); if (ACPI_SUCCESS (status)) { info->address = address; diff -urN linux-2.4.0-test10/drivers/acpi/namespace/nsxfobj.c linux-2.4.0-test10-lia/drivers/acpi/namespace/nsxfobj.c --- linux-2.4.0-test10/drivers/acpi/namespace/nsxfobj.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/namespace/nsxfobj.c Fri Sep 15 16:38:46 2000 @@ -2,7 +2,7 @@ * * Module Name: nsxfobj - Public interfaces to the ACPI subsystem * ACPI Object oriented interfaces - * $Revision: 65 $ + * $Revision: 67 $ * ******************************************************************************/ @@ -28,6 +28,7 @@ #include "acpi.h" #include "acinterp.h" #include "acnamesp.h" +#include "acdispat.h" #define _COMPONENT NAMESPACE diff -urN linux-2.4.0-test10/drivers/acpi/os.c linux-2.4.0-test10-lia/drivers/acpi/os.c --- linux-2.4.0-test10/drivers/acpi/os.c Fri Sep 22 14:21:17 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/os.c Thu Oct 19 16:07:09 2000 @@ -2,6 +2,7 @@ * os.c - OS-dependent functions * * Copyright (C) 2000 Andrew Henroid + * Copyright (C) 2000 J.I. Lee * * 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 @@ -18,24 +19,63 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include + #include #include #include #include #include #include -#include +#include +#include #include +#include #include "acpi.h" +#ifdef CONFIG_ACPI_KERNEL_CONFIG_ONLY +#include "acpiconf.h" +#else #include "driver.h" +#endif #define _COMPONENT OS_DEPENDENT - MODULE_NAME ("os") + MODULE_NAME ("os") + + +#ifdef CONFIG_ACPI_KERNEL_CONFIG +#include "osconf.h" + +struct acpi_osd acpi_osd_rt = { + /* these are runtime osd entries that differ from boottime entries */ + acpi_os_allocate_rt, + acpi_os_callocate_rt, + acpi_os_free_rt, + acpi_os_queue_for_execution_rt, + acpi_os_read_pci_cfg_byte_rt, + acpi_os_read_pci_cfg_word_rt, + acpi_os_read_pci_cfg_dword_rt, + acpi_os_write_pci_cfg_byte_rt, + acpi_os_write_pci_cfg_word_rt, + acpi_os_write_pci_cfg_dword_rt +}; +#else +#define acpi_os_allocate_rt acpi_os_allocate +#define acpi_os_callocate_rt acpi_os_callocate +#define acpi_os_free_rt acpi_os_free +#define acpi_os_queue_for_execution_rt acpi_os_queue_for_execution +#define acpi_os_read_pci_cfg_byte_rt acpi_os_read_pci_cfg_byte +#define acpi_os_read_pci_cfg_word_rt acpi_os_read_pci_cfg_word +#define acpi_os_read_pci_cfg_dword_rt acpi_os_read_pci_cfg_dword +#define acpi_os_write_pci_cfg_byte_rt acpi_os_write_pci_cfg_byte +#define acpi_os_write_pci_cfg_word_rt acpi_os_write_pci_cfg_word +#define acpi_os_write_pci_cfg_dword_rt acpi_os_write_pci_cfg_dword +#endif static int acpi_irq_irq = 0; static OSD_HANDLER acpi_irq_handler = NULL; static void *acpi_irq_context = NULL; + char * strupr(char *str) { @@ -84,13 +124,13 @@ } void * -acpi_os_allocate(u32 size) +acpi_os_allocate_rt(u32 size) { return kmalloc(size, GFP_KERNEL); } void * -acpi_os_callocate(u32 size) +acpi_os_callocate_rt(u32 size) { void *ptr = acpi_os_allocate(size); if (ptr) @@ -99,7 +139,7 @@ } void -acpi_os_free(void *ptr) +acpi_os_free_rt(void *ptr) { kfree(ptr); } @@ -132,12 +172,108 @@ (*acpi_irq_handler)(acpi_irq_context); } +#ifdef CONFIG_ACPI_KERNEL_CONFIG +struct irqaction acpiirqaction; +/* + * codes from request_irq and free_irq. + */ ACPI_STATUS acpi_os_install_interrupt_handler(u32 irq, OSD_HANDLER handler, void *context) { + struct irqaction *act; + int retval; + + if (irq >= NR_IRQS) { + printk("ACPI: install SCI handler fail: invalid irq%d\n", irq); + return AE_ERROR; + } + + if (!handler) { + printk("ACPI: install SCI handler fail: invalid handler\n"); + return AE_ERROR; + } + + act = & acpiirqaction; + acpi_irq_irq = irq; acpi_irq_handler = handler; acpi_irq_context = context; + + act->handler = acpi_irq; + act->flags = SA_INTERRUPT | SA_SHIRQ; + act->mask = 0; + act->name = "acpi"; + act->next = NULL; + act->dev_id = acpi_irq; + + retval = setup_irq(irq, act); + if (retval) { + printk("ACPI: install SCI handler fail: setup_irq\n"); + acpi_irq_handler = NULL; + return AE_ERROR; + } + dprintk(("ACPI: install SCI %d handler pass\n", irq)); + + return AE_OK; +} + +ACPI_STATUS +acpi_os_remove_interrupt_handler(u32 irq, OSD_HANDLER handler) +{ + irq_desc_t *desc; + struct irqaction **p; + unsigned long flags; + + if (!acpi_irq_handler) + return AE_OK; + + if (irq != acpi_irq_irq) return AE_ERROR; + + acpi_irq_handler = NULL; + + desc = irq_desc + irq; + spin_lock_irqsave(&desc->lock,flags); + p = &desc->action; + for (;;) { + struct irqaction * action = *p; + if (action) { + struct irqaction **pp = p; + p = &action->next; + if (action->dev_id != acpi_irq) + continue; + + /* Found it - now remove it from the list of entries */ + *pp = action->next; + if (!desc->action) { + desc->status |= IRQ_DISABLED; + desc->handler->shutdown(irq); + } + spin_unlock_irqrestore(&desc->lock,flags); + +#ifdef CONFIG_SMP + /* Wait to make sure it's not being used on another CPU */ + while (desc->status & IRQ_INPROGRESS) + barrier(); +#endif + return AE_OK; + } + printk("ACPI: Trying to free free IRQ%d\n",irq); + spin_unlock_irqrestore(&desc->lock,flags); + return AE_OK; + } + + return AE_OK; +} + +#else + +ACPI_STATUS +acpi_os_install_interrupt_handler(u32 irq, OSD_HANDLER handler, void *context) +{ + acpi_irq_irq = irq; + acpi_irq_handler = handler; + acpi_irq_context = context; + if (request_irq(irq, acpi_irq, SA_SHIRQ, @@ -149,6 +285,7 @@ return AE_OK; } + ACPI_STATUS acpi_os_remove_interrupt_handler(u32 irq, OSD_HANDLER handler) { @@ -158,6 +295,7 @@ } return AE_OK; } +#endif /* * Running in interpreter thread context, safe to sleep @@ -212,8 +350,9 @@ outl(val, port); } + ACPI_STATUS -acpi_os_read_pci_cfg_byte( +acpi_os_read_pci_cfg_byte_rt( u32 bus, u32 func, u32 addr, @@ -227,7 +366,7 @@ } ACPI_STATUS -acpi_os_read_pci_cfg_word( +acpi_os_read_pci_cfg_word_rt( u32 bus, u32 func, u32 addr, @@ -241,7 +380,7 @@ } ACPI_STATUS -acpi_os_read_pci_cfg_dword( +acpi_os_read_pci_cfg_dword_rt( u32 bus, u32 func, u32 addr, @@ -255,7 +394,7 @@ } ACPI_STATUS -acpi_os_write_pci_cfg_byte( +acpi_os_write_pci_cfg_byte_rt( u32 bus, u32 func, u32 addr, @@ -269,7 +408,7 @@ } ACPI_STATUS -acpi_os_write_pci_cfg_word( +acpi_os_write_pci_cfg_word_rt( u32 bus, u32 func, u32 addr, @@ -283,7 +422,7 @@ } ACPI_STATUS -acpi_os_write_pci_cfg_dword( +acpi_os_write_pci_cfg_dword_rt( u32 bus, u32 func, u32 addr, @@ -301,13 +440,17 @@ */ ACPI_STATUS -acpi_os_queue_for_execution( +acpi_os_queue_for_execution_rt( u32 priority, OSD_EXECUTION_CALLBACK callback, void *context) { +#ifndef CONFIG_ACPI_KERNEL_CONFIG_ONLY if (acpi_run(callback, context)) return AE_ERROR; +#else + (*callback)(context); +#endif return AE_OK; } diff -urN linux-2.4.0-test10/drivers/acpi/osconf.c linux-2.4.0-test10-lia/drivers/acpi/osconf.c --- linux-2.4.0-test10/drivers/acpi/osconf.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/drivers/acpi/osconf.c Fri Sep 22 18:11:07 2000 @@ -0,0 +1,334 @@ +/* + * osconf.c - ACPI OS-dependent functions for Kernel Boot/Configuration time + * + * Copyright (C) 2000 Intel Corp. + * Copyright (C) 2000 J.I. Lee + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acpi.h" +#include "osconf.h" + + +static void * __init acpi_os_allocate_bt(u32 size); +static void * __init acpi_os_callocate_bt(u32 size); +static void __init acpi_os_free_bt(void *ptr); + +static ACPI_STATUS __init +acpi_os_queue_for_execution_bt( + u32 priority, + OSD_EXECUTION_CALLBACK callback, + void *context + ); + +static ACPI_STATUS __init +acpi_os_read_pci_cfg_byte_bt( u32 segbus, u32 func, u32 addr, u8 * val); + +static ACPI_STATUS __init +acpi_os_read_pci_cfg_word_bt( u32 segbus, u32 func, u32 addr, u16 * val); + +static ACPI_STATUS __init +acpi_os_read_pci_cfg_dword_bt( u32 segbus, u32 func, u32 addr, u32 * val); + +static ACPI_STATUS __init +acpi_os_write_pci_cfg_byte_bt( u32 segbus, u32 func, u32 addr, u8 val); + +static ACPI_STATUS __init +acpi_os_write_pci_cfg_word_bt( u32 segbus, u32 func, u32 addr, u16 val); + +static ACPI_STATUS __init +acpi_os_write_pci_cfg_dword_bt( u32 segbus, u32 func, u32 addr, u32 val); + + +static struct acpi_osd *acpi_osd; +extern struct acpi_osd acpi_osd_rt; +static struct acpi_osd acpi_osd_bt __initdata = { + /* these are boottime osd entries that differ from runtime entries */ + acpi_os_allocate_bt, + acpi_os_callocate_bt, + acpi_os_free_bt, + acpi_os_queue_for_execution_bt, + acpi_os_read_pci_cfg_byte_bt, + acpi_os_read_pci_cfg_word_bt, + acpi_os_read_pci_cfg_dword_bt, + acpi_os_write_pci_cfg_byte_bt, + acpi_os_write_pci_cfg_word_bt, + acpi_os_write_pci_cfg_dword_bt +}; + +#ifdef CONFIG_ACPI_KERNEL_CONFIG_BM_PROFILE +static void __init +acpi_cf_bm_statistics( void ); +#endif + +void __init +acpi_os_bind_osd(int acpi_phase) +{ + switch (acpi_phase) { + case ACPI_CF_PHASE_BOOTTIME: + acpi_osd = &acpi_osd_bt; + printk("Acpi cfg:bind to Boot time Acpi OSD\n"); + break; + case ACPI_CF_PHASE_RUNTIME: + default: + acpi_osd = &acpi_osd_rt; + printk("Acpi cfg:bind to Run time Acpi OSD\n"); +#ifdef CONFIG_ACPI_KERNEL_CONFIG_BM_PROFILE + acpi_cf_bm_statistics(); +#endif + break; + } +} + + +void * +acpi_os_allocate(u32 size) +{ + return acpi_osd->allocate(size); +} + +void * +acpi_os_callocate(u32 size) +{ + return acpi_osd->callocate(size); +} + +void +acpi_os_free(void *ptr) +{ + acpi_osd->free(ptr); + return; +} + + +ACPI_STATUS +acpi_os_queue_for_execution( + u32 priority, + OSD_EXECUTION_CALLBACK callback, + void *context) +{ + return acpi_osd->queue_for_exec(priority, callback, context); +} + + +ACPI_STATUS +acpi_os_read_pci_cfg_byte( u32 segbus, u32 func, u32 addr, u8 * val) +{ + return acpi_osd->read_pci_cfg_byte(segbus, func, addr, val); +} + + +ACPI_STATUS +acpi_os_read_pci_cfg_word( u32 segbus, u32 func, u32 addr, u16 * val) +{ + return acpi_osd->read_pci_cfg_word(segbus, func, addr, val); +} + + +ACPI_STATUS +acpi_os_read_pci_cfg_dword( u32 segbus, u32 func, u32 addr, u32 * val) +{ + return acpi_osd->read_pci_cfg_dword(segbus, func, addr, val); +} + + +ACPI_STATUS +acpi_os_write_pci_cfg_byte( u32 segbus, u32 func, u32 addr, u8 val) +{ + return acpi_osd->write_pci_cfg_byte(segbus, func, addr, val); +} + + +ACPI_STATUS +acpi_os_write_pci_cfg_word( u32 segbus, u32 func, u32 addr, u16 val) +{ + return acpi_osd->write_pci_cfg_word(segbus, func, addr, val); +} + + +ACPI_STATUS +acpi_os_write_pci_cfg_dword( u32 segbus, u32 func, u32 addr, u32 val) +{ + return acpi_osd->write_pci_cfg_dword(segbus, func, addr, val); +} + + + +#ifdef CONFIG_ACPI_KERNEL_CONFIG_BM_PROFILE +/* + * Let's profile bootmem usage to see how much we consume. J.I. + */ +static unsigned long bm_alloc_size __initdata = 0; +static unsigned long bm_alloc_size_max __initdata = 0; +static unsigned long bm_alloc_count_max __initdata = 0; +static unsigned long bm_free_count_max __initdata = 0; + +static void __init +acpi_cf_bm_checkin(void *ptr, u32 size) +{ + bm_alloc_count_max++; + bm_alloc_size += size; + if (bm_alloc_size > bm_alloc_size_max) + bm_alloc_size_max = bm_alloc_size; +}; + +static void __init +acpi_cf_bm_checkout(void *ptr, u32 size) +{ + bm_free_count_max++; + bm_alloc_size -= size; +}; + +static void __init +acpi_cf_bm_statistics( void ) +{ + printk("Acpi cfg:bm_alloc_size_max =%ld bytes\n", bm_alloc_size_max); + printk("Acpi cfg:bm_alloc_count_max=%ld\n", bm_alloc_count_max); + printk("Acpi cfg:bm_free_count_max =%ld\n", bm_free_count_max); +} +#endif + + +static void * __init +acpi_os_allocate_bt(u32 size) +{ + void *ptr; + + size += sizeof(unsigned long); + ptr = alloc_bootmem(size); + + if (ptr) { +#ifdef CONFIG_ACPI_KERNEL_CONFIG_BM_PROFILE + acpi_cf_bm_checkin(ptr, size); +#endif + *((unsigned long *)ptr) = (unsigned long)size; + ptr += sizeof(unsigned long); + } + + return ptr; +} + +static void * __init +acpi_os_callocate_bt(u32 size) +{ + void *ptr = acpi_os_allocate_bt(size); + + return ptr; +} + +static void __init +acpi_os_free_bt(void *ptr) +{ + unsigned long size; + + ptr -= sizeof(size); + size = *((unsigned long *)ptr); + +#ifdef CONFIG_ACPI_KERNEL_CONFIG_BM_PROFILE + acpi_cf_bm_checkout(ptr, (unsigned long)size); +#endif + //if (size) + free_bootmem (__pa((unsigned long)ptr), (u32)size); +} + + +static ACPI_STATUS __init +acpi_os_queue_for_execution_bt( + u32 priority, + OSD_EXECUTION_CALLBACK callback, + void *context) +{ + /* + * run callback immediately + */ + (*callback)(context); + return AE_OK; +} + + +static ACPI_STATUS __init +acpi_os_read_pci_cfg_byte_bt( u32 segbus, u32 func, u32 addr, u8 * val) +{ + unsigned int devfn; + s64 status; + u64 lval; + + devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); + status = ia64_sal_pci_config_read(PCI_CONFIG_ADDRESS((segbus & 0xffff), devfn, addr), 1, &lval); + *val = lval; + + return status; +} + + +static ACPI_STATUS __init +acpi_os_read_pci_cfg_word_bt( u32 segbus, u32 func, u32 addr, u16 * val) +{ + unsigned int devfn; + s64 status; + u64 lval; + + devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); + status = ia64_sal_pci_config_read(PCI_CONFIG_ADDRESS((segbus & 0xffff), devfn, addr), 2, &lval); + *val = lval; + + return status; +} + + +static ACPI_STATUS __init +acpi_os_read_pci_cfg_dword_bt( u32 segbus, u32 func, u32 addr, u32 * val) +{ + unsigned int devfn; + s64 status; + u64 lval; + + devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); + status = ia64_sal_pci_config_read(PCI_CONFIG_ADDRESS((segbus & 0xffff), devfn, addr), 4, &lval); + *val = lval; + + return status; +} + + +static ACPI_STATUS __init +acpi_os_write_pci_cfg_byte_bt( u32 segbus, u32 func, u32 addr, u8 val) +{ + unsigned int devfn; + + devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); + return ia64_sal_pci_config_write(PCI_CONFIG_ADDRESS((segbus & 0xffff), devfn, addr), 1, val); +} + + +static ACPI_STATUS __init +acpi_os_write_pci_cfg_word_bt( u32 segbus, u32 func, u32 addr, u16 val) +{ + unsigned int devfn; + + devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); + return ia64_sal_pci_config_write(PCI_CONFIG_ADDRESS((segbus & 0xffff), devfn, addr), 2, val); +} + + +static ACPI_STATUS __init +acpi_os_write_pci_cfg_dword_bt( u32 segbus, u32 func, u32 addr, u32 val) +{ + unsigned int devfn; + + devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); + return ia64_sal_pci_config_write(PCI_CONFIG_ADDRESS((segbus & 0xffff), devfn, addr), 4, val); +} + + diff -urN linux-2.4.0-test10/drivers/acpi/osconf.h linux-2.4.0-test10-lia/drivers/acpi/osconf.h --- linux-2.4.0-test10/drivers/acpi/osconf.h Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/drivers/acpi/osconf.h Mon Aug 28 14:56:12 2000 @@ -0,0 +1,91 @@ +/* + * osconf.h - ACPI OS-dependent headers for Kernel Boot/Configuration time + * + * Copyright (C) 2000 Intel Corp. + * Copyright (C) 2000 J.I. Lee + */ + + +struct acpi_osd { + void * (*allocate)(u32 size); + void * (*callocate)(u32 size); + void (*free)(void *ptr); + ACPI_STATUS (*queue_for_exec)(u32 pri, OSD_EXECUTION_CALLBACK cb, void *context); + ACPI_STATUS (*read_pci_cfg_byte)(u32 bus, u32 func, u32 addr, u8 *val); + ACPI_STATUS (*read_pci_cfg_word)(u32 bus, u32 func, u32 addr, u16 *val); + ACPI_STATUS (*read_pci_cfg_dword)(u32 bus, u32 func, u32 addr, u32 *val); + ACPI_STATUS (*write_pci_cfg_byte)(u32 bus, u32 func, u32 addr, u8 val); + ACPI_STATUS (*write_pci_cfg_word)(u32 bus, u32 func, u32 addr, u16 val); + ACPI_STATUS (*write_pci_cfg_dword)(u32 bus, u32 func, u32 addr, u32 val); +}; + + +#define PCI_CONFIG_ADDRESS(bus, devfn, where) \ + (((u64) bus << 16) | ((u64) (devfn & 0xff) << 8) | (where & 0xff)) + +#define ACPI_CF_PHASE_BOOTTIME 0x00 +#define ACPI_CF_PHASE_RUNTIME 0x01 + + +/* acpi_osd functions */ +void * acpi_os_allocate(u32 size); +void * acpi_os_callocate(u32 size); +void acpi_os_free(void *ptr); + + +ACPI_STATUS +acpi_os_queue_for_execution( + u32 priority, + OSD_EXECUTION_CALLBACK callback, + void *context + ); + +ACPI_STATUS +acpi_os_read_pci_cfg_byte( u32 segbus, u32 func, u32 addr, u8 * val); + +ACPI_STATUS +acpi_os_read_pci_cfg_word( u32 segbus, u32 func, u32 addr, u16 * val); + +ACPI_STATUS +acpi_os_read_pci_cfg_dword( u32 segbus, u32 func, u32 addr, u32 * val); + +ACPI_STATUS +acpi_os_write_pci_cfg_byte( u32 segbus, u32 func, u32 addr, u8 val); + +ACPI_STATUS +acpi_os_write_pci_cfg_word( u32 segbus, u32 func, u32 addr, u16 val); + +ACPI_STATUS +acpi_os_write_pci_cfg_dword( u32 segbus, u32 func, u32 addr, u32 val); + + +/* acpi_osd_rt functions */ +extern void * acpi_os_allocate_rt(u32 size); +extern void * acpi_os_callocate_rt(u32 size); +extern void acpi_os_free_rt(void *ptr); + +extern ACPI_STATUS +acpi_os_queue_for_execution_rt( + u32 priority, + OSD_EXECUTION_CALLBACK callback, + void *context + ); + +extern ACPI_STATUS +acpi_os_read_pci_cfg_byte_rt( u32 segbus, u32 func, u32 addr, u8 * val); + +extern ACPI_STATUS +acpi_os_read_pci_cfg_word_rt( u32 segbus, u32 func, u32 addr, u16 * val); + +extern ACPI_STATUS +acpi_os_read_pci_cfg_dword_rt( u32 segbus, u32 func, u32 addr, u32 * val); + +extern ACPI_STATUS +acpi_os_write_pci_cfg_byte_rt( u32 segbus, u32 func, u32 addr, u8 val); + +extern ACPI_STATUS +acpi_os_write_pci_cfg_word_rt( u32 segbus, u32 func, u32 addr, u16 val); + +extern ACPI_STATUS +acpi_os_write_pci_cfg_dword_rt( u32 segbus, u32 func, u32 addr, u32 val); + diff -urN linux-2.4.0-test10/drivers/acpi/parser/psparse.c linux-2.4.0-test10-lia/drivers/acpi/parser/psparse.c --- linux-2.4.0-test10/drivers/acpi/parser/psparse.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/parser/psparse.c Fri Sep 15 16:38:46 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: psparse - Parser top level AML parse routines - * $Revision: 51 $ + * $Revision: 56 $ * *****************************************************************************/ @@ -577,15 +577,23 @@ parser_state = walk_state->parser_state; - if (walk_state->prev_op) { - op = walk_state->prev_op; - arg_types = walk_state->prev_arg_types; + if (walk_state->walk_type & WALK_METHOD_RESTART) { + if (acpi_ps_has_completed_scope (parser_state)) { + acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count); + } + + else if (walk_state->prev_op) { + /* We were in the middle of an op */ + + op = walk_state->prev_op; + arg_types = walk_state->prev_arg_types; + } } /* * Iterative parsing loop, while there is more aml to process: */ - while (parser_state->aml < parser_state->aml_end) { + while ((parser_state->aml < parser_state->aml_end) || (op)) { if (!op) { /* Get the next opcode from the AML stream */ @@ -691,11 +699,11 @@ deferred_op->length = 0; } } - } - else { + } + else { /* Not a named opcode, just allocate Op and append to parent */ op = acpi_ps_alloc_op (opcode); @@ -703,6 +711,25 @@ return (AE_NO_MEMORY); } + + if ((op->opcode == AML_CREATE_FIELD_OP) || + (op->opcode == AML_BIT_FIELD_OP) || + (op->opcode == AML_BYTE_FIELD_OP) || + (op->opcode == AML_WORD_FIELD_OP) || + (op->opcode == AML_DWORD_FIELD_OP)) + { + /* + * Backup to beginning of Create_xXXfield declaration (1 for + * Opcode) + * + * Body_length is unknown until we parse the body + */ + deferred_op = (ACPI_PARSE2_OBJECT *) op; + + deferred_op->data = parser_state->aml -1; + deferred_op->length = 0; + } + acpi_ps_append_arg (acpi_ps_get_parent_scope (parser_state), op); if ((walk_state->descending_callback != NULL)) { @@ -728,7 +755,11 @@ } + /* Start Arg_count at zero because we don't know if there are any args yet */ + arg_count = 0; + + if (arg_types) /* Are there any arguments that must be processed? */ { /* get arguments */ @@ -761,12 +792,11 @@ arg = acpi_ps_get_next_arg (parser_state, GET_CURRENT_ARG_TYPE (arg_types), &arg_count); - if (arg) { arg->aml_offset = aml_offset; + acpi_ps_append_arg (op, arg); } - acpi_ps_append_arg (op, arg); INCREMENT_ARG_LIST (arg_types); } @@ -800,6 +830,10 @@ } } + + /* + * Zero Arg_count means that all arguments for this op have been processed + */ if (!arg_count) { /* completed Op, prepare for next */ @@ -821,11 +855,29 @@ */ deferred_op->length = parser_state->aml - - deferred_op->data; + deferred_op->data; } } } + if ((op->opcode == AML_CREATE_FIELD_OP) || + (op->opcode == AML_BIT_FIELD_OP) || + (op->opcode == AML_BYTE_FIELD_OP) || + (op->opcode == AML_WORD_FIELD_OP) || + (op->opcode == AML_DWORD_FIELD_OP)) + { + /* + * Backup to beginning of Create_xXXfield declaration (1 for + * Opcode) + * + * Body_length is unknown until we parse the body + * -4 for the name (last) -- TBD: namestring: may be longer + * than 4? + */ + deferred_op = (ACPI_PARSE2_OBJECT *) op; + + deferred_op->length = parser_state->aml - deferred_op->data; + } /* This op complete, notify the dispatcher */ @@ -841,6 +893,9 @@ close_this_op: + /* + * Finished one argument of the containing scope + */ parser_state->scope->parse_scope.arg_count--; /* Close this Op (may result in parse subtree deletion) */ @@ -850,8 +905,18 @@ } - if (status == AE_CTRL_END) { - acpi_ps_pop_scope (parser_state, &op, &arg_types); + if (status == AE_CTRL_TRANSFER) { + /* + * We are about to transfer to a called method. + */ + walk_state->prev_op = op; + walk_state->prev_arg_types = arg_types; + return (status); + } + + else if (status == AE_CTRL_END) { + acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count); + status = walk_state->ascending_callback (walk_state, op); status = acpi_ps_next_parse_state (walk_state, op, status); acpi_ps_complete_this_op (walk_state, op); @@ -859,9 +924,25 @@ status = AE_OK; } + else if (status == AE_CTRL_TERMINATE) { + status = AE_OK; + + /* Clean up */ + do + { + if (op) { + acpi_ps_complete_this_op (walk_state, op); + } + + acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count); + } while (op); + + return (status); + } + else if (ACPI_FAILURE (status)) { if (op == NULL) { - acpi_ps_pop_scope (parser_state, &op, &arg_types); + acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count); } walk_state->prev_op = op; walk_state->prev_arg_types = arg_types; @@ -870,19 +951,6 @@ * TEMP: */ - if (status == AE_CTRL_TERMINATE) { - status = AE_OK; - - /* Clean up */ - do - { - if (op) { - acpi_ps_complete_this_op (walk_state, op); - } - - acpi_ps_pop_scope (parser_state, &op, &arg_types); - } while (op); - } return (status); } @@ -890,7 +958,7 @@ /* This scope complete? */ if (acpi_ps_has_completed_scope (parser_state)) { - acpi_ps_pop_scope (parser_state, &op, &arg_types); + acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count); } else { @@ -899,6 +967,9 @@ } + + /* Arg_count is non-zero */ + else { /* complex argument, push Op and prepare for argument */ @@ -937,7 +1008,7 @@ acpi_ps_complete_this_op (walk_state, op); } - acpi_ps_pop_scope (parser_state, &op, &arg_types); + acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count); } while (op); @@ -953,7 +1024,7 @@ acpi_ps_complete_this_op (walk_state, op); } - acpi_ps_pop_scope (parser_state, &op, &arg_types); + acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count); } while (op); @@ -1145,6 +1216,7 @@ */ acpi_ds_restart_control_method (walk_state, return_desc); + walk_state->walk_type |= WALK_METHOD_RESTART; } /* diff -urN linux-2.4.0-test10/drivers/acpi/parser/psscope.c linux-2.4.0-test10-lia/drivers/acpi/parser/psscope.c --- linux-2.4.0-test10/drivers/acpi/parser/psscope.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/parser/psscope.c Fri Sep 15 16:38:46 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: psscope - Parser scope stack management routines - * $Revision: 18 $ + * $Revision: 20 $ * *****************************************************************************/ @@ -188,7 +188,8 @@ acpi_ps_pop_scope ( ACPI_PARSE_STATE *parser_state, ACPI_PARSE_OBJECT **op, - u32 *arg_list) + u32 *arg_list, + u32 *arg_count) { ACPI_GENERIC_STATE *scope = parser_state->scope; @@ -204,6 +205,7 @@ *op = scope->parse_scope.op; *arg_list = scope->parse_scope.arg_list; + *arg_count = scope->parse_scope.arg_count; parser_state->pkg_end = scope->parse_scope.pkg_end; /* All done with this scope state structure */ @@ -216,6 +218,7 @@ *op = NULL; *arg_list = 0; + *arg_count = 0; } diff -urN linux-2.4.0-test10/drivers/acpi/parser/psutils.c linux-2.4.0-test10-lia/drivers/acpi/parser/psutils.c --- linux-2.4.0-test10/drivers/acpi/parser/psutils.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/parser/psutils.c Fri Sep 15 16:38:46 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: psutils - Parser miscellaneous utilities (Parser only) - * $Revision: 29 $ + * $Revision: 30 $ * *****************************************************************************/ @@ -460,7 +460,12 @@ u16 opcode) { return ((u8) - (opcode == AML_METHOD_OP || + (opcode == AML_METHOD_OP || + opcode == AML_CREATE_FIELD_OP || + opcode == AML_BIT_FIELD_OP || + opcode == AML_BYTE_FIELD_OP || + opcode == AML_WORD_FIELD_OP || + opcode == AML_DWORD_FIELD_OP || opcode == AML_REGION_OP)); } diff -urN linux-2.4.0-test10/drivers/acpi/parser/pswalk.c linux-2.4.0-test10-lia/drivers/acpi/parser/pswalk.c --- linux-2.4.0-test10/drivers/acpi/parser/pswalk.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/parser/pswalk.c Fri Sep 15 16:38:46 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: pswalk - Parser routines to walk parsed op tree(s) - * $Revision: 45 $ + * $Revision: 46 $ * *****************************************************************************/ @@ -449,7 +449,7 @@ ******************************************************************************/ ACPI_STATUS -acpi_ps_walk_parsed_aml ( +mmmm_acpi_ps_walk_parsed_aml ( ACPI_PARSE_OBJECT *start_op, ACPI_PARSE_OBJECT *end_op, ACPI_OPERAND_OBJECT *mth_desc, diff -urN linux-2.4.0-test10/drivers/acpi/resources/rsaddr.c linux-2.4.0-test10-lia/drivers/acpi/resources/rsaddr.c --- linux-2.4.0-test10/drivers/acpi/resources/rsaddr.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/resources/rsaddr.c Fri Sep 15 16:38:46 2000 @@ -1,12 +1,12 @@ -/****************************************************************************** +/******************************************************************************* * * Module Name: rsaddr - Acpi_rs_address16_resource * Acpi_rs_address16_stream * Acpi_rs_address32_resource * Acpi_rs_address32_stream - * $Revision: 9 $ + * $Revision: 11 $ * - *****************************************************************************/ + ******************************************************************************/ /* * Copyright (C) 2000 R. Byron Moore @@ -33,11 +33,11 @@ MODULE_NAME ("rsaddr") -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_address16_resource * - * PARAMETERS: - * Byte_stream_buffer - Pointer to the resource input byte + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte * stream * Bytes_consumed - u32 pointer that is filled with * the number of bytes consumed from @@ -53,7 +53,7 @@ * structure pointed to by the Output_buffer. Return the * number of bytes consumed from the byte stream. * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_address16_resource ( @@ -253,11 +253,11 @@ } -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_address16_stream * - * PARAMETERS: - * Linked_list - Pointer to the resource linked list + * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with * the number of bytes of the @@ -268,7 +268,7 @@ * DESCRIPTION: Take the linked list resource structure and fills in the * the appropriate bytes in a byte stream * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_address16_stream ( @@ -350,7 +350,6 @@ */ MOVE_UNALIGNED16_TO_16 (buffer, &linked_list->data.address16.min_address_range); - buffer += 2; /* @@ -358,7 +357,6 @@ */ MOVE_UNALIGNED16_TO_16 (buffer, &linked_list->data.address16.max_address_range); - buffer += 2; /* @@ -366,7 +364,6 @@ */ MOVE_UNALIGNED16_TO_16 (buffer, &linked_list->data.address16.address_translation_offset); - buffer += 2; /* @@ -374,7 +371,6 @@ */ MOVE_UNALIGNED16_TO_16 (buffer, &linked_list->data.address16.address_length); - buffer += 2; /* @@ -418,11 +414,12 @@ return (AE_OK); } -/*************************************************************************** + +/******************************************************************************* + * * FUNCTION: Acpi_rs_address32_resource * - * PARAMETERS: - * Byte_stream_buffer - Pointer to the resource input byte + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte * stream * Bytes_consumed - u32 pointer that is filled with * the number of bytes consumed from @@ -438,7 +435,7 @@ * structure pointed to by the Output_buffer. Return the * number of bytes consumed from the byte stream. * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_address32_resource ( @@ -641,11 +638,11 @@ } -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_address32_stream * - * PARAMETERS: - * Linked_list - Pointer to the resource linked list + * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with * the number of bytes of the @@ -656,7 +653,7 @@ * DESCRIPTION: Take the linked list resource structure and fills in the * the appropriate bytes in a byte stream * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_address32_stream ( @@ -676,7 +673,6 @@ * The descriptor field is static */ *buffer = 0x87; - buffer += 1; /* @@ -684,7 +680,6 @@ */ length_field = (u16 *)buffer; - buffer += 2; /* @@ -693,22 +688,17 @@ temp8 = (u8) (linked_list->data.address32.resource_type & 0x03); *buffer = temp8; - buffer += 1; /* * Set the general flags */ temp8 = (u8) (linked_list->data.address32.producer_consumer & 0x01); - temp8 |= (linked_list->data.address32.decode & 0x01) << 1; - temp8 |= (linked_list->data.address32.min_address_fixed & 0x01) << 2; - temp8 |= (linked_list->data.address32.max_address_fixed & 0x01) << 3; *buffer = temp8; - buffer += 1; /* @@ -747,7 +737,6 @@ */ MOVE_UNALIGNED32_TO_32 (buffer, &linked_list->data.address32.min_address_range); - buffer += 4; /* @@ -755,7 +744,6 @@ */ MOVE_UNALIGNED32_TO_32 (buffer, &linked_list->data.address32.max_address_range); - buffer += 4; /* @@ -763,7 +751,6 @@ */ MOVE_UNALIGNED32_TO_32 (buffer, &linked_list->data.address32.address_translation_offset); - buffer += 4; /* @@ -771,7 +758,6 @@ */ MOVE_UNALIGNED32_TO_32 (buffer, &linked_list->data.address32.address_length); - buffer += 4; /* @@ -781,7 +767,6 @@ temp8 = (u8) linked_list->data.address32.resource_source_index; *buffer = temp8; - buffer += 1; temp_pointer = (NATIVE_CHAR *) buffer; diff -urN linux-2.4.0-test10/drivers/acpi/resources/rscalc.c linux-2.4.0-test10-lia/drivers/acpi/resources/rscalc.c --- linux-2.4.0-test10/drivers/acpi/resources/rscalc.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/resources/rscalc.c Mon Sep 18 20:28:29 2000 @@ -1,10 +1,10 @@ -/****************************************************************************** +/******************************************************************************* * * Module Name: rscalc - Acpi_rs_calculate_byte_stream_length * Acpi_rs_calculate_list_length - * $Revision: 9 $ + * $Revision: 11 $ * - *****************************************************************************/ + ******************************************************************************/ /* * Copyright (C) 2000 R. Byron Moore @@ -31,11 +31,11 @@ MODULE_NAME ("rscalc") -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_calculate_byte_stream_length * - * PARAMETERS: - * Linked_list - Pointer to the resource linked list + * PARAMETERS: Linked_list - Pointer to the resource linked list * Size_needed - u32 pointer of the size buffer needed * to properly return the parsed data * @@ -45,7 +45,7 @@ * the size buffer needed to hold the linked list that conveys * the resource data. * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_calculate_byte_stream_length ( @@ -279,15 +279,14 @@ *size_needed = byte_stream_size_needed; return (AE_OK); - -} /* Acpi_rs_calculate_byte_stream_length */ +} -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_calculate_list_length * - * PARAMETERS: - * Byte_stream_buffer - Pointer to the resource byte stream + * PARAMETERS: Byte_stream_buffer - Pointer to the resource byte stream * Byte_stream_buffer_length - Size of Byte_stream_buffer * Size_needed - u32 pointer of the size buffer * needed to properly return the @@ -299,7 +298,7 @@ * the size buffer needed to hold the linked list that conveys * the resource data. * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_calculate_list_length ( @@ -344,7 +343,6 @@ structure_size = sizeof (MEMORY24_RESOURCE) + RESOURCE_LENGTH_NO_DATA; - break; case LARGE_VENDOR_DEFINED: @@ -481,7 +479,6 @@ * Interrupt table length to the Temp8 variable. */ buffer += 3; - temp8 = *buffer; /* @@ -521,7 +518,7 @@ break; -/* 64-bit not currently supported */ +/* TBD: [Future] 64-bit not currently supported */ /* case 0x8A: break; @@ -555,7 +552,6 @@ * trailing bytes */ buffer = byte_stream_buffer; - temp8 = *buffer; if(temp8 & 0x01) { @@ -587,7 +583,6 @@ structure_size = sizeof (IO_RESOURCE) + RESOURCE_LENGTH_NO_DATA + (number_of_interrupts * sizeof (u32)); - break; @@ -621,7 +616,6 @@ structure_size = sizeof (DMA_RESOURCE) + RESOURCE_LENGTH_NO_DATA + (number_of_channels * sizeof (u32)); - break; @@ -634,7 +628,6 @@ * Determine if it there are two or three trailing bytes */ buffer = byte_stream_buffer; - temp8 = *buffer; if(temp8 & 0x01) { @@ -657,7 +650,6 @@ * End Dependent Functions Resource */ bytes_consumed = 1; - structure_size = RESOURCE_LENGTH; break; @@ -667,7 +659,6 @@ * IO Port Resource */ bytes_consumed = 8; - structure_size = sizeof (IO_RESOURCE) + RESOURCE_LENGTH_NO_DATA; break; @@ -679,7 +670,6 @@ * Fixed IO Port Resource */ bytes_consumed = 4; - structure_size = sizeof (FIXED_IO_RESOURCE) + RESOURCE_LENGTH_NO_DATA; break; @@ -700,7 +690,6 @@ * Ensure a 32-bit boundry for the structure */ temp8 = (u8) ROUND_UP_TO_32_bITS (temp8); - structure_size = sizeof (VENDOR_RESOURCE) + RESOURCE_LENGTH_NO_DATA + (temp8 * sizeof (u8)); @@ -713,7 +702,6 @@ * End Tag */ bytes_consumed = 2; - structure_size = RESOURCE_LENGTH; break; @@ -749,14 +737,14 @@ *size_needed = buffer_size; return (AE_OK); +} -} /* Acpi_rs_calculate_list_length */ -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_calculate_pci_routing_table_length * - * PARAMETERS: - * Package_object - Pointer to the package object + * PARAMETERS: Package_object - Pointer to the package object * Buffer_size_needed - u32 pointer of the size buffer * needed to properly return the * parsed data @@ -767,17 +755,22 @@ * calculates the size of the corresponding linked list of * descriptions. * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_calculate_pci_routing_table_length ( ACPI_OPERAND_OBJECT *package_object, u32 *buffer_size_needed) { - u32 number_of_elements; - u32 temp_size_needed; - ACPI_OPERAND_OBJECT **top_object_list; - u32 index; + u32 number_of_elements; + u32 temp_size_needed; + ACPI_OPERAND_OBJECT **top_object_list; + u32 index; + ACPI_OPERAND_OBJECT *package_element; + ACPI_OPERAND_OBJECT **sub_object_list; + u8 name_found; + u32 table_index; + number_of_elements = package_object->package.count; @@ -801,11 +794,6 @@ top_object_list = package_object->package.elements; for (index = 0; index < number_of_elements; index++) { - ACPI_OPERAND_OBJECT *package_element; - ACPI_OPERAND_OBJECT **sub_object_list; - u8 name_found; - u32 table_index; - /* * Dereference the sub-package */ @@ -844,7 +832,6 @@ * terminating NULL */ temp_size_needed += (*sub_object_list)->string.length; - temp_size_needed = ROUND_UP_TO_32_bITS (temp_size_needed); } else { @@ -855,13 +842,17 @@ temp_size_needed += sizeof(u32); } + /* Align the count before returning it */ + temp_size_needed = ROUND_UP_TO_32_bITS (temp_size_needed); + /* * Point to the next ACPI_OPERAND_OBJECT */ top_object_list++; } + *buffer_size_needed = temp_size_needed; return (AE_OK); -} \ No newline at end of file +} diff -urN linux-2.4.0-test10/drivers/acpi/resources/rscreate.c linux-2.4.0-test10-lia/drivers/acpi/resources/rscreate.c --- linux-2.4.0-test10/drivers/acpi/resources/rscreate.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/resources/rscreate.c Fri Sep 15 16:38:46 2000 @@ -1,11 +1,11 @@ -/****************************************************************************** +/******************************************************************************* * * Module Name: rscreate - Acpi_rs_create_resource_list * Acpi_rs_create_pci_routing_table * Acpi_rs_create_byte_stream - * $Revision: 16 $ + * $Revision: 18 $ * - *****************************************************************************/ + ******************************************************************************/ /* * Copyright (C) 2000 R. Byron Moore @@ -182,11 +182,9 @@ * contain a u32 Address, a u8 Pin, a Name and a u8 * Source_index. */ - top_object_list = package_object->package.elements; - - number_of_elements = package_object->package.count; - - user_prt = (PCI_ROUTING_TABLE *) buffer; + top_object_list = package_object->package.elements; + number_of_elements = package_object->package.count; + user_prt = (PCI_ROUTING_TABLE *) buffer; for (index = 0; index < number_of_elements; index++) { /* @@ -196,6 +194,7 @@ * be zero because we cleared the return buffer earlier */ buffer += user_prt->length; + buffer = ROUND_PTR_UP_TO_4 (buffer, u8); user_prt = (PCI_ROUTING_TABLE *) buffer; /* @@ -257,8 +256,6 @@ * Add to the Length field the length of the string */ user_prt->length += (*sub_object_list)->string.length; - user_prt->length = - ROUND_UP_TO_32_bITS (user_prt->length); } else { @@ -280,6 +277,10 @@ } } + /* Now align the current length */ + + user_prt->length = ROUND_UP_TO_32_bITS (user_prt->length); + /* * Dereference the Source Index */ @@ -314,7 +315,6 @@ *output_buffer_length = buffer_size_needed; return (AE_OK); - } @@ -393,6 +393,5 @@ } return (AE_OK); - } diff -urN linux-2.4.0-test10/drivers/acpi/resources/rsdump.c linux-2.4.0-test10-lia/drivers/acpi/resources/rsdump.c --- linux-2.4.0-test10/drivers/acpi/resources/rsdump.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/resources/rsdump.c Fri Sep 15 16:38:46 2000 @@ -1,9 +1,9 @@ -/****************************************************************************** +/******************************************************************************* * * Module Name: rsdump - Functions do dump out the resource structures. - * $Revision: 10 $ + * $Revision: 11 $ * - *****************************************************************************/ + ******************************************************************************/ /* * Copyright (C) 2000 R. Byron Moore @@ -30,7 +30,7 @@ MODULE_NAME ("rsdump") -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_rs_dump_irq * @@ -76,7 +76,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_rs_dump_dma * @@ -156,7 +156,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_rs_dump_start_dependent_functions * @@ -221,7 +221,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_rs_dump_io * @@ -261,7 +261,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_rs_dump_fixed_io * @@ -291,7 +291,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_rs_dump_vendor_specific * @@ -324,7 +324,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_rs_dump_memory24 * @@ -366,7 +366,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_rs_dump_memory32 * @@ -408,7 +408,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_rs_dump_fixed_memory32 * @@ -444,7 +444,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_rs_dump_address16 * @@ -587,7 +587,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_rs_dump_address32 * @@ -729,7 +729,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_rs_dump_extended_irq * @@ -787,7 +787,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_rs_dump_resource_list * @@ -886,7 +886,7 @@ return; } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_rs_dump_irq_list * diff -urN linux-2.4.0-test10/drivers/acpi/resources/rsio.c linux-2.4.0-test10-lia/drivers/acpi/resources/rsio.c --- linux-2.4.0-test10/drivers/acpi/resources/rsio.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/resources/rsio.c Fri Sep 15 16:38:46 2000 @@ -1,4 +1,4 @@ -/****************************************************************************** +/******************************************************************************* * * Module Name: rsio - Acpi_rs_io_resource * Acpi_rs_fixed_io_resource @@ -6,9 +6,9 @@ * Acpi_rs_fixed_io_stream * Acpi_rs_dma_resource * Acpi_rs_dma_stream - * $Revision: 7 $ + * $Revision: 9 $ * - *****************************************************************************/ + ******************************************************************************/ /* * Copyright (C) 2000 R. Byron Moore @@ -35,11 +35,11 @@ MODULE_NAME ("rsio") -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_io_resource * - * PARAMETERS: - * Byte_stream_buffer - Pointer to the resource input byte + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte * stream * Bytes_consumed - u32 pointer that is filled with * the number of bytes consumed from @@ -55,7 +55,7 @@ * structure pointed to by the Output_buffer. Return the * number of bytes consumed from the byte stream. * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_io_resource ( @@ -133,11 +133,11 @@ } -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_fixed_io_resource * - * PARAMETERS: - * Byte_stream_buffer - Pointer to the resource input byte + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte * stream * Bytes_consumed - u32 pointer that is filled with * the number of bytes consumed from @@ -153,7 +153,7 @@ * structure pointed to by the Output_buffer. Return the * number of bytes consumed from the byte stream. * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_fixed_io_resource ( @@ -207,11 +207,11 @@ } -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_io_stream * - * PARAMETERS: - * Linked_list - Pointer to the resource linked list + * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with * the number of bytes of the @@ -222,7 +222,7 @@ * DESCRIPTION: Take the linked list resource structure and fills in the * the appropriate bytes in a byte stream * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_io_stream ( @@ -239,7 +239,6 @@ * The descriptor field is static */ *buffer = 0x47; - buffer += 1; /* @@ -248,7 +247,6 @@ temp8 = (u8) (linked_list->data.io.io_decode & 0x01); *buffer = temp8; - buffer += 1; /* @@ -256,8 +254,7 @@ */ temp16 = (u16) linked_list->data.io.min_base_address; - MOVE_UNALIGNED16_TO_16 (&temp16, buffer); - + MOVE_UNALIGNED16_TO_16 (buffer, &temp16); buffer += 2; /* @@ -265,8 +262,7 @@ */ temp16 = (u16) linked_list->data.io.max_base_address; - MOVE_UNALIGNED16_TO_16 (&temp16, buffer); - + MOVE_UNALIGNED16_TO_16 (buffer, &temp16); buffer += 2; /* @@ -275,7 +271,6 @@ temp8 = (u8) linked_list->data.io.alignment; *buffer = temp8; - buffer += 1; /* @@ -284,7 +279,6 @@ temp8 = (u8) linked_list->data.io.range_length; *buffer = temp8; - buffer += 1; /* @@ -297,11 +291,11 @@ } -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_fixed_io_stream * - * PARAMETERS: - * Linked_list - Pointer to the resource linked list + * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with * the number of bytes of the @@ -312,7 +306,7 @@ * DESCRIPTION: Take the linked list resource structure and fills in the * the appropriate bytes in a byte stream * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_fixed_io_stream ( @@ -337,8 +331,7 @@ */ temp16 = (u16) linked_list->data.fixed_io.base_address; - MOVE_UNALIGNED16_TO_16 (&temp16, buffer); - + MOVE_UNALIGNED16_TO_16 (buffer, &temp16); buffer += 2; /* @@ -347,7 +340,6 @@ temp8 = (u8) linked_list->data.fixed_io.range_length; *buffer = temp8; - buffer += 1; /* @@ -360,11 +352,11 @@ } -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_dma_resource * - * PARAMETERS: - * Byte_stream_buffer - Pointer to the resource input byte + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte * stream * Bytes_consumed - u32 pointer that is filled with * the number of bytes consumed from @@ -380,7 +372,7 @@ * structure pointed to by the Output_buffer. Return the * number of bytes consumed from the byte stream. * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_dma_resource ( @@ -402,14 +394,12 @@ * The number of bytes consumed are Constant */ *bytes_consumed = 3; - output_struct->id = dma; /* * Point to the 8-bits of Byte 1 */ buffer += 1; - temp8 = *buffer; /* Decode the IRQ bits */ @@ -431,9 +421,8 @@ /* * Point to Byte 2 */ - buffer += 1; - - temp8 = *buffer; + buffer += 1; + temp8 = *buffer; /* * Check for transfer preference (Bits[1:0]) @@ -468,11 +457,11 @@ } -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_dma_stream * - * PARAMETERS: - * Linked_list - Pointer to the resource linked list + * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with * the number of bytes of the @@ -483,7 +472,7 @@ * DESCRIPTION: Take the linked list resource structure and fills in the * the appropriate bytes in a byte stream * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_dma_stream ( @@ -501,9 +490,7 @@ * The descriptor field is static */ *buffer = 0x2A; - buffer += 1; - temp8 = 0; /* @@ -518,20 +505,16 @@ } *buffer = temp8; - buffer += 1; /* * Set the DMA Info */ temp8 = (u8) ((linked_list->data.dma.type & 0x03) << 5); - temp8 |= ((linked_list->data.dma.bus_master & 0x01) << 2); - temp8 |= (linked_list->data.dma.transfer & 0x03); *buffer = temp8; - buffer += 1; /* diff -urN linux-2.4.0-test10/drivers/acpi/resources/rsirq.c linux-2.4.0-test10-lia/drivers/acpi/resources/rsirq.c --- linux-2.4.0-test10/drivers/acpi/resources/rsirq.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/resources/rsirq.c Fri Sep 15 16:38:46 2000 @@ -1,12 +1,12 @@ -/****************************************************************************** +/******************************************************************************* * * Module Name: rsirq - Acpi_rs_irq_resource, * Acpi_rs_irq_stream * Acpi_rs_extended_irq_resource * Acpi_rs_extended_irq_stream - * $Revision: 8 $ + * $Revision: 10 $ * - *****************************************************************************/ + ******************************************************************************/ /* * Copyright (C) 2000 R. Byron Moore @@ -33,11 +33,11 @@ MODULE_NAME ("rsirq") -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_irq_resource * - * PARAMETERS: - * Byte_stream_buffer - Pointer to the resource input byte + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte * stream * Bytes_consumed - u32 pointer that is filled with * the number of bytes consumed from @@ -53,7 +53,7 @@ * structure pointed to by the Output_buffer. Return the * number of bytes consumed from the byte stream. * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_irq_resource ( @@ -77,9 +77,7 @@ * (Bits:0-1) */ temp8 = *buffer; - *bytes_consumed = (temp8 & 0x03) + 1; - output_struct->id = irq; /* @@ -91,6 +89,7 @@ output_struct->data.irq.number_of_interrupts = 0; /* Decode the IRQ bits */ + for (i = 0, index = 0; index < 16; index++) { if((temp16 >> index) & 0x01) { output_struct->data.irq.interrupts[i] = index; @@ -109,7 +108,6 @@ */ if (4 == *bytes_consumed) { buffer += 2; - temp8 = *buffer; /* @@ -166,11 +164,11 @@ } -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_irq_stream * - * PARAMETERS: - * Linked_list - Pointer to the resource linked list + * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with * the number of bytes of the @@ -181,7 +179,7 @@ * DESCRIPTION: Take the linked list resource structure and fills in the * the appropriate bytes in a byte stream * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_irq_stream ( @@ -213,7 +211,6 @@ } buffer += 1; - temp16 = 0; /* @@ -227,8 +224,7 @@ temp16 |= 0x1 << temp8; } - MOVE_UNALIGNED16_TO_16 (&temp16, buffer); - + MOVE_UNALIGNED16_TO_16 (buffer, &temp16); buffer += 2; /* @@ -236,7 +232,6 @@ */ if (IRQinfo_byte_needed) { temp8 = 0; - temp8 = (u8) ((linked_list->data.irq.shared_exclusive & 0x01) << 4); @@ -251,7 +246,6 @@ } *buffer = temp8; - buffer += 1; } @@ -265,11 +259,11 @@ } -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_extended_irq_resource * - * PARAMETERS: - * Byte_stream_buffer - Pointer to the resource input byte + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte * stream * Bytes_consumed - u32 pointer that is filled with * the number of bytes consumed from @@ -285,7 +279,7 @@ * structure pointed to by the Output_buffer. Return the * number of bytes consumed from the byte stream. * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_extended_irq_resource ( @@ -450,11 +444,11 @@ } -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_extended_irq_stream * - * PARAMETERS: - * Linked_list - Pointer to the resource linked list + * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with * the number of bytes of the @@ -463,9 +457,9 @@ * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code * * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * the appropriate bytes in a byte stream * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_extended_irq_stream ( @@ -518,7 +512,6 @@ temp8 = (u8) linked_list->data.extended_irq.number_of_interrupts; *buffer = temp8; - buffer += 1; for (index = 0; diff -urN linux-2.4.0-test10/drivers/acpi/resources/rslist.c linux-2.4.0-test10-lia/drivers/acpi/resources/rslist.c --- linux-2.4.0-test10/drivers/acpi/resources/rslist.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/resources/rslist.c Fri Sep 15 16:38:46 2000 @@ -1,10 +1,10 @@ -/****************************************************************************** +/******************************************************************************* * * Module Name: rslist - Acpi_rs_byte_stream_to_list * Acpi_list_to_byte_stream - * $Revision: 6 $ + * $Revision: 8 $ * - *****************************************************************************/ + ******************************************************************************/ /* * Copyright (C) 2000 R. Byron Moore @@ -32,11 +32,11 @@ MODULE_NAME ("rslist") -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_byte_stream_to_list * - * PARAMETERS: - * Byte_stream_buffer - Pointer to the resource byte stream + * PARAMETERS: Byte_stream_buffer - Pointer to the resource byte stream * Byte_stream_buffer_length - Length of Byte_stream_buffer * Output_buffer - Pointer to the buffer that will * contain the output structures @@ -46,7 +46,7 @@ * DESCRIPTION: Takes the resource byte stream and parses it, creating a * linked list of resources in the caller's output buffer * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_byte_stream_to_list ( @@ -157,7 +157,7 @@ break; -/* 64-bit not currently supported */ +/* TBD: [Future] 64-bit not currently supported */ /* case 0x8A: break; @@ -309,15 +309,14 @@ } return (AE_OK); - -} /* Acpi_rs_byte_stream_to_list */ +} -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_list_to_byte_stream * - * PARAMETERS: - * Linked_list - Pointer to the resource linked list + * PARAMETERS: Linked_list - Pointer to the resource linked list * Byte_steam_size_needed - Calculated size of the byte stream * needed from calling * Acpi_rs_calculate_byte_stream_length() @@ -332,7 +331,7 @@ * DESCRIPTION: Takes the resource linked list and parses it, creating a * byte stream of resources in the caller's output buffer * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_list_to_byte_stream ( @@ -503,6 +502,5 @@ } return (AE_OK); - -} /* Acpi_rs_list_to_byte_stream */ +} diff -urN linux-2.4.0-test10/drivers/acpi/resources/rsmemory.c linux-2.4.0-test10-lia/drivers/acpi/resources/rsmemory.c --- linux-2.4.0-test10/drivers/acpi/resources/rsmemory.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/resources/rsmemory.c Fri Sep 15 16:38:46 2000 @@ -1,4 +1,4 @@ -/****************************************************************************** +/******************************************************************************* * * Module Name: rsmem24 - Acpi_rs_memory24_resource * Acpi_rs_memory24_stream @@ -6,9 +6,9 @@ * Acpi_rs_fixed_memory32_resource * Acpi_rs_memory32_range_stream * Acpi_rs_fixed_memory32_stream - * $Revision: 7 $ + * $Revision: 9 $ * - *****************************************************************************/ + ******************************************************************************/ /* * Copyright (C) 2000 R. Byron Moore @@ -35,11 +35,11 @@ MODULE_NAME ("rsmemory") -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_memory24_resource * - * PARAMETERS: - * Byte_stream_buffer - Pointer to the resource input byte + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte * stream * Bytes_consumed - u32 pointer that is filled with * the number of bytes consumed from @@ -55,7 +55,7 @@ * structure pointed to by the Output_buffer. Return the * number of bytes consumed from the byte stream. * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_memory24_resource ( @@ -78,54 +78,42 @@ buffer += 1; MOVE_UNALIGNED16_TO_16 (&temp16, buffer); - buffer += 2; - *bytes_consumed = temp16 + 3; - output_struct->id = memory24; /* * Check Byte 3 the Read/Write bit */ temp8 = *buffer; - buffer += 1; - output_struct->data.memory24.read_write_attribute = temp8 & 0x01; /* * Get Min_base_address (Bytes 4-5) */ MOVE_UNALIGNED16_TO_16 (&temp16, buffer); - buffer += 2; - output_struct->data.memory24.min_base_address = temp16; /* * Get Max_base_address (Bytes 6-7) */ MOVE_UNALIGNED16_TO_16 (&temp16, buffer); - buffer += 2; - output_struct->data.memory24.max_base_address = temp16; /* * Get Alignment (Bytes 8-9) */ MOVE_UNALIGNED16_TO_16 (&temp16, buffer); - buffer += 2; - output_struct->data.memory24.alignment = temp16; /* * Get Range_length (Bytes 10-11) */ MOVE_UNALIGNED16_TO_16 (&temp16, buffer); - output_struct->data.memory24.range_length = temp16; /* @@ -142,11 +130,11 @@ } -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_memory24_stream * - * PARAMETERS: - * Linked_list - Pointer to the resource linked list + * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with * the number of bytes of the @@ -157,7 +145,7 @@ * DESCRIPTION: Take the linked list resource structure and fills in the * the appropriate bytes in a byte stream * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_memory24_stream ( @@ -174,16 +162,13 @@ * The descriptor field is static */ *buffer = 0x81; - buffer += 1; /* * The length field is static */ temp16 = 0x09; - MOVE_UNALIGNED16_TO_16 (buffer, &temp16); - buffer += 2; /* @@ -227,11 +212,11 @@ } -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_memory32_range_resource * - * PARAMETERS: - * Byte_stream_buffer - Pointer to the resource input byte + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte * stream * Bytes_consumed - u32 pointer that is filled with * the number of bytes consumed from @@ -247,7 +232,7 @@ * structure pointed to by the Output_buffer. Return the * number of bytes consumed from the byte stream. * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_memory32_range_resource ( @@ -332,11 +317,11 @@ } -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_fixed_memory32_resource * - * PARAMETERS: - * Byte_stream_buffer - Pointer to the resource input byte + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte * stream * Bytes_consumed - u32 pointer that is filled with * the number of bytes consumed from @@ -352,7 +337,7 @@ * structure pointed to by the Output_buffer. Return the * number of bytes consumed from the byte stream. * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_fixed_memory32_resource ( @@ -414,11 +399,11 @@ } -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_memory32_range_stream * - * PARAMETERS: - * Linked_list - Pointer to the resource linked list + * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with * the number of bytes of the @@ -429,7 +414,7 @@ * DESCRIPTION: Take the linked list resource structure and fills in the * the appropriate bytes in a byte stream * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_memory32_range_stream ( @@ -497,11 +482,11 @@ } -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_fixed_memory32_stream * - * PARAMETERS: - * Linked_list - Pointer to the resource linked list + * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with * the number of bytes of the @@ -512,7 +497,7 @@ * DESCRIPTION: Take the linked list resource structure and fills in the * the appropriate bytes in a byte stream * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_fixed_memory32_stream ( diff -urN linux-2.4.0-test10/drivers/acpi/resources/rsmisc.c linux-2.4.0-test10-lia/drivers/acpi/resources/rsmisc.c --- linux-2.4.0-test10/drivers/acpi/resources/rsmisc.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/resources/rsmisc.c Fri Sep 15 16:38:46 2000 @@ -1,4 +1,4 @@ -/****************************************************************************** +/******************************************************************************* * * Module Name: rsmisc - Acpi_rs_end_tag_resource * Acpi_rs_end_tag_stream @@ -8,9 +8,9 @@ * Acpi_rs_end_dependent_functions_resource * Acpi_rs_start_dependent_functions_stream * Acpi_rs_end_dependent_functions_stream - * $Revision: 7 $ + * $Revision: 9 $ * - *****************************************************************************/ + ******************************************************************************/ /* * Copyright (C) 2000 R. Byron Moore @@ -37,11 +37,11 @@ MODULE_NAME ("rsmisc") -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_end_tag_resource * - * PARAMETERS: - * Byte_stream_buffer - Pointer to the resource input byte + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte * stream * Bytes_consumed - u32 pointer that is filled with * the number of bytes consumed from @@ -57,7 +57,7 @@ * structure pointed to by the Output_buffer. Return the * number of bytes consumed from the byte stream. * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_end_tag_resource ( @@ -94,11 +94,11 @@ } -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_end_tag_stream * - * PARAMETERS: - * Linked_list - Pointer to the resource linked list + * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with * the number of bytes of the @@ -109,7 +109,7 @@ * DESCRIPTION: Take the linked list resource structure and fills in the * the appropriate bytes in a byte stream * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_end_tag_stream ( @@ -125,7 +125,6 @@ * The descriptor field is static */ *buffer = 0x79; - buffer += 1; /* @@ -135,7 +134,6 @@ temp8 = 0; *buffer = temp8; - buffer += 1; /* @@ -147,11 +145,12 @@ return (AE_OK); } -/*************************************************************************** + +/******************************************************************************* + * * FUNCTION: Acpi_rs_vendor_resource * - * PARAMETERS: - * Byte_stream_buffer - Pointer to the resource input byte + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte * stream * Bytes_consumed - u32 pointer that is filled with * the number of bytes consumed from @@ -167,7 +166,7 @@ * structure pointed to by the Output_buffer. Return the * number of bytes consumed from the byte stream. * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_vendor_resource ( @@ -230,7 +229,6 @@ } output_struct->id = vendor_specific; - output_struct->data.vendor_specific.length = temp16; for (index = 0; index < temp16; index++) { @@ -259,11 +257,11 @@ } -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_vendor_stream * - * PARAMETERS: - * Linked_list - Pointer to the resource linked list + * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with * the number of bytes of the @@ -274,7 +272,7 @@ * DESCRIPTION: Take the linked list resource structure and fills in the * the appropriate bytes in a byte stream * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_vendor_stream ( @@ -300,13 +298,11 @@ * Set the descriptor field and length bytes */ *buffer = 0x84; - buffer += 1; temp16 = (u16) linked_list->data.vendor_specific.length; - MOVE_UNALIGNED16_TO_16 (&temp16, buffer); - + MOVE_UNALIGNED16_TO_16 (buffer, &temp16); buffer += 2; } @@ -319,11 +315,9 @@ * Set the descriptor field */ temp8 = 0x70; - temp8 |= linked_list->data.vendor_specific.length; *buffer = temp8; - buffer += 1; } @@ -332,6 +326,7 @@ */ for (index = 0; index < linked_list->data.vendor_specific.length; index++) { temp8 = linked_list->data.vendor_specific.reserved[index]; + *buffer = temp8; buffer += 1; } @@ -345,11 +340,12 @@ return (AE_OK); } -/*************************************************************************** + +/******************************************************************************* + * * FUNCTION: Acpi_rs_start_dependent_functions_resource * - * PARAMETERS: - * Byte_stream_buffer - Pointer to the resource input byte + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte * stream * Bytes_consumed - u32 pointer that is filled with * the number of bytes consumed from @@ -365,7 +361,7 @@ * structure pointed to by the Output_buffer. Return the * number of bytes consumed from the byte stream. * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_start_dependent_functions_resource ( @@ -441,11 +437,11 @@ } -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_end_dependent_functions_resource * - * PARAMETERS: - * Byte_stream_buffer - Pointer to the resource input byte + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte * stream * Bytes_consumed - u32 pointer that is filled with * the number of bytes consumed from @@ -461,7 +457,7 @@ * structure pointed to by the Output_buffer. Return the * number of bytes consumed from the byte stream. * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_end_dependent_functions_resource ( @@ -498,11 +494,11 @@ } -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_start_dependent_functions_stream * - * PARAMETERS: - * Linked_list - Pointer to the resource linked list + * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with * the number of bytes of the @@ -513,7 +509,8 @@ * DESCRIPTION: Take the linked list resource structure and fills in the * the appropriate bytes in a byte stream * - ***************************************************************************/ + ******************************************************************************/ + ACPI_STATUS acpi_rs_start_dependent_functions_stream ( RESOURCE *linked_list, @@ -537,18 +534,15 @@ } else { *buffer = 0x31; - buffer += 1; /* * Set the Priority Byte Definition */ temp8 = 0; - temp8 = (u8) ((linked_list->data.start_dependent_functions.performance_robustness & 0x03) << 2); - temp8 |= (linked_list->data.start_dependent_functions.compatibility_priority & 0x03); @@ -568,11 +562,11 @@ } -/*************************************************************************** +/******************************************************************************* + * * FUNCTION: Acpi_rs_end_dependent_functions_stream * - * PARAMETERS: - * Linked_list - Pointer to the resource linked list + * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with * the number of bytes of the @@ -583,7 +577,7 @@ * DESCRIPTION: Take the linked list resource structure and fills in the * the appropriate bytes in a byte stream * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_rs_end_dependent_functions_stream ( @@ -599,7 +593,6 @@ * The descriptor field is static */ *buffer = 0x38; - buffer += 1; /* diff -urN linux-2.4.0-test10/drivers/acpi/resources/rsutils.c linux-2.4.0-test10-lia/drivers/acpi/resources/rsutils.c --- linux-2.4.0-test10/drivers/acpi/resources/rsutils.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/resources/rsutils.c Fri Sep 15 16:38:46 2000 @@ -1,9 +1,9 @@ -/****************************************************************************** +/******************************************************************************* * * Module Name: rsutils - Utilities for the resource manager - * $Revision: 10 $ + * $Revision: 12 $ * - *****************************************************************************/ + ******************************************************************************/ /* * Copyright (C) 2000 R. Byron Moore @@ -33,7 +33,7 @@ MODULE_NAME ("rsutils") -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_rs_get_prt_method_data * @@ -117,7 +117,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_rs_get_crs_method_data * @@ -200,7 +200,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_rs_get_prs_method_data * @@ -281,7 +281,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_rs_set_srs_method_data * @@ -310,6 +310,7 @@ u8 *byte_stream = NULL; u32 buffer_size_needed = 0; + /* already validated params, so we won't repeat here */ /* @@ -325,7 +326,6 @@ status = acpi_rs_create_byte_stream (in_buffer->pointer, byte_stream, &buffer_size_needed); - /* * We expect a return of AE_BUFFER_OVERFLOW * if not, exit with the error @@ -338,7 +338,6 @@ * Allocate the buffer needed */ byte_stream = acpi_cm_callocate(buffer_size_needed); - if (NULL == byte_stream) { return (AE_NO_MEMORY); } @@ -349,7 +348,6 @@ status = acpi_rs_create_byte_stream (in_buffer->pointer, byte_stream, &buffer_size_needed); - if (ACPI_FAILURE (status)) { goto cleanup; } diff -urN linux-2.4.0-test10/drivers/acpi/resources/rsxface.c linux-2.4.0-test10-lia/drivers/acpi/resources/rsxface.c --- linux-2.4.0-test10/drivers/acpi/resources/rsxface.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/resources/rsxface.c Fri Sep 15 16:38:46 2000 @@ -1,9 +1,9 @@ -/****************************************************************************** +/******************************************************************************* * * Module Name: rsxface - Public interfaces to the ACPI subsystem - * $Revision: 7 $ + * $Revision: 8 $ * - *****************************************************************************/ + ******************************************************************************/ /* * Copyright (C) 2000 R. Byron Moore @@ -33,7 +33,7 @@ MODULE_NAME ("rsxface") -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_get_irq_routing_table * @@ -83,7 +83,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_get_current_resources * @@ -134,7 +134,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_get_possible_resources * @@ -142,7 +142,7 @@ * device we are querying * Ret_buffer - a pointer to a buffer to receive the * resources for the device - * + * * RETURN: Status - the status of the call * * DESCRIPTION: This function is called to get a list of the possible resources @@ -182,7 +182,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_set_current_resources * diff -urN linux-2.4.0-test10/drivers/acpi/table.c linux-2.4.0-test10-lia/drivers/acpi/table.c --- linux-2.4.0-test10/drivers/acpi/table.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/table.c Fri Sep 15 16:38:46 2000 @@ -286,18 +286,16 @@ { printk(KERN_INFO "ACPI: support found\n"); } - else if (acpi_find_chipset()) { - acpi_terminate(); - return -1; + else if (ACPI_SUCCESS(acpi_find_chipset())) { + printk(KERN_INFO "ACPI: Tables not found. Using chipset ACPI support.\n"); } - - if (acpi_fetch_facp()) { + else { + printk(KERN_INFO "ACPI: Not supported.\n"); acpi_terminate(); return -1; } - if (!ACPI_SUCCESS(acpi_load_namespace())) { - printk(KERN_ERR "ACPI: namespace load failed\n"); + if (acpi_fetch_facp()) { acpi_terminate(); return -1; } diff -urN linux-2.4.0-test10/drivers/acpi/tables/tbget.c linux-2.4.0-test10-lia/drivers/acpi/tables/tbget.c --- linux-2.4.0-test10/drivers/acpi/tables/tbget.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/tables/tbget.c Fri Sep 15 16:38:46 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: tbget - ACPI Table get* routines - * $Revision: 22 $ + * $Revision: 24 $ * *****************************************************************************/ @@ -266,9 +266,14 @@ * determine if there are enough tables to continue. */ - acpi_tb_delete_single_table (&table_info); + acpi_tb_uninstall_table (&table_info); } } + + + /* Dump the FACP Header */ + + /* Dump the entire FACP */ /* diff -urN linux-2.4.0-test10/drivers/acpi/tables/tbinstal.c linux-2.4.0-test10-lia/drivers/acpi/tables/tbinstal.c --- linux-2.4.0-test10/drivers/acpi/tables/tbinstal.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/tables/tbinstal.c Fri Sep 15 16:38:46 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: tbinstal - ACPI table installation and removal - * $Revision: 29 $ + * $Revision: 32 $ * *****************************************************************************/ @@ -307,7 +307,7 @@ * Memory can either be mapped or allocated */ - for (type = 0; type < ACPI_TABLE_MAX; type++) { + for (type = 0; type < NUM_ACPI_TABLES; type++) { acpi_tb_delete_acpi_table (type); } @@ -381,6 +381,9 @@ case ACPI_TABLE_SBST: acpi_gbl_SBST = NULL; + case ACPI_TABLE_SPIC: + break; + default: break; } @@ -424,7 +427,7 @@ */ for (i = 0; i < count; i++) { - table_desc = acpi_tb_delete_single_table (table_desc); + table_desc = acpi_tb_uninstall_table (table_desc); } return; @@ -439,37 +442,20 @@ * * RETURN: None. * - * DESCRIPTION: Free the memory associated with an internal ACPI table that - * is either installed or has never been installed. - * Table mutex should be locked. + * DESCRIPTION: Low-level free for a single ACPI table. Handles cases where + * the table was allocated a buffer or was mapped. * ******************************************************************************/ -ACPI_TABLE_DESC * +void acpi_tb_delete_single_table ( ACPI_TABLE_DESC *table_desc) { - ACPI_TABLE_DESC *next_desc; - if (!table_desc) { - return (NULL); - } - - - /* Unlink the descriptor */ - - if (table_desc->prev) { - table_desc->prev->next = table_desc->next; - } - - if (table_desc->next) { - table_desc->next->prev = table_desc->prev; + return; } - - /* Free the memory allocated for the table itself */ - if (table_desc->pointer) { /* Valid table, determine type of memory allocation */ @@ -477,7 +463,6 @@ { case ACPI_MEM_NOT_ALLOCATED: - break; @@ -493,10 +478,52 @@ break; } } +} - /* Free the table descriptor (Don't delete the list head, tho) */ +/******************************************************************************* + * + * FUNCTION: Acpi_tb_uninstall_table + * + * PARAMETERS: Table_info - A table info struct + * + * RETURN: None. + * + * DESCRIPTION: Free the memory associated with an internal ACPI table that + * is either installed or has never been installed. + * Table mutex should be locked. + * + ******************************************************************************/ + +ACPI_TABLE_DESC * +acpi_tb_uninstall_table ( + ACPI_TABLE_DESC *table_desc) +{ + ACPI_TABLE_DESC *next_desc; + + + if (!table_desc) { + return (NULL); + } + + /* Unlink the descriptor */ + + if (table_desc->prev) { + table_desc->prev->next = table_desc->next; + } + + if (table_desc->next) { + table_desc->next->prev = table_desc->prev; + } + + + /* Free the memory allocated for the table itself */ + + acpi_tb_delete_single_table (table_desc); + + + /* Free the table descriptor (Don't delete the list head, tho) */ if ((table_desc->prev) == (table_desc->next)) { diff -urN linux-2.4.0-test10/drivers/acpi/tables/tbtable.c linux-2.4.0-test10-lia/drivers/acpi/tables/tbtable.c --- linux-2.4.0-test10/drivers/acpi/tables/tbtable.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/tables/tbtable.c Wed Sep 20 13:27:02 2000 @@ -75,7 +75,7 @@ * RSDP structure was found; Now get the RSDT */ - status = acpi_tb_get_table ((void *) acpi_gbl_RSDP->rsdt_physical_address, NULL, + status = acpi_tb_get_table ((void *) (NATIVE_UINT)acpi_gbl_RSDP->rsdt_physical_address, NULL, &table_info); if (ACPI_FAILURE (status)) { if (status == AE_BAD_SIGNATURE) { diff -urN linux-2.4.0-test10/drivers/acpi/tables/tbutils.c linux-2.4.0-test10-lia/drivers/acpi/tables/tbutils.c --- linux-2.4.0-test10/drivers/acpi/tables/tbutils.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/tables/tbutils.c Fri Sep 15 16:38:46 2000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: tbutils - Table manipulation utilities - * $Revision: 26 $ + * $Revision: 27 $ * *****************************************************************************/ @@ -107,7 +107,9 @@ /* Check for a pointer within the DSDT */ - if (IS_IN_ACPI_TABLE (where, acpi_gbl_DSDT)) { + if ((acpi_gbl_DSDT) && + (IS_IN_ACPI_TABLE (where, acpi_gbl_DSDT))) + { return (TRUE); } diff -urN linux-2.4.0-test10/drivers/acpi/tables/tbxface.c linux-2.4.0-test10-lia/drivers/acpi/tables/tbxface.c --- linux-2.4.0-test10/drivers/acpi/tables/tbxface.c Fri Sep 15 14:30:30 2000 +++ linux-2.4.0-test10-lia/drivers/acpi/tables/tbxface.c Fri Sep 15 16:38:46 2000 @@ -2,7 +2,7 @@ * * Module Name: tbxface - Public interfaces to the ACPI subsystem * ACPI table oriented interfaces - * $Revision: 24 $ + * $Revision: 27 $ * *****************************************************************************/ @@ -69,6 +69,11 @@ goto error_exit; } + status = acpi_ns_load_namespace (); + if (ACPI_FAILURE (status)) { + goto error_exit; + } + return (AE_OK); @@ -119,9 +124,22 @@ status = acpi_tb_install_table (NULL, &table_info); if (ACPI_FAILURE (status)) { - /* TBD: [Errors] must free table allocated by Acpi_tb_get_table */ + /* Free table allocated by Acpi_tb_get_table */ + + acpi_tb_delete_single_table (&table_info); + return (status); } + + status = acpi_ns_load_table (table_info.installed_desc, acpi_gbl_root_node); + if (ACPI_FAILURE (status)) { + /* Uninstall table and free the buffer */ + + acpi_tb_uninstall_table (table_info.installed_desc); + return (status); + } + + return (status); } @@ -289,12 +307,11 @@ /* - * Must have a buffer + * If we have a buffer, we must have a length too */ if ((instance == 0) || (!ret_buffer) || - (!ret_buffer->pointer) || - (!ret_buffer->length)) + ((!ret_buffer->pointer) && (ret_buffer->length))) { return (AE_BAD_PARAMETER); } diff -urN linux-2.4.0-test10/drivers/char/Makefile linux-2.4.0-test10-lia/drivers/char/Makefile --- linux-2.4.0-test10/drivers/char/Makefile Sun Oct 1 19:45:29 2000 +++ linux-2.4.0-test10-lia/drivers/char/Makefile Mon Oct 30 22:17:11 2000 @@ -112,6 +112,7 @@ obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o +obj-$(CONFIG_SIM_SERIAL) += simserial.o obj-$(CONFIG_ROCKETPORT) += rocket.o obj-$(CONFIG_MOXA_SMARTIO) += mxser.o obj-$(CONFIG_MOXA_INTELLIO) += moxa.o diff -urN linux-2.4.0-test10/drivers/char/drm/vm.c linux-2.4.0-test10-lia/drivers/char/drm/vm.c --- linux-2.4.0-test10/drivers/char/drm/vm.c Sun Oct 1 20:00:00 2000 +++ linux-2.4.0-test10-lia/drivers/char/drm/vm.c Mon Oct 30 22:48:30 2000 @@ -272,6 +272,7 @@ drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_map_t *map = NULL; + unsigned long off; int i; DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", @@ -288,7 +289,16 @@ bit longer. */ for (i = 0; i < dev->map_count; i++) { map = dev->maplist[i]; - if (map->offset == VM_OFFSET(vma)) break; + off = map->offset ^ VM_OFFSET(vma); +#ifdef __ia64__ + /* + * Ignore region bits, makes IA32 processes happier + * XXX This is a hack... + */ + off &= ~0xe000000000000000; +#endif // __ia64__ + if (off == 0) + break; } if (i >= dev->map_count) return -EINVAL; diff -urN linux-2.4.0-test10/drivers/char/mem.c linux-2.4.0-test10-lia/drivers/char/mem.c --- linux-2.4.0-test10/drivers/char/mem.c Tue Oct 10 10:33:51 2000 +++ linux-2.4.0-test10-lia/drivers/char/mem.c Wed Nov 1 14:57:56 2000 @@ -195,8 +195,12 @@ * through a file pointer that was marked O_SYNC will be * done non-cached. */ - if (noncached_address(offset) || (file->f_flags & O_SYNC)) + if (noncached_address(offset) || (file->f_flags & O_SYNC) + || vma->vm_flags & VM_NONCACHED) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + if (vma->vm_flags & VM_WRITECOMBINED) + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); /* * Don't dump addresses that are not real memory to a core file. diff -urN linux-2.4.0-test10/drivers/char/simserial.c linux-2.4.0-test10-lia/drivers/char/simserial.c --- linux-2.4.0-test10/drivers/char/simserial.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/drivers/char/simserial.c Wed Nov 1 23:18:55 2000 @@ -0,0 +1,1095 @@ +/* + * Simulated Serial Driver (fake serial) + * + * This driver is mostly used for bringup purposes and will go away. + * It has a strong dependency on the system console. All outputs + * are rerouted to the same facility as the one used by printk which, in our + * case means sys_sim.c console (goes via the simulator). The code hereafter + * is completely leveraged from the serial.c driver. + * + * Copyright (C) 1999-2000 Hewlett-Packard Co + * Copyright (C) 1999 Stephane Eranian + * Copyright (C) 2000 David Mosberger-Tang + * + * 02/04/00 D. Mosberger Merged in serial.c bug fixes in rs_close(). + * 02/25/00 D. Mosberger Synced up with 2.3.99pre-5 version of serial.c. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#undef SIMSERIAL_DEBUG /* define this to get some debug information */ + +#define KEYBOARD_INTR 3 /* must match with simulator! */ + +#define NR_PORTS 1 /* only one port for now */ +#define SERIAL_INLINE 1 + +#ifdef SERIAL_INLINE +#define _INLINE_ inline +#endif + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT) + +#define SSC_GETCHAR 21 + +extern long ia64_ssc (long, long, long, long, int); +extern void ia64_ssc_connect_irq (long intr, long irq); + +static char *serial_name = "SimSerial driver"; +static char *serial_version = "0.6"; + +/* + * This has been extracted from asm/serial.h. We need one eventually but + * I don't know exactly what we're going to put in it so just fake one + * for now. + */ +#define BASE_BAUD ( 1843200 / 16 ) + +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) + +/* + * Most of the values here are meaningless to this particular driver. + * However some values must be preserved for the code (leveraged from serial.c + * to work correctly). + * port must not be 0 + * type must not be UNKNOWN + * So I picked arbitrary (guess from where?) values instead + */ +static struct serial_state rs_table[NR_PORTS]={ + /* UART CLK PORT IRQ FLAGS */ + { 0, BASE_BAUD, 0x3F8, 0, STD_COM_FLAGS,0,PORT_16550 } /* ttyS0 */ +}; + +/* + * Just for the fun of it ! + */ +static struct serial_uart_config uart_config[] = { + { "unknown", 1, 0 }, + { "8250", 1, 0 }, + { "16450", 1, 0 }, + { "16550", 1, 0 }, + { "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO }, + { "cirrus", 1, 0 }, + { "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH }, + { "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO | + UART_STARTECH }, + { "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO}, + { 0, 0} +}; + +static struct tty_driver serial_driver, callout_driver; +static int serial_refcount; + +static struct async_struct *IRQ_ports[NR_IRQS]; +static struct tty_struct *serial_table[NR_PORTS]; +static struct termios *serial_termios[NR_PORTS]; +static struct termios *serial_termios_locked[NR_PORTS]; + +static struct console *console; + +static unsigned char *tmp_buf; +static DECLARE_MUTEX(tmp_buf_sem); + +extern struct console *console_drivers; /* from kernel/printk.c */ + +/* + * ------------------------------------------------------------ + * rs_stop() and rs_start() + * + * This routines are called before setting or resetting tty->stopped. + * They enable or disable transmitter interrupts, as necessary. + * ------------------------------------------------------------ + */ +static void rs_stop(struct tty_struct *tty) +{ +#ifdef SIMSERIAL_DEBUG + printk("rs_stop: tty->stopped=%d tty->hw_stopped=%d tty->flow_stopped=%d\n", + tty->stopped, tty->hw_stopped, tty->flow_stopped); +#endif + +} + +static void rs_start(struct tty_struct *tty) +{ +#if SIMSERIAL_DEBUG + printk("rs_start: tty->stopped=%d tty->hw_stopped=%d tty->flow_stopped=%d\n", + tty->stopped, tty->hw_stopped, tty->flow_stopped); +#endif +} + +static void receive_chars(struct tty_struct *tty) +{ + unsigned char ch; + static unsigned char seen_esc = 0; + + while ( (ch = ia64_ssc(0, 0, 0, 0, SSC_GETCHAR)) ) { + if ( ch == 27 && seen_esc == 0 ) { + seen_esc = 1; + continue; + } else { + if ( seen_esc==1 && ch == 'O' ) { + seen_esc = 2; + continue; + } else if ( seen_esc == 2 ) { + if ( ch == 'P' ) show_state(); /* F1 key */ + if ( ch == 'Q' ) show_buffers(); /* F2 key */ + seen_esc = 0; + continue; + } + } + seen_esc = 0; + if (tty->flip.count >= TTY_FLIPBUF_SIZE) break; + + *tty->flip.char_buf_ptr = ch; + + *tty->flip.flag_buf_ptr = 0; + + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + } + tty_flip_buffer_push(tty); +} + +/* + * This is the serial driver's interrupt routine for a single port + */ +static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs) +{ + struct async_struct * info; + + /* + * I don't know exactly why they don't use the dev_id opaque data + * pointer instead of this extra lookup table + */ + info = IRQ_ports[irq]; + if (!info || !info->tty) { + printk("simrs_interrupt_single: info|tty=0 info=%p problem\n", info); + return; + } + /* + * pretty simple in our case, because we only get interrupts + * on inbound traffic + */ + receive_chars(info->tty); +} + +/* + * ------------------------------------------------------------------- + * Here ends the serial interrupt routines. + * ------------------------------------------------------------------- + */ + +#if 0 +/* + * not really used in our situation so keep them commented out for now + */ +static DECLARE_TASK_QUEUE(tq_serial); /* used to be at the top of the file */ +static void do_serial_bh(void) +{ + run_task_queue(&tq_serial); + printk("do_serial_bh: called\n"); +} +#endif + +static void do_softint(void *private_) +{ + printk("simserial: do_softint called\n"); +} + +static void rs_put_char(struct tty_struct *tty, unsigned char ch) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (!tty || !info->xmit.buf) return; + + save_flags(flags); cli(); + if (CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) == 0) { + restore_flags(flags); + return; + } + info->xmit.buf[info->xmit.head] = ch; + info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1); + restore_flags(flags); +} + +static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) +{ + int count; + unsigned long flags; + + save_flags(flags); cli(); + + if (info->x_char) { + char c = info->x_char; + + console->write(console, &c, 1); + + info->state->icount.tx++; + info->x_char = 0; + + goto out; + } + + if (info->xmit.head == info->xmit.tail || info->tty->stopped || info->tty->hw_stopped) { +#ifdef SIMSERIAL_DEBUG + printk("transmit_chars: head=%d, tail=%d, stopped=%d\n", + info->xmit.head, info->xmit.tail, info->tty->stopped); +#endif + goto out; + } + /* + * We removed the loop and try to do it in to chunks. We need + * 2 operations maximum because it's a ring buffer. + * + * First from current to tail if possible. + * Then from the beginning of the buffer until necessary + */ + + count = MIN(CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE), + SERIAL_XMIT_SIZE - info->xmit.tail); + console->write(console, info->xmit.buf+info->xmit.tail, count); + + info->xmit.tail = (info->xmit.tail+count) & (SERIAL_XMIT_SIZE-1); + + /* + * We have more at the beginning of the buffer + */ + count = CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); + if (count) { + console->write(console, info->xmit.buf, count); + info->xmit.tail += count; + } +out: + restore_flags(flags); +} + +static void rs_flush_chars(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + + if (info->xmit.head == info->xmit.tail || tty->stopped || tty->hw_stopped || + !info->xmit.buf) + return; + + transmit_chars(info, NULL); +} + + +static int rs_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) +{ + int c, ret = 0; + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (!tty || !info->xmit.buf || !tmp_buf) return 0; + + save_flags(flags); + if (from_user) { + down(&tmp_buf_sem); + while (1) { + int c1; + c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); + if (count < c) + c = count; + if (c <= 0) + break; + + c -= copy_from_user(tmp_buf, buf, c); + if (!c) { + if (!ret) + ret = -EFAULT; + break; + } + cli(); + c1 = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); + if (c1 < c) + c = c1; + memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c); + info->xmit.head = ((info->xmit.head + c) & + (SERIAL_XMIT_SIZE-1)); + restore_flags(flags); + buf += c; + count -= c; + ret += c; + } + up(&tmp_buf_sem); + } else { + cli(); + while (1) { + c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); + if (count < c) + c = count; + if (c <= 0) { + break; + } + memcpy(info->xmit.buf + info->xmit.head, buf, c); + info->xmit.head = ((info->xmit.head + c) & + (SERIAL_XMIT_SIZE-1)); + buf += c; + count -= c; + ret += c; + } + restore_flags(flags); + } + /* + * Hey, we transmit directly from here in our case + */ + if (CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) + && !tty->stopped && !tty->hw_stopped) { + transmit_chars(info, NULL); + } + return ret; +} + +static int rs_write_room(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + + return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); +} + +static int rs_chars_in_buffer(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + + return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); +} + +static void rs_flush_buffer(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + save_flags(flags); cli(); + info->xmit.head = info->xmit.tail = 0; + restore_flags(flags); + + wake_up_interruptible(&tty->write_wait); + + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); +} + +/* + * This function is used to send a high-priority XON/XOFF character to + * the device + */ +static void rs_send_xchar(struct tty_struct *tty, char ch) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + + info->x_char = ch; + if (ch) { + /* + * I guess we could call console->write() directly but + * let's do that for now. + */ + transmit_chars(info, NULL); + } +} + +/* + * ------------------------------------------------------------ + * rs_throttle() + * + * This routine is called by the upper-layer tty layer to signal that + * incoming characters should be throttled. + * ------------------------------------------------------------ + */ +static void rs_throttle(struct tty_struct * tty) +{ + if (I_IXOFF(tty)) rs_send_xchar(tty, STOP_CHAR(tty)); + + printk("simrs_throttle called\n"); +} + +static void rs_unthrottle(struct tty_struct * tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else + rs_send_xchar(tty, START_CHAR(tty)); + } + printk("simrs_unthrottle called\n"); +} + +/* + * rs_break() --- routine which turns the break handling on or off + */ +static void rs_break(struct tty_struct *tty, int break_state) +{ +} + +static int rs_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg) +{ + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && + (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + + switch (cmd) { + case TIOCMGET: + printk("rs_ioctl: TIOCMGET called\n"); + return -EINVAL; + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + printk("rs_ioctl: TIOCMBIS/BIC/SET called\n"); + return -EINVAL; + case TIOCGSERIAL: + printk("simrs_ioctl TIOCGSERIAL called\n"); + return 0; + case TIOCSSERIAL: + printk("simrs_ioctl TIOCSSERIAL called\n"); + return 0; + case TIOCSERCONFIG: + printk("rs_ioctl: TIOCSERCONFIG called\n"); + return -EINVAL; + + case TIOCSERGETLSR: /* Get line status register */ + printk("rs_ioctl: TIOCSERGETLSR called\n"); + return -EINVAL; + + case TIOCSERGSTRUCT: + printk("rs_ioctl: TIOCSERGSTRUCT called\n"); +#if 0 + if (copy_to_user((struct async_struct *) arg, + info, sizeof(struct async_struct))) + return -EFAULT; +#endif + return 0; + + /* + * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change + * - mask passed in arg for lines of interest + * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) + * Caller should use TIOCGICOUNT to see which one it was + */ + case TIOCMIWAIT: + printk("rs_ioctl: TIOCMIWAIT: called\n"); + return 0; + /* + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ + case TIOCGICOUNT: + printk("rs_ioctl: TIOCGICOUNT called\n"); + return 0; + + case TIOCSERGWILD: + case TIOCSERSWILD: + /* "setserial -W" is called in Debian boot */ + printk ("TIOCSER?WILD ioctl obsolete, ignored.\n"); + return 0; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) + +static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +{ + unsigned int cflag = tty->termios->c_cflag; + + if ( (cflag == old_termios->c_cflag) + && ( RELEVANT_IFLAG(tty->termios->c_iflag) + == RELEVANT_IFLAG(old_termios->c_iflag))) + return; + + + /* Handle turning off CRTSCTS */ + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + rs_start(tty); + } +} +/* + * This routine will shutdown a serial port; interrupts are disabled, and + * DTR is dropped if the hangup on close termio flag is on. + */ +static void shutdown(struct async_struct * info) +{ + unsigned long flags; + struct serial_state *state; + int retval; + + if (!(info->flags & ASYNC_INITIALIZED)) return; + + state = info->state; + +#ifdef SIMSERIAL_DEBUG + printk("Shutting down serial port %d (irq %d)....", info->line, + state->irq); +#endif + + save_flags(flags); cli(); /* Disable interrupts */ + + /* + * First unlink the serial port from the IRQ chain... + */ + if (info->next_port) + info->next_port->prev_port = info->prev_port; + if (info->prev_port) + info->prev_port->next_port = info->next_port; + else + IRQ_ports[state->irq] = info->next_port; + + /* + * Free the IRQ, if necessary + */ + if (state->irq && (!IRQ_ports[state->irq] || + !IRQ_ports[state->irq]->next_port)) { + if (IRQ_ports[state->irq]) { + free_irq(state->irq, NULL); + retval = request_irq(state->irq, rs_interrupt_single, + IRQ_T(info), "serial", NULL); + + if (retval) + printk("serial shutdown: request_irq: error %d" + " Couldn't reacquire IRQ.\n", retval); + } else + free_irq(state->irq, NULL); + } + + if (info->xmit.buf) { + free_page((unsigned long) info->xmit.buf); + info->xmit.buf = 0; + } + + if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); + + info->flags &= ~ASYNC_INITIALIZED; + restore_flags(flags); +} + +/* + * ------------------------------------------------------------ + * rs_close() + * + * This routine is called when the serial port gets closed. First, we + * wait for the last remaining data to be sent. Then, we unlink its + * async structure from the interrupt chain if necessary, and we free + * that IRQ if nothing is left in the chain. + * ------------------------------------------------------------ + */ +static void rs_close(struct tty_struct *tty, struct file * filp) +{ + struct async_struct * info = (struct async_struct *)tty->driver_data; + struct serial_state *state; + unsigned long flags; + + if (!info ) return; + + state = info->state; + + save_flags(flags); cli(); + + if (tty_hung_up_p(filp)) { +#ifdef SIMSERIAL_DEBUG + printk("rs_close: hung_up\n"); +#endif + MOD_DEC_USE_COUNT; + restore_flags(flags); + return; + } +#ifdef SIMSERIAL_DEBUG + printk("rs_close ttys%d, count = %d\n", info->line, state->count); +#endif + if ((tty->count == 1) && (state->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. state->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + printk("rs_close: bad serial port count; tty->count is 1, " + "state->count is %d\n", state->count); + state->count = 1; + } + if (--state->count < 0) { + printk("rs_close: bad serial port count for ttys%d: %d\n", + info->line, state->count); + state->count = 0; + } + if (state->count) { + MOD_DEC_USE_COUNT; + restore_flags(flags); + return; + } + info->flags |= ASYNC_CLOSING; + restore_flags(flags); + + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + shutdown(info); + if (tty->driver.flush_buffer) tty->driver.flush_buffer(tty); + if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); + info->event = 0; + info->tty = 0; + if (info->blocked_open) { + if (info->close_delay) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(info->close_delay); + } + wake_up_interruptible(&info->open_wait); + } + info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|ASYNC_CLOSING); + wake_up_interruptible(&info->close_wait); + MOD_DEC_USE_COUNT; +} + +/* + * rs_wait_until_sent() --- wait until the transmitter is empty + */ +static void rs_wait_until_sent(struct tty_struct *tty, int timeout) +{ +} + + +/* + * rs_hangup() --- called by tty_hangup() when a hangup is signaled. + */ +static void rs_hangup(struct tty_struct *tty) +{ + struct async_struct * info = (struct async_struct *)tty->driver_data; + struct serial_state *state = info->state; + +#ifdef SIMSERIAL_DEBUG + printk("rs_hangup: called\n"); +#endif + + state = info->state; + + rs_flush_buffer(tty); + if (info->flags & ASYNC_CLOSING) + return; + shutdown(info); + + info->event = 0; + state->count = 0; + info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE); + info->tty = 0; + wake_up_interruptible(&info->open_wait); +} + + +static int get_async_struct(int line, struct async_struct **ret_info) +{ + struct async_struct *info; + struct serial_state *sstate; + + sstate = rs_table + line; + sstate->count++; + if (sstate->info) { + *ret_info = sstate->info; + return 0; + } + info = kmalloc(sizeof(struct async_struct), GFP_KERNEL); + if (!info) { + sstate->count--; + return -ENOMEM; + } + memset(info, 0, sizeof(struct async_struct)); + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); + init_waitqueue_head(&info->delta_msr_wait); + info->magic = SERIAL_MAGIC; + info->port = sstate->port; + info->flags = sstate->flags; + info->xmit_fifo_size = sstate->xmit_fifo_size; + info->line = line; + info->tqueue.routine = do_softint; + info->tqueue.data = info; + info->state = sstate; + if (sstate->info) { + kfree(info); + *ret_info = sstate->info; + return 0; + } + *ret_info = sstate->info = info; + return 0; +} + +static int +startup(struct async_struct *info) +{ + unsigned long flags; + int retval=0; + void (*handler)(int, void *, struct pt_regs *); + struct serial_state *state= info->state; + unsigned long page; + + page = get_free_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + + save_flags(flags); cli(); + + if (info->flags & ASYNC_INITIALIZED) { + free_page(page); + goto errout; + } + + if (!state->port || !state->type) { + if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); + free_page(page); + goto errout; + } + if (info->xmit.buf) + free_page(page); + else + info->xmit.buf = (unsigned char *) page; + +#ifdef SIMSERIAL_DEBUG + printk("startup: ttys%d (irq %d)...", info->line, state->irq); +#endif + + /* + * Allocate the IRQ if necessary + */ + if (state->irq && (!IRQ_ports[state->irq] || + !IRQ_ports[state->irq]->next_port)) { + if (IRQ_ports[state->irq]) { + retval = -EBUSY; + goto errout; + } else + handler = rs_interrupt_single; + + retval = request_irq(state->irq, handler, IRQ_T(info), + "simserial", NULL); + if (retval) { + if (capable(CAP_SYS_ADMIN)) { + if (info->tty) + set_bit(TTY_IO_ERROR, + &info->tty->flags); + retval = 0; + } + goto errout; + } + } + + /* + * Insert serial port into IRQ chain. + */ + info->prev_port = 0; + info->next_port = IRQ_ports[state->irq]; + if (info->next_port) + info->next_port->prev_port = info; + IRQ_ports[state->irq] = info; + + if (info->tty) clear_bit(TTY_IO_ERROR, &info->tty->flags); + + info->xmit.head = info->xmit.tail = 0; + +#if 0 + /* + * Set up serial timers... + */ + timer_table[RS_TIMER].expires = jiffies + 2*HZ/100; + timer_active |= 1 << RS_TIMER; +#endif + + /* + * Set up the tty->alt_speed kludge + */ + if (info->tty) { + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + info->tty->alt_speed = 57600; + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + info->tty->alt_speed = 115200; + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + info->tty->alt_speed = 230400; + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + info->tty->alt_speed = 460800; + } + + info->flags |= ASYNC_INITIALIZED; + restore_flags(flags); + return 0; + +errout: + restore_flags(flags); + return retval; +} + + +/* + * This routine is called whenever a serial port is opened. It + * enables interrupts for a serial port, linking in its async structure into + * the IRQ chain. It also performs the serial-specific + * initialization for the tty structure. + */ +static int rs_open(struct tty_struct *tty, struct file * filp) +{ + struct async_struct *info; + int retval, line; + unsigned long page; + + MOD_INC_USE_COUNT; + line = MINOR(tty->device) - tty->driver.minor_start; + if ((line < 0) || (line >= NR_PORTS)) { + MOD_DEC_USE_COUNT; + return -ENODEV; + } + retval = get_async_struct(line, &info); + if (retval) { + MOD_DEC_USE_COUNT; + return retval; + } + tty->driver_data = info; + info->tty = tty; + +#ifdef SIMSERIAL_DEBUG + printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line, + info->state->count); +#endif + info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + + if (!tmp_buf) { + page = get_free_page(GFP_KERNEL); + if (!page) { + /* MOD_DEC_USE_COUNT; "info->tty" will cause this? */ + return -ENOMEM; + } + if (tmp_buf) + free_page(page); + else + tmp_buf = (unsigned char *) page; + } + + /* + * If the port is the middle of closing, bail out now + */ + if (tty_hung_up_p(filp) || + (info->flags & ASYNC_CLOSING)) { + if (info->flags & ASYNC_CLOSING) + interruptible_sleep_on(&info->close_wait); + /* MOD_DEC_USE_COUNT; "info->tty" will cause this? */ +#ifdef SERIAL_DO_RESTART + return ((info->flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); +#else + return -EAGAIN; +#endif + } + + /* + * Start up serial port + */ + retval = startup(info); + if (retval) { + /* MOD_DEC_USE_COUNT; "info->tty" will cause this? */ + return retval; + } + + if ((info->state->count == 1) && + (info->flags & ASYNC_SPLIT_TERMIOS)) { + if (tty->driver.subtype == SERIAL_TYPE_NORMAL) + *tty->termios = info->state->normal_termios; + else + *tty->termios = info->state->callout_termios; + } + + /* + * figure out which console to use (should be one already) + */ + console = console_drivers; + while (console) { + if ((console->flags & CON_ENABLED) && console->write) break; + console = console->next; + } + + info->session = current->session; + info->pgrp = current->pgrp; + +#ifdef SIMSERIAL_DEBUG + printk("rs_open ttys%d successful\n", info->line); +#endif + return 0; +} + +/* + * /proc fs routines.... + */ + +static inline int line_info(char *buf, struct serial_state *state) +{ + return sprintf(buf, "%d: uart:%s port:%lX irq:%d\n", + state->line, uart_config[state->type].name, + state->port, state->irq); +} + +int rs_read_proc(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + int i, len = 0, l; + off_t begin = 0; + + len += sprintf(page, "simserinfo:1.0 driver:%s\n", serial_version); + for (i = 0; i < NR_PORTS && len < 4000; i++) { + l = line_info(page + len, &rs_table[i]); + len += l; + if (len+begin > off+count) + goto done; + if (len+begin < off) { + begin += len; + len = 0; + } + } + *eof = 1; +done: + if (off >= len+begin) + return 0; + *start = page + (begin-off); + return ((count < begin+len-off) ? count : begin+len-off); +} + +/* + * --------------------------------------------------------------------- + * rs_init() and friends + * + * rs_init() is called at boot-time to initialize the serial driver. + * --------------------------------------------------------------------- + */ + +/* + * This routine prints out the appropriate serial driver version + * number, and identifies which options were configured into this + * driver. + */ +static inline void show_serial_version(void) +{ + printk(KERN_INFO "%s version %s with", serial_name, serial_version); + printk(" no serial options enabled\n"); +} + +/* + * The serial driver boot-time initialization code! + */ +static int __init +simrs_init (void) +{ + int i; + struct serial_state *state; + + show_serial_version(); + + /* Initialize the tty_driver structure */ + + memset(&serial_driver, 0, sizeof(struct tty_driver)); + serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.driver_name = "simserial"; + serial_driver.name = "ttyS"; + serial_driver.major = TTY_MAJOR; + serial_driver.minor_start = 64; + serial_driver.num = 1; + serial_driver.type = TTY_DRIVER_TYPE_SERIAL; + serial_driver.subtype = SERIAL_TYPE_NORMAL; + serial_driver.init_termios = tty_std_termios; + serial_driver.init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver.flags = TTY_DRIVER_REAL_RAW; + serial_driver.refcount = &serial_refcount; + serial_driver.table = serial_table; + serial_driver.termios = serial_termios; + serial_driver.termios_locked = serial_termios_locked; + + serial_driver.open = rs_open; + serial_driver.close = rs_close; + serial_driver.write = rs_write; + serial_driver.put_char = rs_put_char; + serial_driver.flush_chars = rs_flush_chars; + serial_driver.write_room = rs_write_room; + serial_driver.chars_in_buffer = rs_chars_in_buffer; + serial_driver.flush_buffer = rs_flush_buffer; + serial_driver.ioctl = rs_ioctl; + serial_driver.throttle = rs_throttle; + serial_driver.unthrottle = rs_unthrottle; + serial_driver.send_xchar = rs_send_xchar; + serial_driver.set_termios = rs_set_termios; + serial_driver.stop = rs_stop; + serial_driver.start = rs_start; + serial_driver.hangup = rs_hangup; + serial_driver.break_ctl = rs_break; + serial_driver.wait_until_sent = rs_wait_until_sent; + serial_driver.read_proc = rs_read_proc; + + /* + * Let's have a little bit of fun ! + */ + for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { + + if (state->type == PORT_UNKNOWN) continue; + + if (!state->irq) { + state->irq = ia64_alloc_irq(); + ia64_ssc_connect_irq(KEYBOARD_INTR, state->irq); + } + + printk(KERN_INFO "ttyS%02d at 0x%04lx (irq = %d) is a %s\n", + state->line, + state->port, state->irq, + uart_config[state->type].name); + } + /* + * The callout device is just like normal device except for + * major number and the subtype code. + */ + callout_driver = serial_driver; + callout_driver.name = "cua"; + callout_driver.major = TTYAUX_MAJOR; + callout_driver.subtype = SERIAL_TYPE_CALLOUT; + callout_driver.read_proc = 0; + callout_driver.proc_entry = 0; + + if (tty_register_driver(&serial_driver)) + panic("Couldn't register simserial driver\n"); + + if (tty_register_driver(&callout_driver)) + panic("Couldn't register callout driver\n"); + + return 0; +} + +#ifndef MODULE +__initcall(simrs_init); +#endif diff -urN linux-2.4.0-test10/drivers/char/vt.c linux-2.4.0-test10-lia/drivers/char/vt.c --- linux-2.4.0-test10/drivers/char/vt.c Mon Oct 16 12:58:51 2000 +++ linux-2.4.0-test10-lia/drivers/char/vt.c Wed Nov 1 14:57:58 2000 @@ -62,7 +62,7 @@ */ unsigned char keyboard_type = KB_101; -#if !defined(__alpha__) && !defined(__mips__) && !defined(__arm__) && !defined(__sh__) +#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips__) && !defined(__arm__) && !defined(__sh__) asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on); #endif @@ -472,7 +472,7 @@ ucval = keyboard_type; goto setchar; -#if !defined(__alpha__) && !defined(__mips__) && !defined(__arm__) && !defined(__sh__) +#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips__) && !defined(__arm__) && !defined(__sh__) /* * These cannot be implemented on any machine that implements * ioperm() in user level (such as Alpha PCs). diff -urN linux-2.4.0-test10/drivers/media/radio/Makefile linux-2.4.0-test10-lia/drivers/media/radio/Makefile --- linux-2.4.0-test10/drivers/media/radio/Makefile Tue Sep 19 08:01:34 2000 +++ linux-2.4.0-test10-lia/drivers/media/radio/Makefile Mon Oct 30 22:17:11 2000 @@ -9,7 +9,7 @@ # parent makes.. # -O_OBJS := +O_OBJS := dummy.o OX_OBJS := M_OBJS := MX_OBJS := diff -urN linux-2.4.0-test10/drivers/media/radio/dummy.c linux-2.4.0-test10-lia/drivers/media/radio/dummy.c --- linux-2.4.0-test10/drivers/media/radio/dummy.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/drivers/media/radio/dummy.c Mon Oct 30 22:17:11 2000 @@ -0,0 +1 @@ +/* just so the linker knows what kind of object files it's deadling with... */ diff -urN linux-2.4.0-test10/drivers/media/video/Makefile linux-2.4.0-test10-lia/drivers/media/video/Makefile --- linux-2.4.0-test10/drivers/media/video/Makefile Tue Aug 22 11:29:02 2000 +++ linux-2.4.0-test10-lia/drivers/media/video/Makefile Mon Oct 30 22:17:11 2000 @@ -16,7 +16,7 @@ # Object file lists. -obj-y := +obj-y := dummy.o obj-m := obj-n := obj- := diff -urN linux-2.4.0-test10/drivers/media/video/dummy.c linux-2.4.0-test10-lia/drivers/media/video/dummy.c --- linux-2.4.0-test10/drivers/media/video/dummy.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/drivers/media/video/dummy.c Mon Oct 30 22:17:11 2000 @@ -0,0 +1 @@ +/* just so the linker knows what kind of object files it's deadling with... */ diff -urN linux-2.4.0-test10/drivers/net/Makefile linux-2.4.0-test10-lia/drivers/net/Makefile --- linux-2.4.0-test10/drivers/net/Makefile Thu Sep 21 13:27:10 2000 +++ linux-2.4.0-test10-lia/drivers/net/Makefile Mon Oct 30 22:17:11 2000 @@ -199,6 +199,7 @@ obj-$(CONFIG_ES3210) += es3210.o 8390.o obj-$(CONFIG_LNE390) += lne390.o 8390.o obj-$(CONFIG_NE3210) += ne3210.o 8390.o +obj-$(CONFIG_SIMETH) += simeth.o obj-$(CONFIG_PPP) += ppp_generic.o slhc.o obj-$(CONFIG_PPP_ASYNC) += ppp_async.o diff -urN linux-2.4.0-test10/drivers/net/eepro100.c linux-2.4.0-test10-lia/drivers/net/eepro100.c --- linux-2.4.0-test10/drivers/net/eepro100.c Mon Oct 16 12:58:51 2000 +++ linux-2.4.0-test10-lia/drivers/net/eepro100.c Wed Nov 1 14:58:03 2000 @@ -25,6 +25,8 @@ Disabled FC and ER, to avoid lockups when when we get FCP interrupts. 2000 Jul 17 Goutham Rao PCI DMA API fixes, adding pci_dma_sync_single calls where neccesary + 2000 Aug 31 David Mosberger + RX_ALIGN support: enables rx DMA without causing unaligned accesses. */ static const char *version = @@ -41,6 +43,14 @@ static int txdmacount = 128; static int rxdmacount; +#ifdef __ia64__ + /* align rx buffers to 2 bytes so that IP header is aligned */ +# define RX_ALIGN +# define RxFD_ALIGNMENT __attribute__ ((aligned (2), packed)) +#else +# define RxFD_ALIGNMENT +#endif + /* Set the copy breakpoint for the copy-only-tiny-buffer Rx method. Lower values use more memory, but are faster. */ static int rx_copybreak = 200; @@ -429,18 +439,18 @@ /* The Speedo3 Rx and Tx frame/buffer descriptors. */ struct descriptor { /* A generic descriptor. */ - s32 cmd_status; /* All command and status fields. */ + volatile s32 cmd_status; /* All command and status fields. */ u32 link; /* struct descriptor * */ unsigned char params[0]; }; /* The Speedo3 Rx and Tx buffer descriptors. */ struct RxFD { /* Receive frame descriptor. */ - s32 status; + volatile s32 status; u32 link; /* struct RxFD * */ u32 rx_buf_addr; /* void * */ u32 count; -}; +} RxFD_ALIGNMENT; /* Selected elements of the Tx/RxFD.status word. */ enum RxFD_bits { @@ -1207,6 +1217,9 @@ for (i = 0; i < RX_RING_SIZE; i++) { struct sk_buff *skb; skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD)); +#ifdef RX_ALIGN + skb_reserve(skb, 2); /* Align IP on 16 byte boundary */ +#endif sp->rx_skbuff[i] = skb; if (skb == NULL) break; /* OK. Just initially short of Rx bufs. */ @@ -1656,6 +1669,9 @@ struct sk_buff *skb; /* Get a fresh skbuff to replace the consumed one. */ skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD)); +#ifdef RX_ALIGN + skb_reserve(skb, 2); /* Align IP on 16 byte boundary */ +#endif sp->rx_skbuff[entry] = skb; if (skb == NULL) { sp->rx_ringp[entry] = NULL; diff -urN linux-2.4.0-test10/drivers/net/simeth.c linux-2.4.0-test10-lia/drivers/net/simeth.c --- linux-2.4.0-test10/drivers/net/simeth.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/drivers/net/simeth.c Wed Nov 1 23:19:29 2000 @@ -0,0 +1,596 @@ +/* + * Simulated Ethernet Driver + * + * Copyright (C) 1999-2000 Hewlett-Packard Co + * Copyright (C) 1999-2000 Stephane Eranain + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SIMETH_RECV_MAX 10 + +/* + * Maximum possible received frame for Ethernet. + * We preallocate an sk_buff of that size to avoid costly + * memcpy for temporary buffer into sk_buff. We do basically + * what's done in other drivers, like eepro with a ring. + * The difference is, of course, that we don't have real DMA !!! + */ +#define SIMETH_FRAME_SIZE ETH_FRAME_LEN + + +#define SSC_NETDEV_PROBE 100 +#define SSC_NETDEV_SEND 101 +#define SSC_NETDEV_RECV 102 +#define SSC_NETDEV_ATTACH 103 +#define SSC_NETDEV_DETACH 104 + +#define NETWORK_INTR 8 + +/* + * This structure is need for the module version + * It hasn't been tested yet + */ +struct simeth_local { + struct net_device *next_module; + struct net_device_stats stats; + int simfd; /* descriptor in the simulator */ +}; + +static int simeth_probe1(void); +static int simeth_open(struct net_device *dev); +static int simeth_close(struct net_device *dev); +static int simeth_tx(struct sk_buff *skb, struct net_device *dev); +static int simeth_rx(struct net_device *dev); +static struct net_device_stats *simeth_get_stats(struct net_device *dev); +static void simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs); +static void set_multicast_list(struct net_device *dev); +static int simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr); + +static char *simeth_version="v0.2"; + +/* + * This variable is used to establish a mapping between the Linux/ia64 kernel + * and the host linux kernel. + * + * As of today, we support only one card, even though most of the code + * is ready for many more. The mapping is then: + * linux/ia64 -> linux/x86 + * eth0 -> eth1 + * + * In the future, we some string operations, we could easily support up + * to 10 cards (0-9). + * + * The default mapping can be changed on the kernel command line by + * specifying simeth=ethX (or whatever string you want). + */ +static char *simeth_device="eth0"; /* default host interface to use */ + + + +static volatile unsigned int card_count; /* how many cards "found" so far */ +static int simeth_debug=0; /* set to 1 to get debug information */ + +/* + * Used to catch IFF_UP & IFF_DOWN events + */ +static struct notifier_block simeth_dev_notifier = { + simeth_device_event, + 0 +}; + + +/* + * Function used when using a kernel command line option. + * + * Format: simeth=interface_name (like eth0) + */ +static int __init +simeth_setup(char *str) +{ + simeth_device = str; + return 1; +} + +__setup("simeth=", simeth_setup); + +/* + * Function used to probe for simeth devices when not installed + * as a loadable module + */ + +int __init +simeth_probe (void) +{ + return simeth_probe1(); +} + +extern long ia64_ssc (long, long, long, long, int); +extern void ia64_ssc_connect_irq (long intr, long irq); + +static inline int +netdev_probe(char *name, unsigned char *ether) +{ + return ia64_ssc(__pa(name), __pa(ether), 0,0, SSC_NETDEV_PROBE); +} + + +static inline int +netdev_connect(int irq) +{ + /* XXX Fix me + * this does not support multiple cards + * also no return value + */ + ia64_ssc_connect_irq(NETWORK_INTR, irq); + return 0; +} + +static inline int +netdev_attach(int fd, int irq, unsigned int ipaddr) +{ + /* this puts the host interface in the right mode (start interupting) */ + return ia64_ssc(fd, ipaddr, 0,0, SSC_NETDEV_ATTACH); +} + + +static inline int +netdev_detach(int fd) +{ + /* + * inactivate the host interface (don't interrupt anymore) */ + return ia64_ssc(fd, 0,0,0, SSC_NETDEV_DETACH); +} + +static inline int +netdev_send(int fd, unsigned char *buf, unsigned int len) +{ + return ia64_ssc(fd, __pa(buf), len, 0, SSC_NETDEV_SEND); +} + +static inline int +netdev_read(int fd, unsigned char *buf, unsigned int len) +{ + return ia64_ssc(fd, __pa(buf), len, 0, SSC_NETDEV_RECV); +} + +/* + * Function shared with module code, so cannot be in init section + * + * So far this function "detects" only one card (test_&_set) but could + * be extended easily. + * + * Return: + * - -ENODEV is no device found + * - -ENOMEM is no more memory + * - 0 otherwise + */ +static int +simeth_probe1(void) +{ + unsigned char mac_addr[ETH_ALEN]; + struct simeth_local *local; + struct net_device *dev; + int fd, i; + + /* + * XXX Fix me + * let's support just one card for now + */ + if (test_and_set_bit(0, &card_count)) + return -ENODEV; + + /* + * check with the simulator for the device + */ + fd = netdev_probe(simeth_device, mac_addr); + if (fd == -1) + return -ENODEV; + + dev = init_etherdev(NULL, sizeof(struct simeth_local)); + if (!dev) + return -ENOMEM; + + memcpy(dev->dev_addr, mac_addr, sizeof(mac_addr)); + + dev->irq = ia64_alloc_irq(); + + /* + * attach the interrupt in the simulator, this does enable interrupts + * until a netdev_attach() is called + */ + netdev_connect(dev->irq); + + memset(dev->priv, 0, sizeof(struct simeth_local)); + + local = dev->priv; + local->simfd = fd; /* keep track of underlying file descriptor */ + local->next_module = NULL; + + dev->open = simeth_open; + dev->stop = simeth_close; + dev->hard_start_xmit = simeth_tx; + dev->get_stats = simeth_get_stats; + dev->set_multicast_list = set_multicast_list; /* no yet used */ + + /* Fill in the fields of the device structure with ethernet-generic values. */ + ether_setup(dev); + + printk("simeth: %s alpha\n", simeth_version); + printk("%s: hosteth=%s simfd=%d, HwAddr", dev->name, simeth_device, local->simfd); + for(i = 0; i < ETH_ALEN; i++) { + printk(" %2.2x", dev->dev_addr[i]); + } + printk(", IRQ %d\n", dev->irq); + +#ifdef MODULE + local->next_module = simeth_dev; + simeth_dev = dev; +#endif + /* + * XXX Fix me + * would not work with more than one device ! + */ + register_netdevice_notifier(&simeth_dev_notifier); + + return 0; +} + +/* + * actually binds the device to an interrupt vector + */ +static int +simeth_open(struct net_device *dev) +{ + if (request_irq(dev->irq, simeth_interrupt, 0, "simeth", dev)) { + printk ("simeth: unable to get IRQ %d.\n", dev->irq); + return -EAGAIN; + } + + netif_start_queue(dev); + MOD_INC_USE_COUNT; + + return 0; +} + +/* copied from lapbether.c */ +static __inline__ int dev_is_ethdev(struct net_device *dev) +{ + return ( dev->type == ARPHRD_ETHER && strncmp(dev->name, "dummy", 5)); +} + + +/* + * Handler for IFF_UP or IFF_DOWN + * + * The reason for that is that we don't want to be interrupted when the + * interface is down. There is no way to unconnect in the simualtor. Instead + * we use this function to shutdown packet processing in the frame filter + * in the simulator. Thus no interrupts are generated + * + * + * That's also the place where we pass the IP address of this device to the + * simulator so that that we can start filtering packets for it + * + * There may be a better way of doing this, but I don't know which yet. + */ +static int +simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr) +{ + struct net_device *dev = (struct net_device *)ptr; + struct simeth_local *local; + struct in_device *in_dev; + struct in_ifaddr **ifap = NULL; + struct in_ifaddr *ifa = NULL; + int r; + + + if ( ! dev ) { + printk(KERN_WARNING "simeth_device_event dev=0\n"); + return NOTIFY_DONE; + } + + if ( event != NETDEV_UP && event != NETDEV_DOWN ) return NOTIFY_DONE; + + /* + * Check whether or not it's for an ethernet device + * + * XXX Fixme: This works only as long as we support one + * type of ethernet device. + */ + if ( !dev_is_ethdev(dev) ) return NOTIFY_DONE; + + if ((in_dev=dev->ip_ptr) != NULL) { + for (ifap=&in_dev->ifa_list; (ifa=*ifap) != NULL; ifap=&ifa->ifa_next) + if (strcmp(dev->name, ifa->ifa_label) == 0) break; + } + if ( ifa == NULL ) { + printk("simeth_open: can't find device %s's ifa\n", dev->name); + return NOTIFY_DONE; + } + + printk("simeth_device_event: %s ipaddr=0x%x\n", dev->name, htonl(ifa->ifa_local)); + + /* + * XXX Fix me + * if the device was up, and we're simply reconfiguring it, not sure + * we get DOWN then UP. + */ + + local = dev->priv; + /* now do it for real */ + r = event == NETDEV_UP ? + netdev_attach(local->simfd, dev->irq, htonl(ifa->ifa_local)): + netdev_detach(local->simfd); + + printk("simeth: netdev_attach/detach: event=%s ->%d\n", event == NETDEV_UP ? "attach":"detach", r); + + return NOTIFY_DONE; +} + +static int +simeth_close(struct net_device *dev) +{ + netif_stop_queue(dev); + + free_irq(dev->irq, dev); + + MOD_DEC_USE_COUNT; + + return 0; +} + +/* + * Only used for debug + */ +static void +frame_print(unsigned char *from, unsigned char *frame, int len) +{ + int i; + + printk("%s: (%d) %02x", from, len, frame[0] & 0xff); + for(i=1; i < 6; i++ ) { + printk(":%02x", frame[i] &0xff); + } + printk(" %2x", frame[6] &0xff); + for(i=7; i < 12; i++ ) { + printk(":%02x", frame[i] &0xff); + } + printk(" [%02x%02x]\n", frame[12], frame[13]); + + for(i=14; i < len; i++ ) { + printk("%02x ", frame[i] &0xff); + if ( (i%10)==0) printk("\n"); + } + printk("\n"); +} + + +/* + * Function used to transmit of frame, very last one on the path before + * going to the simulator. + */ +static int +simeth_tx(struct sk_buff *skb, struct net_device *dev) +{ + struct simeth_local *local = (struct simeth_local *)dev->priv; + +#if 0 + /* ensure we have at least ETH_ZLEN bytes (min frame size) */ + unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + /* Where do the extra padding bytes comes from inthe skbuff ? */ +#else + /* the real driver in the host system is going to take care of that + * or maybe it's the NIC itself. + */ + unsigned int length = skb->len; +#endif + + local->stats.tx_bytes += skb->len; + local->stats.tx_packets++; + + + if (simeth_debug > 5) frame_print("simeth_tx", skb->data, length); + + netdev_send(local->simfd, skb->data, length); + + /* + * we are synchronous on write, so we don't simulate a + * trasnmit complete interrupt, thus we don't need to arm a tx + */ + + dev_kfree_skb(skb); + return 0; +} + +static inline struct sk_buff * +make_new_skb(struct net_device *dev) +{ + struct sk_buff *nskb; + + /* + * The +2 is used to make sure that the IP header is nicely + * aligned (on 4byte boundary I assume 14+2=16) + */ + nskb = dev_alloc_skb(SIMETH_FRAME_SIZE + 2); + if ( nskb == NULL ) { + printk(KERN_NOTICE "%s: memory squeeze. dropping packet.\n", dev->name); + return NULL; + } + nskb->dev = dev; + + skb_reserve(nskb, 2); /* Align IP on 16 byte boundaries */ + + skb_put(nskb,SIMETH_FRAME_SIZE); + + return nskb; +} + +/* + * called from interrupt handler to process a received frame + */ +static int +simeth_rx(struct net_device *dev) +{ + struct simeth_local *local; + struct sk_buff *skb; + int len; + int rcv_count = SIMETH_RECV_MAX; + + local = (struct simeth_local *)dev->priv; + /* + * the loop concept has been borrowed from other drivers + * looks to me like it's a throttling thing to avoid pushing to many + * packets at one time into the stack. Making sure we can process them + * upstream and make forward progress overall + */ + do { + if ( (skb=make_new_skb(dev)) == NULL ) { + printk(KERN_NOTICE "%s: memory squeeze. dropping packet.\n", dev->name); + local->stats.rx_dropped++; + return 0; + } + /* + * Read only one frame at a time + */ + len = netdev_read(local->simfd, skb->data, SIMETH_FRAME_SIZE); + if ( len == 0 ) { + if ( simeth_debug > 0 ) printk(KERN_WARNING "%s: count=%d netdev_read=0\n", dev->name, SIMETH_RECV_MAX-rcv_count); + break; + } +#if 0 + /* + * XXX Fix me + * Should really do a csum+copy here + */ + memcpy(skb->data, frame, len); +#endif + skb->protocol = eth_type_trans(skb, dev); + + if ( simeth_debug > 6 ) frame_print("simeth_rx", skb->data, len); + + /* + * push the packet up & trigger software interrupt + */ + netif_rx(skb); + + local->stats.rx_packets++; + local->stats.rx_bytes += len; + + } while ( --rcv_count ); + + return len; /* 0 = nothing left to read, otherwise, we can try again */ +} + +/* + * Interrupt handler (Yes, we can do it too !!!) + */ +static void +simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs) +{ + struct net_device *dev = dev_id; + + if ( dev == NULL ) { + printk(KERN_WARNING "simeth: irq %d for unknown device\n", irq); + return; + } + + /* + * very simple loop because we get interrupts only when receving + */ + while (simeth_rx(dev)); +} + +static struct net_device_stats * +simeth_get_stats(struct net_device *dev) +{ + struct simeth_local *local = (struct simeth_local *) dev->priv; + + return &local->stats; +} + +/* fake multicast ability */ +static void +set_multicast_list(struct net_device *dev) +{ + printk(KERN_WARNING "%s: set_multicast_list called\n", dev->name); +} + +#ifdef CONFIG_NET_FASTROUTE +static int +simeth_accept_fastpath(struct net_device *dev, struct dst_entry *dst) +{ + printk(KERN_WARNING "%s: simeth_accept_fastpath called\n", dev->name); + return -1; +} +#endif + + +#ifdef MODULE +static int +simeth_init(void) +{ + unsigned int cards_found = 0; + + /* iterate over probe */ + + while ( simeth_probe1() == 0 ) cards_found++; + + return cards_found ? 0 : -ENODEV; +} + + +int +init_module(void) +{ + simeth_dev = NULL; + + /* the register_netdev is done "indirectly by ether_initdev() */ + + return simeth_init(); +} + +void +cleanup_module(void) +{ + struct net_device *next; + + while ( simeth_dev ) { + + next = ((struct simeth_private *)simeth_dev->priv)->next_module; + + unregister_netdev(simeth_dev); + + kfree(simeth_dev); + + simeth_dev = next; + } + /* + * XXX fix me + * not clean wihen multiple devices + */ + unregister_netdevice_notifier(&simeth_dev_notifier); +} +#else /* !MODULE */ +__initcall(simeth_probe); +#endif /* !MODULE */ diff -urN linux-2.4.0-test10/drivers/net/tulip/tulip_core.c linux-2.4.0-test10-lia/drivers/net/tulip/tulip_core.c --- linux-2.4.0-test10/drivers/net/tulip/tulip_core.c Mon Oct 16 13:36:08 2000 +++ linux-2.4.0-test10-lia/drivers/net/tulip/tulip_core.c Wed Nov 1 14:58:04 2000 @@ -52,7 +52,7 @@ /* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */ #if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \ - || defined(__sparc_) + || defined(__sparc_) || defined(__ia64__) static int rx_copybreak = 1518; #else static int rx_copybreak = 100; @@ -71,7 +71,7 @@ ToDo: Non-Intel setting could be better. */ -#if defined(__alpha__) +#if defined(__alpha__) || defined(__ia64__) static int csr0 = 0x01A00000 | 0xE000; #elif defined(__i386__) || defined(__powerpc__) || defined(__hppa__) static int csr0 = 0x01A00000 | 0x8000; diff -urN linux-2.4.0-test10/drivers/scsi/Makefile linux-2.4.0-test10-lia/drivers/scsi/Makefile --- linux-2.4.0-test10/drivers/scsi/Makefile Wed Sep 20 13:12:13 2000 +++ linux-2.4.0-test10-lia/drivers/scsi/Makefile Mon Oct 30 22:17:11 2000 @@ -51,6 +51,7 @@ obj-$(CONFIG_SUN3_SCSI) += sun3_scsi.o obj-$(CONFIG_MVME16x_SCSI) += mvme16x.o 53c7xx.o obj-$(CONFIG_BVME6000_SCSI) += bvme6000.o 53c7xx.o +obj-$(CONFIG_SCSI_SIM) += simscsi.o obj-$(CONFIG_SCSI_SIM710) += sim710.o obj-$(CONFIG_SCSI_ADVANSYS) += advansys.o obj-$(CONFIG_SCSI_PCI2000) += pci2000.o @@ -122,7 +123,7 @@ scsicam.o scsi_proc.o scsi_error.o \ scsi_obsolete.o scsi_queue.o scsi_lib.o \ scsi_merge.o scsi_dma.o scsi_scan.o \ - + sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o initio-objs := ini9100u.o i91uscsi.o a100u2w-objs := inia100.o i60uscsi.o diff -urN linux-2.4.0-test10/drivers/scsi/ql12160_fw.h linux-2.4.0-test10-lia/drivers/scsi/ql12160_fw.h --- linux-2.4.0-test10/drivers/scsi/ql12160_fw.h Mon Feb 7 19:45:28 2000 +++ linux-2.4.0-test10-lia/drivers/scsi/ql12160_fw.h Mon Oct 30 22:17:11 2000 @@ -1,56 +1,93 @@ /* + ************************************************************************ + * * + * --- ISP12160 Initiator Firmware --- * + * 32 LUN Support * + * * + ************************************************************************ + * * + * Copyright (C) 1999,2000 Qlogic, Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted provided + * that the following conditions are met: + * 1. Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. - * 2. The name of the author may not be used to endorse or promote products + + * 2. Redistribution in binary form must reproduce the above copyright + + * notice, this list of conditions and the following disclaimer in the + + * documentation and/or other materials provided with the distribution. + + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * * + ************************************************************************ + */ + /* - * Firmware Version 10.01.19 (12:38 Oct 12, 1999) + * Firmware Version 10.04.08 (11:30 May 31, 2000) */ #ifdef UNIQUE_FW_NAME -unsigned short fw12160i_version = 10*1024+1; +unsigned short fw12160i_version = 10*1024+4; #else -unsigned short risc_code_version = 10*1024+1; +unsigned short risc_code_version = 10*1024+4; #endif #ifdef UNIQUE_FW_NAME -unsigned char fw12160i_version_str[] = {10,1,19}; +unsigned char fw12160i_version_str[] = {10,4,8}; #else -unsigned char firmware_version[] = {10,1,19}; +unsigned char firmware_version[] = {10,4,8}; #endif #ifdef UNIQUE_FW_NAME -#define fw12160i_VERSION_STRING "10.1.19" +#define fw12160i_VERSION_STRING "10.04.08" #else -#define FW_VERSION_STRING "10.1.19" +#define FW_VERSION_STRING "10.04.08" #endif #ifdef UNIQUE_FW_NAME @@ -64,1326 +101,1383 @@ #else unsigned short risc_code01[] = { #endif - 0x0804, 0x1041, 0x0000, 0x32f8, 0x0000, 0x2043, 0x4f50, 0x5952, + 0x0804, 0x1041, 0x0000, 0x34e5, 0x0000, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932, 0x2c31, 0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749, 0x4320, 0x434f, 0x5250, 0x4f52, 0x4154, 0x494f, 0x4e00, 0x2049, 0x5350, 0x3132, 0x3136, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, 0x2056, - 0x6572, 0x7369, 0x6f6e, 0x2031, 0x302e, 0x3031, 0x2020, 0x2043, + 0x6572, 0x7369, 0x6f6e, 0x2031, 0x302e, 0x3034, 0x2020, 0x2043, 0x7573, 0x746f, 0x6d65, 0x7220, 0x4e6f, 0x2e20, 0x3030, 0x2050, 0x726f, 0x6475, 0x6374, 0x204e, 0x6f2e, 0x2020, 0x3030, 0x2020, - 0x2400, 0x20c9, 0x8cff, 0x2071, 0x0200, 0x70a0, 0x70a2, 0x2001, + 0x2400, 0x20c9, 0x8eff, 0x2071, 0x0200, 0x70a0, 0x70a2, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1120, 0x2071, 0x0100, 0x70a0, 0x70a2, - 0x20c1, 0x0020, 0x2089, 0x1223, 0x2071, 0x0010, 0x70c3, 0x0004, + 0x20c1, 0x0020, 0x2089, 0x1221, 0x2071, 0x0010, 0x70c3, 0x0004, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, 0x000a, 0x2001, 0x04fd, 0x2004, 0x70d6, 0x2009, 0xfeff, 0x2130, 0x2128, - 0xa1a2, 0x4300, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, - 0xa192, 0x8d00, 0x2009, 0x0000, 0x2001, 0x0032, 0x080c, 0x1d83, - 0x2218, 0x2079, 0x4300, 0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9, + 0xa1a2, 0x4500, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, + 0xa192, 0x8f00, 0x2009, 0x0000, 0x2001, 0x0032, 0x080c, 0x1dcf, + 0x2218, 0x2079, 0x4500, 0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9, 0x0040, 0x42a4, 0x8109, 0x1dd8, 0x2009, 0xff00, 0x3400, 0xa102, 0x0218, 0x0110, 0x20a8, 0x42a4, 0x781b, 0x0064, 0x7814, 0xc0cd, - 0xc0d5, 0x7816, 0x2071, 0x0200, 0x00d6, 0x2069, 0x4340, 0x080c, - 0x42d8, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1130, 0x2069, 0x4380, - 0x2071, 0x0100, 0x080c, 0x42d8, 0x7814, 0xc0d4, 0x7816, 0x00de, + 0xc0d5, 0x7816, 0x2071, 0x0200, 0x00d6, 0x2069, 0x4540, 0x080c, + 0x44bd, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1130, 0x2069, 0x4580, + 0x2071, 0x0100, 0x080c, 0x44bd, 0x7814, 0xc0d4, 0x7816, 0x00de, 0x7eca, 0x7cc2, 0x7bc6, 0x7867, 0x0000, 0x7800, 0xc08d, 0x7802, 0x2031, 0x0030, 0x78af, 0x0101, 0x7823, 0x0002, 0x7827, 0x0002, - 0x2009, 0x0002, 0x2069, 0x4340, 0x681b, 0x0003, 0x6823, 0x0007, - 0x6827, 0x00fa, 0x682b, 0x0008, 0x682f, 0x0028, 0x6837, 0x0000, - 0x683b, 0x0006, 0x6833, 0x0008, 0x683f, 0x0000, 0x8109, 0x0500, - 0x68d3, 0x000a, 0x68c3, 0x43c0, 0x2079, 0x4300, 0x68d7, 0x762d, - 0x68c7, 0x48c0, 0x68cb, 0x47c0, 0x68cf, 0x88c0, 0x68ab, 0x8b44, - 0x68af, 0x8b49, 0x68b3, 0x8b44, 0x68b7, 0x8b44, 0x68a7, 0x0001, - 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x11c8, 0x2069, 0x4380, 0x0860, - 0x68d3, 0x000a, 0x68c3, 0x45c0, 0x68d7, 0x7839, 0x68c7, 0x68c0, - 0x68cb, 0x4840, 0x68cf, 0x89d0, 0x68ab, 0x8b49, 0x68af, 0x8b4e, - 0x68b3, 0x8b49, 0x68b7, 0x8b49, 0x68a7, 0x0001, 0x00e6, 0x2069, - 0x47c0, 0x2071, 0x0200, 0x70ec, 0xd0e4, 0x2019, 0x1c09, 0x2021, - 0x0009, 0x1120, 0x2019, 0x1c0c, 0x2021, 0x000c, 0x080c, 0x1cf3, - 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1188, 0x2069, 0x4840, 0x2071, - 0x0100, 0x70ec, 0xd0e4, 0x2019, 0x1c09, 0x2021, 0x0009, 0x1120, - 0x2019, 0x1c0c, 0x2021, 0x000c, 0x080c, 0x1cf3, 0x00ee, 0x2011, - 0x0002, 0x2069, 0x48c0, 0x2009, 0x0002, 0x20a9, 0x0100, 0x6837, - 0x0000, 0x680b, 0x0040, 0x7bc8, 0xa386, 0xfeff, 0x1128, 0x6817, - 0x0100, 0x681f, 0x0064, 0x0020, 0x6817, 0x0064, 0x681f, 0x0002, - 0xade8, 0x0010, 0x1f04, 0x1137, 0x8109, 0x1d38, 0x2001, 0x01ff, - 0x2004, 0xd0fc, 0x1128, 0x8211, 0x0118, 0x2069, 0x68c0, 0x08d8, - 0x080c, 0x2254, 0x080c, 0x3e39, 0x080c, 0x1b0f, 0x080c, 0x42a0, - 0x2091, 0x2200, 0x2079, 0x4300, 0x2071, 0x0050, 0x2091, 0x2400, - 0x2079, 0x4300, 0x2071, 0x0020, 0x2091, 0x2600, 0x2079, 0x0200, - 0x2071, 0x4340, 0x2091, 0x2800, 0x2079, 0x0100, 0x2071, 0x4380, - 0x2091, 0x2000, 0x2079, 0x4300, 0x2071, 0x0010, 0x3200, 0xa085, - 0x303d, 0x2090, 0x2071, 0x0010, 0x70c3, 0x0000, 0x1004, 0x118e, - 0x70c0, 0xa086, 0x0002, 0x1110, 0x080c, 0x13a3, 0x2039, 0x0000, - 0x080c, 0x129c, 0x78ac, 0xa005, 0x1180, 0x0e04, 0x119c, 0x786c, - 0xa065, 0x0110, 0x080c, 0x1ffe, 0x080c, 0x1da4, 0x0e04, 0x11b1, - 0x786c, 0xa065, 0x0110, 0x080c, 0x1ffe, 0x0e04, 0x11b1, 0x2009, - 0x4347, 0x2011, 0x4387, 0x2104, 0x220c, 0xa105, 0x0110, 0x080c, - 0x1c21, 0x2071, 0x4340, 0x70a4, 0xa005, 0x01e8, 0x7450, 0xa485, - 0x0000, 0x01c8, 0x2079, 0x0200, 0x2091, 0x8000, 0x72d4, 0xa28c, - 0x303d, 0x2190, 0x080c, 0x260d, 0x2091, 0x8000, 0x2091, 0x303d, - 0x0e04, 0x11d3, 0x2079, 0x4300, 0x786c, 0xa065, 0x0120, 0x2071, - 0x0010, 0x080c, 0x1ffe, 0x1d04, 0x11db, 0x2079, 0x4300, 0x2071, - 0x0010, 0x080c, 0x40ed, 0x2071, 0x4380, 0x70a4, 0xa005, 0x0188, - 0x7050, 0xa025, 0x0170, 0x2079, 0x0100, 0x2091, 0x8000, 0x72d4, - 0xa28c, 0x303d, 0x2190, 0x080c, 0x260d, 0x2091, 0x8000, 0x2091, - 0x303d, 0x2079, 0x4300, 0x2071, 0x0010, 0x0e04, 0x11fc, 0x786c, - 0xa065, 0x0110, 0x080c, 0x1ffe, 0x1d04, 0x1190, 0x080c, 0x40ed, - 0x0804, 0x1190, 0x3c00, 0xa084, 0x0007, 0x0002, 0x120e, 0x120e, - 0x1210, 0x1210, 0x1215, 0x1215, 0x121a, 0x121a, 0x080c, 0x243b, - 0x2091, 0x2400, 0x080c, 0x3e9c, 0x0005, 0x2091, 0x2200, 0x080c, - 0x3e9c, 0x0005, 0x2091, 0x2200, 0x080c, 0x3e9c, 0x2091, 0x2400, - 0x080c, 0x3e9c, 0x0005, 0x1243, 0x1243, 0x1244, 0x1244, 0x124f, - 0x124f, 0x124f, 0x124f, 0x1258, 0x1258, 0x1263, 0x1263, 0x124f, - 0x124f, 0x124f, 0x124f, 0x1272, 0x1272, 0x1272, 0x1272, 0x1272, - 0x1272, 0x1272, 0x1272, 0x1272, 0x1272, 0x1272, 0x1272, 0x1272, - 0x1272, 0x1272, 0x1272, 0x0cf8, 0x0006, 0x0106, 0x0126, 0x2091, - 0x2800, 0x080c, 0x2458, 0x012e, 0x010e, 0x000e, 0x000d, 0x0006, - 0x0106, 0x0126, 0x080c, 0x1202, 0x012e, 0x010e, 0x000e, 0x000d, - 0x0006, 0x0106, 0x0126, 0x2091, 0x2600, 0x080c, 0x2458, 0x012e, - 0x010e, 0x000e, 0x000d, 0x0006, 0x0106, 0x0126, 0x2091, 0x2600, - 0x080c, 0x2458, 0x2091, 0x2800, 0x080c, 0x2458, 0x012e, 0x010e, - 0x000e, 0x000d, 0x0006, 0x0106, 0x0126, 0x00e6, 0x00f6, 0x2079, - 0x4300, 0x2071, 0x0200, 0x2069, 0x4340, 0x3d00, 0xd08c, 0x1120, - 0x2069, 0x4380, 0x2071, 0x0100, 0x080c, 0x42d8, 0x00fe, 0x00ee, - 0x012e, 0x010e, 0x000e, 0x000d, 0x7008, 0x800b, 0x1240, 0x7007, - 0x0002, 0xa08c, 0x01e0, 0x1120, 0xd09c, 0x0108, 0x0887, 0x0897, - 0x70c3, 0x4002, 0x0804, 0x13a6, 0x0e04, 0x1308, 0x2061, 0x0000, - 0x6018, 0xd084, 0x1904, 0x1308, 0x7828, 0xa005, 0x1120, 0x0004, - 0x1309, 0x0804, 0x1308, 0xd0fc, 0x0148, 0x0006, 0x080c, 0x1aa9, - 0x000e, 0x0168, 0x2001, 0x4007, 0x0804, 0x13a5, 0x0006, 0x080c, - 0x1a9b, 0x000e, 0x0120, 0x2001, 0x4007, 0x0804, 0x13a5, 0x7910, - 0xd0fc, 0x1128, 0x2061, 0x4340, 0xc19c, 0xc7fc, 0x0020, 0x2061, - 0x4380, 0xc19d, 0xc7fd, 0x6064, 0xa005, 0x15d0, 0x7912, 0x6083, - 0x0000, 0x7828, 0xc0fc, 0xa086, 0x0018, 0x1120, 0x00c6, 0x080c, - 0x18c9, 0x00ce, 0x782b, 0x0000, 0x607c, 0xa065, 0x0190, 0x00c6, - 0x609c, 0x080c, 0x1b76, 0x00ce, 0x609f, 0x0000, 0x080c, 0x19db, - 0x2009, 0x0018, 0x6087, 0x0103, 0x080c, 0x1ab7, 0x1198, 0x080c, - 0x1b02, 0x7810, 0xd09c, 0x1118, 0x2061, 0x4340, 0x0020, 0x2061, - 0x4380, 0xc09c, 0x7812, 0x607f, 0x0000, 0x60d4, 0xd0c4, 0x0130, - 0xc0c4, 0x60d6, 0x2001, 0x4005, 0x0804, 0x13a5, 0x0804, 0x13a3, - 0x0005, 0xa006, 0x70c2, 0x70c6, 0x70ca, 0x70ce, 0x70da, 0x70c0, - 0xa08a, 0x0040, 0x1a04, 0x1355, 0x0002, 0x13a3, 0x13f1, 0x13bf, - 0x1425, 0x1459, 0x1459, 0x13b7, 0x19f3, 0x1463, 0x13b1, 0x13c3, - 0x13c4, 0x13c5, 0x13c6, 0x19f7, 0x13b1, 0x1470, 0x14c5, 0x18e4, - 0x19ed, 0x13c7, 0x1795, 0x17cb, 0x17fa, 0x183d, 0x1752, 0x175f, - 0x1772, 0x1784, 0x159a, 0x13b1, 0x14f7, 0x1502, 0x1510, 0x151e, - 0x1535, 0x1543, 0x1546, 0x1554, 0x1562, 0x156c, 0x1580, 0x158c, - 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x15a7, 0x15b8, 0x15d2, 0x1606, - 0x162f, 0x1641, 0x1644, 0x1677, 0x16aa, 0x16bc, 0x1720, 0x1730, - 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x1742, 0x2100, 0xa08a, 0x0040, - 0x1a04, 0x13b1, 0x0002, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, - 0x1a19, 0x1a1f, 0x13b1, 0x13b1, 0x13b1, 0x1a23, 0x1a63, 0x13b1, - 0x13b1, 0x13b1, 0x13b1, 0x13ec, 0x1454, 0x146b, 0x14c0, 0x18df, - 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x1a67, 0x1a0b, 0x1a15, 0x13b1, - 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, - 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, - 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, - 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, - 0x13b1, 0x13b1, 0x13b1, 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0028, - 0x73ce, 0x72ca, 0x71c6, 0x2001, 0x4000, 0x70c2, 0x0e04, 0x13a6, + 0x2009, 0x0002, 0x2069, 0x4540, 0x681b, 0x0003, 0x6823, 0x0007, + 0x6827, 0x00fa, 0x682b, 0x0008, 0x682f, 0x0028, 0x6837, 0x0006, + 0x6833, 0x0008, 0x683b, 0x0000, 0x8109, 0x0500, 0x68cf, 0x000a, + 0x68bf, 0x45c0, 0x2079, 0x4500, 0x68d3, 0x762d, 0x68c3, 0x4ac0, + 0x68c7, 0x49c0, 0x68cb, 0x8ac0, 0x68a7, 0x8d44, 0x68ab, 0x8d49, + 0x68af, 0x8d44, 0x68b3, 0x8d44, 0x68a3, 0x0001, 0x2001, 0x01ff, + 0x2004, 0xd0fc, 0x11c8, 0x2069, 0x4580, 0x0870, 0x68cf, 0x000a, + 0x68bf, 0x47c0, 0x68d3, 0x7839, 0x68c3, 0x6ac0, 0x68c7, 0x4a40, + 0x68cb, 0x8bd0, 0x68a7, 0x8d49, 0x68ab, 0x8d4e, 0x68af, 0x8d49, + 0x68b3, 0x8d49, 0x68a3, 0x0001, 0x00e6, 0x2069, 0x49c0, 0x2071, + 0x0200, 0x70ec, 0xd0e4, 0x2019, 0x1c09, 0x2021, 0x0009, 0x1120, + 0x2019, 0x1c0c, 0x2021, 0x000c, 0x080c, 0x1d3f, 0x2001, 0x01ff, + 0x2004, 0xd0fc, 0x1188, 0x2069, 0x4a40, 0x2071, 0x0100, 0x70ec, + 0xd0e4, 0x2019, 0x1c09, 0x2021, 0x0009, 0x1120, 0x2019, 0x1c0c, + 0x2021, 0x000c, 0x080c, 0x1d3f, 0x00ee, 0x2011, 0x0002, 0x2069, + 0x4ac0, 0x2009, 0x0002, 0x20a9, 0x0100, 0x6837, 0x0000, 0x680b, + 0x0040, 0x7bc8, 0xa386, 0xfeff, 0x1128, 0x6817, 0x0100, 0x681f, + 0x0064, 0x0020, 0x6817, 0x0064, 0x681f, 0x0002, 0xade8, 0x0010, + 0x1f04, 0x1135, 0x8109, 0x1d38, 0x2001, 0x01ff, 0x2004, 0xd0fc, + 0x1128, 0x8211, 0x0118, 0x2069, 0x6ac0, 0x08d8, 0x080c, 0x22b7, + 0x080c, 0x3fba, 0x080c, 0x1b51, 0x080c, 0x4489, 0x2091, 0x2200, + 0x2079, 0x4500, 0x2071, 0x0050, 0x2091, 0x2400, 0x2079, 0x4500, + 0x2071, 0x0020, 0x2091, 0x2600, 0x2079, 0x0200, 0x2071, 0x4540, + 0x2091, 0x2800, 0x2079, 0x0100, 0x2071, 0x4580, 0x2091, 0x2000, + 0x2079, 0x4500, 0x2071, 0x0010, 0x3200, 0xa085, 0x303d, 0x2090, + 0x2071, 0x0010, 0x70c3, 0x0000, 0x1004, 0x118c, 0x70c0, 0xa086, + 0x0002, 0x1110, 0x080c, 0x13b3, 0x2039, 0x0000, 0x080c, 0x12ab, + 0x78ac, 0xa005, 0x1180, 0x0e04, 0x119a, 0x786c, 0xa065, 0x0110, + 0x080c, 0x2061, 0x080c, 0x1df0, 0x0e04, 0x11af, 0x786c, 0xa065, + 0x0110, 0x080c, 0x2061, 0x0e04, 0x11af, 0x2009, 0x4547, 0x2011, + 0x4587, 0x2104, 0x220c, 0xa105, 0x0110, 0x080c, 0x1c63, 0x2071, + 0x4540, 0x70a0, 0xa005, 0x01e8, 0x744c, 0xa485, 0x0000, 0x01c8, + 0x2079, 0x0200, 0x2091, 0x8000, 0x72d0, 0xa28c, 0x303d, 0x2190, + 0x080c, 0x26ff, 0x2091, 0x8000, 0x2091, 0x303d, 0x0e04, 0x11d1, + 0x2079, 0x4500, 0x786c, 0xa065, 0x0120, 0x2071, 0x0010, 0x080c, + 0x2061, 0x1d04, 0x11d9, 0x2079, 0x4500, 0x2071, 0x0010, 0x080c, + 0x42c7, 0x2071, 0x4580, 0x70a0, 0xa005, 0x0188, 0x704c, 0xa025, + 0x0170, 0x2079, 0x0100, 0x2091, 0x8000, 0x72d0, 0xa28c, 0x303d, + 0x2190, 0x080c, 0x26ff, 0x2091, 0x8000, 0x2091, 0x303d, 0x2079, + 0x4500, 0x2071, 0x0010, 0x0e04, 0x11fa, 0x786c, 0xa065, 0x0110, + 0x080c, 0x2061, 0x1d04, 0x118e, 0x080c, 0x42c7, 0x0804, 0x118e, + 0x3c00, 0xa084, 0x0007, 0x0002, 0x120c, 0x120c, 0x120e, 0x120e, + 0x1213, 0x1213, 0x1218, 0x1218, 0x080c, 0x252b, 0x2091, 0x2400, + 0x080c, 0x4052, 0x0005, 0x2091, 0x2200, 0x080c, 0x4052, 0x0005, + 0x2091, 0x2200, 0x080c, 0x4052, 0x2091, 0x2400, 0x080c, 0x4052, + 0x0005, 0x1241, 0x1241, 0x1242, 0x1242, 0x124d, 0x124d, 0x124d, + 0x124d, 0x1256, 0x1256, 0x1261, 0x1261, 0x124d, 0x124d, 0x124d, + 0x124d, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, + 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, + 0x1270, 0x0cf8, 0x0006, 0x0106, 0x0126, 0x2091, 0x2800, 0x080c, + 0x2548, 0x012e, 0x010e, 0x000e, 0x000d, 0x0006, 0x0106, 0x0126, + 0x080c, 0x1200, 0x012e, 0x010e, 0x000e, 0x000d, 0x0006, 0x0106, + 0x0126, 0x2091, 0x2600, 0x080c, 0x2548, 0x012e, 0x010e, 0x000e, + 0x000d, 0x0006, 0x0106, 0x0126, 0x2091, 0x2600, 0x080c, 0x2548, + 0x2091, 0x2800, 0x080c, 0x2548, 0x012e, 0x010e, 0x000e, 0x000d, + 0x0006, 0x0106, 0x0126, 0x00d6, 0x00e6, 0x00f6, 0x2079, 0x4500, + 0x2071, 0x0200, 0x2069, 0x4540, 0x3d00, 0xd08c, 0x0130, 0x70ec, + 0xa084, 0x1c00, 0x78e2, 0x080c, 0x44bd, 0x3d00, 0xd084, 0x0150, + 0x2069, 0x4580, 0x2071, 0x0100, 0x70ec, 0xa084, 0x1c00, 0x78e6, + 0x080c, 0x44bd, 0x080c, 0x24dc, 0x00fe, 0x00ee, 0x00de, 0x012e, + 0x010e, 0x000e, 0x000d, 0x7008, 0x800b, 0x1240, 0x7007, 0x0002, + 0xa08c, 0x01e0, 0x1120, 0xd09c, 0x0108, 0x0887, 0x0897, 0x70c3, + 0x4002, 0x0804, 0x13b6, 0x0e04, 0x1317, 0x2061, 0x0000, 0x6018, + 0xd084, 0x1904, 0x1317, 0x7828, 0xa005, 0x1120, 0x0004, 0x1318, + 0x0804, 0x1317, 0xd0fc, 0x0148, 0x0006, 0x080c, 0x1aeb, 0x000e, + 0x0168, 0x2001, 0x4007, 0x0804, 0x13b5, 0x0006, 0x080c, 0x1add, + 0x000e, 0x0120, 0x2001, 0x4007, 0x0804, 0x13b5, 0x7910, 0xd0fc, + 0x1128, 0x2061, 0x4540, 0xc19c, 0xc7fc, 0x0020, 0x2061, 0x4580, + 0xc19d, 0xc7fd, 0x6060, 0xa005, 0x15d0, 0x7912, 0x607f, 0x0000, + 0x7828, 0xc0fc, 0xa086, 0x0018, 0x1120, 0x00c6, 0x080c, 0x190a, + 0x00ce, 0x782b, 0x0000, 0x6078, 0xa065, 0x0190, 0x00c6, 0x609c, + 0x080c, 0x1bb8, 0x00ce, 0x609f, 0x0000, 0x080c, 0x1a1b, 0x2009, + 0x0018, 0x6087, 0x0103, 0x080c, 0x1af9, 0x1198, 0x080c, 0x1b44, + 0x7810, 0xd09c, 0x1118, 0x2061, 0x4540, 0x0020, 0x2061, 0x4580, + 0xc09c, 0x7812, 0x607b, 0x0000, 0x60d0, 0xd0c4, 0x0130, 0xc0c4, + 0x60d2, 0x2001, 0x4005, 0x0804, 0x13b5, 0x0804, 0x13b3, 0x0005, + 0xa006, 0x70c2, 0x70c6, 0x70ca, 0x70ce, 0x70da, 0x70c0, 0xa03d, + 0xa08a, 0x0040, 0x1a04, 0x1365, 0x0002, 0x13b3, 0x1401, 0x13cf, + 0x1435, 0x1469, 0x1469, 0x13c7, 0x1a33, 0x1473, 0x13c1, 0x13d3, + 0x13d4, 0x13d5, 0x13d6, 0x1a37, 0x13c1, 0x1480, 0x14d5, 0x1925, + 0x1a2d, 0x13d7, 0x17b4, 0x17ea, 0x1819, 0x185c, 0x1771, 0x177e, + 0x1791, 0x17a3, 0x15aa, 0x13c1, 0x1507, 0x1512, 0x1520, 0x152e, + 0x1545, 0x1553, 0x1556, 0x1564, 0x1572, 0x157c, 0x1590, 0x159c, + 0x13c1, 0x13c1, 0x13c1, 0x13c1, 0x15b7, 0x15c8, 0x15e2, 0x1616, + 0x163f, 0x1651, 0x1654, 0x167f, 0x16b8, 0x16ca, 0x173f, 0x174f, + 0x13c1, 0x13c1, 0x13c1, 0x13c1, 0x1761, 0x2100, 0xa08a, 0x0040, + 0x1a04, 0x13c1, 0x0002, 0x13c1, 0x13c1, 0x13c1, 0x13c1, 0x13c1, + 0x1a59, 0x1a5f, 0x13c1, 0x13c1, 0x13c1, 0x1a63, 0x1aa3, 0x13c1, + 0x13c1, 0x13c1, 0x13c1, 0x13fc, 0x1464, 0x147b, 0x14d0, 0x1920, + 0x13c1, 0x13c1, 0x13c1, 0x13c1, 0x1aa7, 0x1a4b, 0x1a55, 0x18ef, + 0x13c1, 0x13c1, 0x13c1, 0x13c1, 0x13c1, 0x13c1, 0x13c1, 0x13c1, + 0x13c1, 0x13c1, 0x13c1, 0x13c1, 0x13c1, 0x13c1, 0x13c1, 0x13c1, + 0x13c1, 0x13c1, 0x13c1, 0x13c1, 0x13c1, 0x13c1, 0x13c1, 0x13c1, + 0x13c1, 0x13c1, 0x13c1, 0x13c1, 0x13c1, 0x13c1, 0x13c1, 0x13c1, + 0x13c1, 0x13c1, 0x13c1, 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0028, + 0x73ce, 0x72ca, 0x71c6, 0x2001, 0x4000, 0x70c2, 0x0e04, 0x13b6, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x0005, 0x70c3, 0x4001, 0x0c90, 0x70c3, 0x4006, 0x0c78, 0x2099, 0x0041, 0x20a1, 0x0041, 0x20a9, 0x0005, 0x53a3, 0x0c20, 0x70c4, 0x70c3, 0x0004, 0x0807, 0x08f8, 0x08f0, 0x08e8, 0x08e0, 0x2091, 0x8000, 0x70c3, 0x0004, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, - 0x2020, 0x70d3, 0x000a, 0x2001, 0x0001, 0x70d6, 0x2079, 0x0000, + 0x2020, 0x70d3, 0x000a, 0x2001, 0x0004, 0x70d6, 0x2079, 0x0000, 0x781b, 0x0001, 0x2031, 0x0030, 0x2059, 0x1000, 0x2029, 0x041a, 0x2051, 0x0445, 0x2061, 0x0447, 0x20c1, 0x0020, 0x2091, 0x5000, 0x2091, 0x4080, 0x0804, 0x0418, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0018, 0x2029, 0x0000, 0x2520, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x20a0, 0x2099, 0x0030, 0x7003, 0x0001, 0x7007, 0x0006, 0x731a, - 0x721e, 0x7422, 0x7526, 0x2021, 0x0040, 0x81ff, 0x0904, 0x13a3, + 0x721e, 0x7422, 0x7526, 0x2021, 0x0040, 0x81ff, 0x0904, 0x13b3, 0xa182, 0x0040, 0x1210, 0x2120, 0xa006, 0x2008, 0x8403, 0x7012, 0x7007, 0x0004, 0x7007, 0x0001, 0x7008, 0xd0fc, 0x0de8, 0x7007, - 0x0002, 0xa084, 0x01e0, 0x0120, 0x70c3, 0x4002, 0x0804, 0x13a6, - 0x24a8, 0x53a5, 0x0c10, 0x0804, 0x13a3, 0x2029, 0x0000, 0x2520, + 0x0002, 0xa084, 0x01e0, 0x0120, 0x70c3, 0x4002, 0x0804, 0x13b6, + 0x24a8, 0x53a5, 0x0c10, 0x0804, 0x13b3, 0x2029, 0x0000, 0x2520, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x2098, 0x20a1, 0x0030, 0x7003, 0x0000, 0x7007, 0x0006, 0x731a, 0x721e, 0x7422, 0x7526, 0x2021, - 0x0040, 0x7007, 0x0006, 0x81ff, 0x0904, 0x13a3, 0xa182, 0x0040, + 0x0040, 0x7007, 0x0006, 0x81ff, 0x0904, 0x13b3, 0xa182, 0x0040, 0x1210, 0x2120, 0xa006, 0x2008, 0x8403, 0x7012, 0x24a8, 0x53a6, 0x7007, 0x0001, 0x7008, 0xd0fc, 0x0de8, 0xa084, 0x01e0, 0x0d48, - 0x70c3, 0x4002, 0x0804, 0x13a6, 0x75d8, 0x74dc, 0x75da, 0x74de, + 0x70c3, 0x4002, 0x0804, 0x13b6, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0878, 0x71c4, 0x70c8, 0x2114, 0xa79e, 0x0004, 0x1108, 0x200a, - 0x72ca, 0x0804, 0x13a2, 0x70c7, 0x000a, 0x70cb, 0x0001, 0x70cf, - 0x0013, 0x0804, 0x13a3, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0018, + 0x72ca, 0x0804, 0x13b2, 0x70c7, 0x000a, 0x70cb, 0x0004, 0x70cf, + 0x0008, 0x0804, 0x13b3, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0018, 0x2029, 0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d0, 0x70c6, 0x72ca, 0x73ce, 0x74d2, 0xa005, 0x05f0, 0xa40a, 0x0110, 0x1a04, - 0x13a5, 0x8001, 0x7872, 0xa084, 0xfc00, 0x0138, 0x78ac, 0xc085, - 0x78ae, 0x2001, 0x4005, 0x0804, 0x13a5, 0x7b7e, 0x7a7a, 0x7e86, + 0x13b5, 0x8001, 0x7872, 0xa084, 0xfc00, 0x0138, 0x78ac, 0xc085, + 0x78ae, 0x2001, 0x4005, 0x0804, 0x13b5, 0x7b7e, 0x7a7a, 0x7e86, 0x7d82, 0x7c76, 0xa48c, 0xff00, 0x0170, 0x8407, 0x8004, 0x8004, 0x810c, 0x810c, 0x810f, 0xa118, 0xa291, 0x0000, 0xa6b1, 0x0000, 0xa581, 0x0000, 0x0050, 0x8407, 0x8004, 0x8004, 0xa318, 0xa291, 0x0000, 0xa6b1, 0x0000, 0xa581, 0x0000, 0x731a, 0x721e, 0x7622, 0x7026, 0xa605, 0x0118, 0x7a10, 0xc2c5, 0x7a12, 0x78ac, 0xa084, - 0xfffc, 0x78ae, 0x0018, 0x78ac, 0xc085, 0x78ae, 0x0804, 0x13a3, + 0xfffc, 0x78ae, 0x0018, 0x78ac, 0xc085, 0x78ae, 0x0804, 0x13b3, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0018, 0x2029, 0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d4, 0x70c6, 0x72ca, 0x73ce, 0x74d6, - 0xa005, 0x0500, 0xa40a, 0x0110, 0x1a04, 0x13a5, 0x8001, 0x7892, + 0xa005, 0x0500, 0xa40a, 0x0110, 0x1a04, 0x13b5, 0x8001, 0x7892, 0xa084, 0xfc00, 0x0138, 0x78ac, 0xc0c5, 0x78ae, 0x2001, 0x4005, - 0x0804, 0x13a5, 0x7a9a, 0x7b9e, 0x7da2, 0x7ea6, 0x2600, 0xa505, + 0x0804, 0x13b5, 0x7a9a, 0x7b9e, 0x7da2, 0x7ea6, 0x2600, 0xa505, 0x0118, 0x7a10, 0xc2c5, 0x7a12, 0x7c96, 0x78ac, 0xa084, 0xfcff, - 0x78ae, 0x0018, 0x78ac, 0xc0c5, 0x78ae, 0x0804, 0x13a3, 0x2009, + 0x78ae, 0x0018, 0x78ac, 0xc0c5, 0x78ae, 0x0804, 0x13b3, 0x2009, 0x0000, 0x786c, 0xa065, 0x0118, 0x8108, 0x6000, 0x0cd8, 0x7ac4, - 0x0804, 0x13a1, 0x2009, 0x4348, 0x210c, 0x2001, 0x01ff, 0x2004, - 0xd0fc, 0x1904, 0x13a2, 0x2011, 0x4388, 0x2214, 0x0804, 0x13a1, - 0x2009, 0x4349, 0x210c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, - 0x13a2, 0x2011, 0x4389, 0x2214, 0x0804, 0x13a1, 0x2061, 0x4340, + 0x0804, 0x13b1, 0x2009, 0x4548, 0x210c, 0x2001, 0x01ff, 0x2004, + 0xd0fc, 0x1904, 0x13b2, 0x2011, 0x4588, 0x2214, 0x0804, 0x13b1, + 0x2009, 0x4549, 0x210c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, + 0x13b2, 0x2011, 0x4589, 0x2214, 0x0804, 0x13b1, 0x2061, 0x4540, 0x6128, 0x622c, 0x8214, 0x8214, 0x8214, 0x2001, 0x01ff, 0x2004, - 0xd0fc, 0x1148, 0x2061, 0x4380, 0x6328, 0x73da, 0x632c, 0x831c, - 0x831c, 0x831c, 0x73de, 0x0804, 0x13a1, 0x2009, 0x434c, 0x210c, - 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13a2, 0x2011, 0x438c, - 0x2214, 0x0804, 0x13a1, 0x7918, 0x0804, 0x13a2, 0x2009, 0x434d, - 0x210c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13a2, 0x2011, - 0x438d, 0x2214, 0x0804, 0x13a1, 0x2009, 0x434e, 0x210c, 0x2001, - 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13a2, 0x2011, 0x438e, 0x2214, - 0x0804, 0x13a1, 0x7920, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, - 0x13a2, 0x7a24, 0x0804, 0x13a1, 0x2011, 0x4840, 0x71c4, 0xd1fc, - 0x1110, 0x2011, 0x47c0, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, - 0x8003, 0xa268, 0x6a00, 0x6b08, 0x6c1c, 0x74da, 0x0804, 0x13a0, - 0x77c4, 0x080c, 0x1b1d, 0x2091, 0x8000, 0x6b1c, 0x6a14, 0x2091, - 0x8001, 0x2708, 0x0804, 0x13a0, 0x2061, 0x4340, 0x6118, 0x2001, - 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13a2, 0x2061, 0x4380, 0x6218, - 0x0804, 0x13a1, 0x77c4, 0x080c, 0x1b1d, 0x2091, 0x8000, 0x6908, - 0x6a18, 0x6b10, 0x77da, 0x2091, 0x8001, 0x0804, 0x13a0, 0x71c4, - 0x2110, 0xa294, 0x000f, 0xa282, 0x0010, 0x1a04, 0x139c, 0x080c, - 0x230e, 0xa384, 0x4000, 0x0110, 0xa295, 0x0020, 0x0804, 0x13a0, - 0x71c4, 0x2100, 0xc0bc, 0xa082, 0x0010, 0x1a04, 0x139c, 0xd1bc, - 0x1120, 0x2011, 0x4348, 0x2204, 0x0020, 0x2011, 0x4388, 0x2204, - 0xc0bd, 0x0006, 0x2100, 0xc0bc, 0x2012, 0x080c, 0x22b4, 0x001e, - 0x0804, 0x13a2, 0x71c4, 0x2021, 0x4349, 0x2404, 0x70c6, 0x2019, - 0x0000, 0x0030, 0x71c8, 0x2021, 0x4389, 0x2404, 0x70ca, 0xc3fd, - 0x2011, 0x15fe, 0x20a9, 0x0008, 0x2204, 0xa106, 0x0138, 0x8210, - 0x1f04, 0x15e4, 0x71c4, 0x72c8, 0x0804, 0x139b, 0xa292, 0x15fe, - 0x0026, 0x2122, 0x001e, 0x080c, 0x22c6, 0x2001, 0x01ff, 0x2004, - 0xd0fc, 0x1110, 0xd3fc, 0x09f0, 0x0804, 0x13a3, 0x03e8, 0x00fa, - 0x01f4, 0x02ee, 0x0064, 0x0019, 0x0032, 0x004b, 0x2061, 0x4340, + 0xd0fc, 0x1148, 0x2061, 0x4580, 0x6328, 0x73da, 0x632c, 0x831c, + 0x831c, 0x831c, 0x73de, 0x0804, 0x13b1, 0x2009, 0x454c, 0x210c, + 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b2, 0x2011, 0x458c, + 0x2214, 0x0804, 0x13b1, 0x7918, 0x0804, 0x13b2, 0x2009, 0x0202, + 0x210c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b2, 0x2011, + 0x0102, 0x2214, 0x0804, 0x13b1, 0x2009, 0x454d, 0x210c, 0x2001, + 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b2, 0x2011, 0x458d, 0x2214, + 0x0804, 0x13b1, 0x7920, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, + 0x13b2, 0x7a24, 0x0804, 0x13b1, 0x2011, 0x4a40, 0x71c4, 0xd1fc, + 0x1110, 0x2011, 0x49c0, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, + 0x8003, 0xa268, 0x6a00, 0x6b08, 0x6c1c, 0x74da, 0x0804, 0x13b0, + 0x77c4, 0x080c, 0x1b5f, 0x2091, 0x8000, 0x6b1c, 0x6a14, 0x2091, + 0x8001, 0x2708, 0x0804, 0x13b0, 0x2061, 0x4540, 0x6118, 0x2001, + 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b2, 0x2061, 0x4580, 0x6218, + 0x0804, 0x13b1, 0x77c4, 0x080c, 0x1b5f, 0x2091, 0x8000, 0x6908, + 0x6a18, 0x6b10, 0x77da, 0x2091, 0x8001, 0x0804, 0x13b0, 0x71c4, + 0x2110, 0xa294, 0x000f, 0xa282, 0x0010, 0x1a04, 0x13ac, 0x080c, + 0x2373, 0xa384, 0x4000, 0x0110, 0xa295, 0x0020, 0x0804, 0x13b0, + 0x71c4, 0x2100, 0xc0bc, 0xa082, 0x0010, 0x1a04, 0x13ac, 0xd1bc, + 0x1120, 0x2011, 0x4548, 0x2204, 0x0020, 0x2011, 0x4588, 0x2204, + 0xc0bd, 0x0006, 0x2100, 0xc0bc, 0x2012, 0x080c, 0x2319, 0x001e, + 0x0804, 0x13b2, 0x71c4, 0x2021, 0x4549, 0x2404, 0x70c6, 0x2019, + 0x0000, 0x0030, 0x71c8, 0x2021, 0x4589, 0x2404, 0x70ca, 0xc3fd, + 0x2011, 0x160e, 0x20a9, 0x0008, 0x2204, 0xa106, 0x0138, 0x8210, + 0x1f04, 0x15f4, 0x71c4, 0x72c8, 0x0804, 0x13ab, 0xa292, 0x160e, + 0x0026, 0x2122, 0x001e, 0x080c, 0x232b, 0x2001, 0x01ff, 0x2004, + 0xd0fc, 0x1110, 0xd3fc, 0x09f0, 0x0804, 0x13b3, 0x03e8, 0x00fa, + 0x01f4, 0x02ee, 0x0064, 0x0019, 0x0032, 0x004b, 0x2061, 0x4540, 0x6128, 0x622c, 0x8214, 0x8214, 0x8214, 0x70c4, 0x602a, 0x70c8, 0x8003, 0x8003, 0x8003, 0x602e, 0x2001, 0x01ff, 0x2004, 0xd0fc, - 0x11a0, 0x0026, 0x0016, 0x2061, 0x4380, 0x6128, 0x622c, 0x8214, + 0x11a0, 0x0026, 0x0016, 0x2061, 0x4580, 0x6128, 0x622c, 0x8214, 0x8214, 0x8214, 0x70d8, 0x602a, 0x70dc, 0x8003, 0x8003, 0x8003, - 0x602e, 0x71da, 0x72de, 0x001e, 0x002e, 0x0804, 0x13a1, 0x2061, - 0x4340, 0x6130, 0x70c4, 0x6032, 0x2001, 0x01ff, 0x2004, 0xd0fc, - 0x1904, 0x13a2, 0x2061, 0x4380, 0x6230, 0x70c8, 0x6032, 0x0804, - 0x13a1, 0x7918, 0x0804, 0x13a2, 0x71c4, 0xa184, 0xffcf, 0x0148, - 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x139c, 0x72c8, 0x0804, - 0x139b, 0x2011, 0x434d, 0x2204, 0x2112, 0x0006, 0x2019, 0x0000, - 0x080c, 0x2302, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x0118, 0x001e, - 0x0804, 0x13a2, 0x71c8, 0xa184, 0xffcf, 0x0128, 0x0006, 0x2110, - 0x71c4, 0x0804, 0x139b, 0x2011, 0x438d, 0x2204, 0x2112, 0x0006, - 0xc3fd, 0x080c, 0x2302, 0x002e, 0x001e, 0x0804, 0x13a1, 0x71c4, + 0x602e, 0x71da, 0x72de, 0x001e, 0x002e, 0x0804, 0x13b1, 0x2061, + 0x4540, 0x6130, 0x70c4, 0x6032, 0x2001, 0x01ff, 0x2004, 0xd0fc, + 0x1904, 0x13b2, 0x2061, 0x4580, 0x6230, 0x70c8, 0x6032, 0x0804, + 0x13b1, 0x7918, 0x0804, 0x13b2, 0x71c4, 0xa184, 0xf0cf, 0x0148, + 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13ac, 0x72c8, 0x0804, + 0x13ab, 0x0006, 0x2019, 0x0000, 0x080c, 0x2367, 0x2001, 0x01ff, + 0x2004, 0xd0fc, 0x0118, 0x001e, 0x0804, 0x13b2, 0x71c8, 0xa184, + 0xf0cf, 0x0128, 0x0006, 0x2110, 0x71c4, 0x0804, 0x13ab, 0x0006, + 0xc3fd, 0x080c, 0x2367, 0x002e, 0x001e, 0x0804, 0x13b1, 0x71c4, 0xa182, 0x0010, 0x0248, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, - 0x139c, 0x72c8, 0x0804, 0x139b, 0x2011, 0x434e, 0x2204, 0x0006, - 0x2112, 0x2019, 0x0000, 0x080c, 0x22ef, 0x2001, 0x01ff, 0x2004, - 0xd0fc, 0x0118, 0x001e, 0x0804, 0x13a2, 0x71c8, 0xa182, 0x0010, - 0x0228, 0x0006, 0x2110, 0x71c4, 0x0804, 0x139b, 0x2011, 0x438e, - 0x2204, 0x0006, 0x2112, 0xc3fd, 0x080c, 0x22ef, 0x002e, 0x001e, - 0x0804, 0x13a1, 0x71c4, 0x72c8, 0xa184, 0xfffd, 0x1904, 0x139b, - 0xa284, 0xfffd, 0x1904, 0x139b, 0x2100, 0x7920, 0x7822, 0x2200, - 0x7a24, 0x7826, 0x0804, 0x13a1, 0x2011, 0x4840, 0x71c4, 0xd1fc, - 0x1110, 0x2011, 0x47c0, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, - 0x8003, 0xa268, 0x72c8, 0x73cc, 0x74d8, 0x71c6, 0x6800, 0x70ca, - 0x73ce, 0x74da, 0x2091, 0x8000, 0x6a02, 0xd2ac, 0x1118, 0x2021, - 0x0000, 0x0078, 0xa484, 0x00ff, 0xa082, 0x0002, 0x16e8, 0x843f, - 0xa7bc, 0x00ff, 0x0130, 0xa786, 0x0002, 0x15b0, 0xa484, 0x00ff, - 0x0598, 0x2061, 0x0200, 0xd1fc, 0x0110, 0x2061, 0x0100, 0x2029, - 0x0009, 0x2031, 0x0062, 0x843f, 0xa7bc, 0x00ff, 0x0130, 0x8307, - 0xa084, 0x00ff, 0x1110, 0xa73d, 0x11f8, 0x2041, 0x001d, 0x8307, - 0xa084, 0x00ff, 0x0150, 0xa842, 0x02b8, 0xa3bc, 0x00ff, 0x2500, - 0xa702, 0x0290, 0x2600, 0xa702, 0x1278, 0x2039, 0x003a, 0x6804, - 0xa705, 0x6806, 0x6b0a, 0x6b0c, 0x73ce, 0x681c, 0x70da, 0x6c1e, - 0x2091, 0x8001, 0x0804, 0x13a3, 0x2091, 0x8001, 0x0804, 0x139d, - 0x77c4, 0x080c, 0x1b1d, 0x2091, 0x8000, 0x6a14, 0x6b1c, 0x2091, - 0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e, 0x2708, 0x0804, 0x13a0, - 0x70c4, 0x2061, 0x4340, 0x6118, 0x601a, 0x2001, 0x01ff, 0x2004, - 0xd0fc, 0x1904, 0x13a2, 0x70c8, 0x2061, 0x4380, 0x6218, 0x601a, - 0x0804, 0x13a1, 0x71c4, 0x72c8, 0x73cc, 0xa182, 0x0010, 0x1a04, - 0x139c, 0x080c, 0x2332, 0xa384, 0x4000, 0x0110, 0xa295, 0x0020, - 0x0804, 0x13a0, 0x77c4, 0x080c, 0x1b1d, 0x2091, 0x8000, 0x6a08, - 0xc28d, 0x6a0a, 0x2091, 0x8001, 0x2708, 0x0804, 0x13a1, 0x77c4, - 0x080c, 0x1b1d, 0x2091, 0x8000, 0x6a08, 0xa294, 0xfff9, 0x6a0a, - 0x6804, 0xa005, 0x0110, 0x080c, 0x2233, 0x2091, 0x8001, 0x2708, - 0x0804, 0x13a1, 0x77c4, 0x080c, 0x1b1d, 0x2091, 0x8000, 0x6a08, - 0xc295, 0x6a0a, 0x6804, 0xa005, 0x0110, 0x080c, 0x2233, 0x2091, - 0x8001, 0x2708, 0x0804, 0x13a1, 0x77c4, 0x2041, 0x0001, 0x2049, - 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x080c, 0x1b35, 0x2091, - 0x8001, 0x2708, 0x6a08, 0x0804, 0x13a1, 0x77c4, 0xd7fc, 0x0128, - 0x080c, 0x1aa9, 0x0138, 0x0804, 0x13a5, 0x080c, 0x1a9b, 0x0110, - 0x0804, 0x13a5, 0x73c8, 0x72cc, 0x77c6, 0x73ca, 0x72ce, 0x080c, - 0x1bad, 0x11e8, 0x6818, 0xa005, 0x01a0, 0x2708, 0x0076, 0x080c, - 0x2351, 0x007e, 0x1170, 0x2001, 0x0015, 0xd7fc, 0x1118, 0x2061, - 0x4340, 0x0018, 0xc0fd, 0x2061, 0x4380, 0x782a, 0x2091, 0x8001, - 0x0005, 0x2091, 0x8001, 0x2001, 0x4005, 0x0804, 0x13a5, 0x2091, - 0x8001, 0x0804, 0x13a3, 0x77c4, 0xd7fc, 0x0128, 0x080c, 0x1aa9, - 0x0138, 0x0804, 0x13a5, 0x080c, 0x1a9b, 0x0110, 0x0804, 0x13a5, - 0x77c6, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, - 0x8000, 0x080c, 0x1b35, 0x2009, 0x0016, 0xd7fc, 0x1118, 0x2061, - 0x4340, 0x0018, 0x2061, 0x4380, 0xc1fd, 0x6067, 0x0003, 0x607f, - 0x0000, 0x6776, 0x6083, 0x000f, 0x792a, 0x080c, 0x2233, 0x2091, - 0x8001, 0x0005, 0x77c8, 0x77ca, 0x77c4, 0x77c6, 0xd7fc, 0x0128, - 0x080c, 0x1aa9, 0x0138, 0x0804, 0x13a5, 0x080c, 0x1a9b, 0x0110, - 0x0804, 0x13a5, 0xa7bc, 0xff00, 0x2091, 0x8000, 0x2009, 0x0017, - 0xd7fc, 0x1118, 0x2061, 0x4340, 0x0018, 0x2061, 0x4380, 0xc1fd, - 0x607f, 0x0000, 0x6067, 0x0002, 0x6776, 0x6083, 0x000f, 0x792a, - 0x080c, 0x2233, 0x2091, 0x8001, 0x2041, 0x0021, 0x2049, 0x0005, - 0x2051, 0x0010, 0x2091, 0x8000, 0x70c8, 0xa005, 0x0118, 0x60d4, - 0xc0fd, 0x60d6, 0x080c, 0x1b35, 0x70c8, 0x6836, 0x8738, 0xa784, - 0x001f, 0x1dc0, 0x2091, 0x8001, 0x0005, 0x72c8, 0xd284, 0x0128, - 0x080c, 0x1aa9, 0x0138, 0x0804, 0x13a5, 0x080c, 0x1a9b, 0x0110, - 0x0804, 0x13a5, 0x72c8, 0x72ca, 0x78ac, 0xa084, 0x0003, 0x1508, - 0x2039, 0x0000, 0xd284, 0x0108, 0xc7fd, 0x2041, 0x0021, 0x2049, - 0x0004, 0x2051, 0x0008, 0x080c, 0x1b1d, 0x2091, 0x8000, 0x6808, - 0xc0d4, 0xa80d, 0x690a, 0x2091, 0x8001, 0x8738, 0xa784, 0x001f, - 0x1d90, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, - 0x1d50, 0x2091, 0x8000, 0x72c8, 0x2069, 0x0100, 0xd284, 0x1110, - 0x2069, 0x0200, 0x6808, 0xa084, 0xfffd, 0x680a, 0x6830, 0xd0b4, - 0x01b0, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, 0xd094, 0x0110, - 0x1f04, 0x1885, 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xd084, - 0x0110, 0x1f04, 0x188e, 0x20a9, 0x00fa, 0x1f04, 0x1895, 0x2079, - 0x4300, 0x2009, 0x0018, 0x72c8, 0xd284, 0x1118, 0x2061, 0x4340, - 0x0018, 0x2061, 0x4380, 0xc1fd, 0x792a, 0x6067, 0x0001, 0x6083, - 0x000f, 0x60a7, 0x0000, 0x60a8, 0x60b2, 0x60b6, 0x60d4, 0xd0b4, - 0x0160, 0xc0b4, 0x60d6, 0x00c6, 0x60b8, 0xa065, 0x6008, 0xc0d4, - 0x600a, 0x6018, 0x8001, 0x601a, 0x00ce, 0x60d4, 0xa084, 0x7eff, - 0x60d6, 0x78ac, 0xc08d, 0x78ae, 0x681b, 0x0054, 0x2091, 0x8001, - 0x0005, 0xd7fc, 0x1118, 0x2069, 0x4340, 0x0010, 0x2069, 0x4380, - 0x71c4, 0x71c6, 0x6916, 0x81ff, 0x1110, 0x68a7, 0x0001, 0x78ac, - 0xc08c, 0x78ae, 0xd084, 0x1110, 0x080c, 0x1c00, 0x0005, 0x75d8, - 0x74dc, 0x75da, 0x74de, 0x0018, 0x2029, 0x0000, 0x2520, 0x71c4, - 0x73c8, 0x72cc, 0x71c6, 0x73ca, 0x72ce, 0x2079, 0x4300, 0x7dde, - 0x7cda, 0x7bd6, 0x7ad2, 0x080c, 0x1afa, 0x0904, 0x19d7, 0x20a9, - 0x0005, 0x20a1, 0x4314, 0x2091, 0x8000, 0x41a1, 0x2091, 0x8001, - 0x2009, 0x0040, 0x080c, 0x1cbf, 0x0120, 0x080c, 0x1b02, 0x0804, - 0x19d7, 0x6004, 0xa08c, 0x00ff, 0xa18e, 0x0009, 0x1120, 0x0006, - 0x080c, 0x1fe3, 0x000e, 0xa084, 0xff00, 0x8007, 0x8009, 0x0904, - 0x1981, 0x00c6, 0x2c68, 0x080c, 0x1afa, 0x05a8, 0x2c00, 0x689e, - 0x8109, 0x1dc0, 0x609f, 0x0000, 0x00ce, 0x00c6, 0x7ddc, 0x7cd8, - 0x7bd4, 0x7ad0, 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000, - 0xa5a9, 0x0000, 0x7dde, 0x7cda, 0x7bd6, 0x7ad2, 0x2c68, 0x689c, - 0xa065, 0x0904, 0x1980, 0x2009, 0x0040, 0x080c, 0x1cbf, 0x1550, - 0x6004, 0xa084, 0x00ff, 0xa086, 0x0002, 0x1168, 0x6004, 0xa084, - 0x00ff, 0xa086, 0x000a, 0x1120, 0x0016, 0x080c, 0x1fe0, 0x001e, - 0x2d00, 0x6002, 0x0898, 0x00ce, 0x00c6, 0x609c, 0x080c, 0x1b76, - 0x00ce, 0x609f, 0x0000, 0x080c, 0x19db, 0x2009, 0x0018, 0x6008, - 0xc0cd, 0x600a, 0x6004, 0x6086, 0x080c, 0x1ab7, 0x080c, 0x1b02, - 0x0804, 0x19d7, 0x00ce, 0x00c6, 0x609c, 0x080c, 0x1b76, 0x00ce, - 0x609f, 0x0000, 0x080c, 0x19db, 0x2009, 0x0018, 0x6087, 0x0103, - 0x601b, 0x0003, 0x080c, 0x1ab7, 0x080c, 0x1b02, 0x0804, 0x19d7, - 0x00ce, 0x6114, 0xd1fc, 0x0120, 0x080c, 0x1aa9, 0x01b8, 0x0018, - 0x080c, 0x1a9b, 0x0198, 0x2029, 0x0000, 0x2520, 0x2009, 0x0018, - 0x73c8, 0x72cc, 0x6087, 0x0103, 0x601b, 0x0021, 0x080c, 0x1ab7, - 0x080c, 0x1b02, 0x2001, 0x4007, 0x0804, 0x13a5, 0x74c4, 0x73c8, - 0x72cc, 0x6014, 0x2091, 0x8000, 0x00e6, 0x2009, 0x0012, 0xd0fc, - 0x1118, 0x2071, 0x4340, 0x0018, 0x2071, 0x4380, 0xc1fd, 0x792a, - 0x7067, 0x0005, 0x71d4, 0xa18c, 0xfe7f, 0x71d6, 0x736a, 0x726e, - 0x7472, 0x7076, 0x707b, 0x0000, 0x2c00, 0x707e, 0xa02e, 0x2530, - 0x611c, 0xa184, 0x0060, 0x0110, 0x080c, 0x3de5, 0x00ee, 0x6596, + 0x13ac, 0x72c8, 0x0804, 0x13ab, 0x2011, 0x454d, 0x2204, 0x0006, + 0x8104, 0x1208, 0x8108, 0x2112, 0x2019, 0x0000, 0x080c, 0x2354, + 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x0118, 0x001e, 0x0804, 0x13b2, + 0x71c8, 0xa182, 0x0010, 0x0228, 0x0006, 0x2110, 0x71c4, 0x0804, + 0x13ab, 0x2011, 0x458d, 0x2204, 0x0006, 0x8104, 0x1208, 0x8108, + 0x2112, 0xc3fd, 0x080c, 0x2354, 0x002e, 0x001e, 0x0804, 0x13b1, + 0x71c4, 0x72c8, 0xa184, 0xfffd, 0x1904, 0x13ab, 0xa284, 0xfffd, + 0x1904, 0x13ab, 0x2100, 0x7920, 0x7822, 0x2200, 0x7a24, 0x7826, + 0x0804, 0x13b1, 0x2011, 0x4a40, 0x71c4, 0xd1fc, 0x1110, 0x2011, + 0x49c0, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa268, + 0x72c8, 0x73cc, 0x74d8, 0x71c6, 0x6800, 0x70ca, 0x73ce, 0x74da, + 0x2091, 0x8000, 0x6a02, 0xd2ac, 0x1118, 0x2021, 0x0000, 0x0090, + 0xa484, 0x00ff, 0xa082, 0x0002, 0x1a04, 0x173b, 0x843f, 0xa7bc, + 0x00ff, 0x0140, 0xa786, 0x0002, 0x1904, 0x173b, 0xa484, 0x00ff, + 0x0904, 0x173b, 0x2061, 0x0200, 0xd1fc, 0x0110, 0x2061, 0x0100, + 0x2029, 0x0009, 0x2031, 0x0062, 0x843f, 0xa7bc, 0x00ff, 0x0130, + 0x8307, 0xa084, 0x00ff, 0x1110, 0xa73d, 0x1138, 0x2041, 0x001d, + 0xa384, 0x00ff, 0xa082, 0x001a, 0x0210, 0xa4a4, 0x00ff, 0x8307, + 0xa084, 0x00ff, 0x0188, 0xa842, 0x02f0, 0xa086, 0x0010, 0x1120, + 0xa39c, 0x00ff, 0xa39d, 0x0f00, 0xa3bc, 0x00ff, 0x2500, 0xa702, + 0x0290, 0x2600, 0xa702, 0x1278, 0x2039, 0x003a, 0x6804, 0xa705, + 0x6806, 0x6b0a, 0x6b0c, 0x73ce, 0x681c, 0x70da, 0x6c1e, 0x2091, + 0x8001, 0x0804, 0x13b3, 0x2091, 0x8001, 0x0804, 0x13ad, 0x77c4, + 0x080c, 0x1b5f, 0x2091, 0x8000, 0x6a14, 0x6b1c, 0x2091, 0x8001, + 0x70c8, 0x6816, 0x70cc, 0x681e, 0x2708, 0x0804, 0x13b0, 0x70c4, + 0x2061, 0x4540, 0x6118, 0x601a, 0x2001, 0x01ff, 0x2004, 0xd0fc, + 0x1904, 0x13b2, 0x70c8, 0x2061, 0x4580, 0x6218, 0x601a, 0x0804, + 0x13b1, 0x71c4, 0x72c8, 0x73cc, 0xa182, 0x0010, 0x1a04, 0x13ac, + 0x080c, 0x2397, 0xa384, 0x4000, 0x0110, 0xa295, 0x0020, 0x0804, + 0x13b0, 0x77c4, 0x080c, 0x1b5f, 0x2091, 0x8000, 0x6a08, 0xc28d, + 0x6a0a, 0x2091, 0x8001, 0x2708, 0x0804, 0x13b1, 0x77c4, 0x080c, + 0x1b5f, 0x2091, 0x8000, 0x6a08, 0xa294, 0xfff9, 0x6a0a, 0x6804, + 0xa005, 0x0110, 0x080c, 0x2296, 0x2091, 0x8001, 0x2708, 0x0804, + 0x13b1, 0x77c4, 0x080c, 0x1b5f, 0x2091, 0x8000, 0x6a08, 0xc295, + 0x6a0a, 0x6804, 0xa005, 0x0110, 0x080c, 0x2296, 0x2091, 0x8001, + 0x2708, 0x0804, 0x13b1, 0x77c4, 0x2041, 0x0001, 0x2049, 0x0005, + 0x2051, 0x0020, 0x2091, 0x8000, 0x080c, 0x1b77, 0x2091, 0x8001, + 0x2708, 0x6a08, 0x0804, 0x13b1, 0x77c4, 0xd7fc, 0x0128, 0x080c, + 0x1aeb, 0x0138, 0x0804, 0x13b5, 0x080c, 0x1add, 0x0110, 0x0804, + 0x13b5, 0x73c8, 0x72cc, 0x77c6, 0x73ca, 0x72ce, 0x080c, 0x1bef, + 0x11e8, 0x6818, 0xa005, 0x01a0, 0x2708, 0x0076, 0x080c, 0x23b6, + 0x007e, 0x1170, 0x2001, 0x0015, 0xd7fc, 0x1118, 0x2061, 0x4540, + 0x0018, 0xc0fd, 0x2061, 0x4580, 0x782a, 0x2091, 0x8001, 0x0005, + 0x2091, 0x8001, 0x2001, 0x4005, 0x0804, 0x13b5, 0x2091, 0x8001, + 0x0804, 0x13b3, 0x77c4, 0xd7fc, 0x0128, 0x080c, 0x1aeb, 0x0138, + 0x0804, 0x13b5, 0x080c, 0x1add, 0x0110, 0x0804, 0x13b5, 0x77c6, + 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, + 0x080c, 0x1b77, 0x2009, 0x0016, 0xd7fc, 0x1118, 0x2061, 0x4540, + 0x0018, 0x2061, 0x4580, 0xc1fd, 0x6063, 0x0003, 0x607b, 0x0000, + 0x6772, 0x607f, 0x000f, 0x792a, 0x080c, 0x2296, 0x2091, 0x8001, + 0x0005, 0x77c8, 0x77ca, 0x77c4, 0x77c6, 0xd7fc, 0x0128, 0x080c, + 0x1aeb, 0x0138, 0x0804, 0x13b5, 0x080c, 0x1add, 0x0110, 0x0804, + 0x13b5, 0xa7bc, 0xff00, 0x2091, 0x8000, 0x2009, 0x0017, 0xd7fc, + 0x1118, 0x2061, 0x4540, 0x0018, 0x2061, 0x4580, 0xc1fd, 0x607b, + 0x0000, 0x6063, 0x0002, 0x6772, 0x607f, 0x000f, 0x792a, 0x080c, + 0x2296, 0x2091, 0x8001, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, + 0x0010, 0x2091, 0x8000, 0x70c8, 0xa005, 0x0118, 0x60d0, 0xc0fd, + 0x60d2, 0x080c, 0x1b77, 0x70c8, 0x6836, 0x8738, 0xa784, 0x001f, + 0x1dc0, 0x2091, 0x8001, 0x0005, 0x2019, 0x0000, 0x72c8, 0xd284, + 0x0128, 0x080c, 0x1aeb, 0x0138, 0x0804, 0x13b5, 0x080c, 0x1add, + 0x0110, 0x0804, 0x13b5, 0x72c8, 0x72ca, 0x78ac, 0xa084, 0x0003, + 0x1508, 0x2039, 0x0000, 0xd284, 0x0108, 0xc7fd, 0x2041, 0x0021, + 0x2049, 0x0004, 0x2051, 0x0008, 0x080c, 0x1b5f, 0x2091, 0x8000, + 0x6808, 0xc0d4, 0xa80d, 0x690a, 0x2091, 0x8001, 0x8738, 0xa784, + 0x001f, 0x1d90, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, + 0x0f00, 0x1d50, 0x2091, 0x8000, 0x72c8, 0x2069, 0x0100, 0xd284, + 0x1110, 0x2069, 0x0200, 0x6808, 0xa084, 0xfffd, 0x680a, 0x6830, + 0xd0b4, 0x01b0, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, 0xd094, + 0x0110, 0x1f04, 0x18a6, 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, + 0xd084, 0x0110, 0x1f04, 0x18af, 0x20a9, 0x00fa, 0x1f04, 0x18b6, + 0x2079, 0x4500, 0x2009, 0x0018, 0x72c8, 0xd284, 0x1118, 0x2061, + 0x4540, 0x0018, 0x2061, 0x4580, 0xc1fd, 0x607b, 0x0000, 0x792a, + 0x6063, 0x0001, 0x607f, 0x000f, 0x60a3, 0x0000, 0x60a4, 0x60ae, + 0x60b2, 0x60d0, 0xd0b4, 0x0160, 0xc0b4, 0x60d2, 0x00c6, 0x60b4, + 0xa065, 0x6008, 0xc0d4, 0x600a, 0x6018, 0x8001, 0x601a, 0x00ce, + 0x60d0, 0xa084, 0x7eff, 0x60d2, 0x78ac, 0xc08d, 0x78ae, 0x83ff, + 0x0108, 0x0005, 0x681b, 0x0054, 0x2091, 0x8001, 0x0005, 0x73cc, + 0x080c, 0x185e, 0x69ec, 0x6a48, 0xa185, 0x1800, 0x684a, 0xa185, + 0x0040, 0x68ee, 0x73cc, 0x2021, 0x0004, 0x20a9, 0x09ff, 0x1f04, + 0x18ff, 0x8421, 0x1dd0, 0x8319, 0x1db0, 0x69ee, 0x6a4a, 0x2091, + 0x8001, 0x0005, 0xd7fc, 0x1118, 0x2069, 0x4540, 0x0010, 0x2069, + 0x4580, 0x71c4, 0x71c6, 0x6916, 0x81ff, 0x1110, 0x68a3, 0x0001, + 0x78ac, 0xc08c, 0x78ae, 0xd084, 0x1110, 0x080c, 0x1c42, 0x0005, + 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0018, 0x2029, 0x0000, 0x2520, + 0x71c4, 0x73c8, 0x72cc, 0x71c6, 0x73ca, 0x72ce, 0x2079, 0x4500, + 0x7dde, 0x7cda, 0x7bd6, 0x7ad2, 0x080c, 0x1b3c, 0x0904, 0x1a17, + 0x20a9, 0x0005, 0x20a1, 0x4514, 0x2091, 0x8000, 0x41a1, 0x2091, + 0x8001, 0x2009, 0x0040, 0x080c, 0x1d0b, 0x0120, 0x080c, 0x1b44, + 0x0804, 0x1a17, 0x6004, 0xa08c, 0x00ff, 0xa18e, 0x0009, 0x1120, + 0x0006, 0x080c, 0x2046, 0x000e, 0xa084, 0xff00, 0x8007, 0x8009, + 0x0904, 0x19c2, 0x00c6, 0x2c68, 0x080c, 0x1b3c, 0x05a8, 0x2c00, + 0x689e, 0x8109, 0x1dc0, 0x609f, 0x0000, 0x00ce, 0x00c6, 0x7ddc, + 0x7cd8, 0x7bd4, 0x7ad0, 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1, + 0x0000, 0xa5a9, 0x0000, 0x7dde, 0x7cda, 0x7bd6, 0x7ad2, 0x2c68, + 0x689c, 0xa065, 0x0904, 0x19c1, 0x2009, 0x0040, 0x080c, 0x1d0b, + 0x1550, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0002, 0x1168, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x000a, 0x1120, 0x0016, 0x080c, 0x2043, + 0x001e, 0x2d00, 0x6002, 0x0898, 0x00ce, 0x00c6, 0x609c, 0x080c, + 0x1bb8, 0x00ce, 0x609f, 0x0000, 0x080c, 0x1a1b, 0x2009, 0x0018, + 0x6008, 0xc0cd, 0x600a, 0x6004, 0x6086, 0x080c, 0x1af9, 0x080c, + 0x1b44, 0x0804, 0x1a17, 0x00ce, 0x00c6, 0x609c, 0x080c, 0x1bb8, + 0x00ce, 0x609f, 0x0000, 0x080c, 0x1a1b, 0x2009, 0x0018, 0x6087, + 0x0103, 0x601b, 0x0003, 0x080c, 0x1af9, 0x080c, 0x1b44, 0x0804, + 0x1a17, 0x00ce, 0x6114, 0xd1fc, 0x0120, 0x080c, 0x1aeb, 0x01b8, + 0x0018, 0x080c, 0x1add, 0x0198, 0x2029, 0x0000, 0x2520, 0x2009, + 0x0018, 0x73c8, 0x72cc, 0x6087, 0x0103, 0x601b, 0x0021, 0x080c, + 0x1af9, 0x080c, 0x1b44, 0x2001, 0x4007, 0x0804, 0x13b5, 0x74c4, + 0x73c8, 0x72cc, 0x6014, 0x2091, 0x8000, 0x00e6, 0x2009, 0x0012, + 0xd0fc, 0x1118, 0x2071, 0x4540, 0x0018, 0x2071, 0x4580, 0xc1fd, + 0x792a, 0x7063, 0x0005, 0x71d0, 0xc1c4, 0x71d2, 0x7366, 0x726a, + 0x746e, 0x7072, 0x7077, 0x0000, 0x2c00, 0x707a, 0xa02e, 0x2530, + 0x611c, 0xa184, 0x0060, 0x0110, 0x080c, 0x3f66, 0x00ee, 0x6596, 0x65a6, 0x669a, 0x66aa, 0x60af, 0x0000, 0x60b3, 0x0000, 0x6714, - 0x6023, 0x0000, 0x080c, 0x2233, 0x2091, 0x8001, 0x0005, 0x70c3, - 0x4005, 0x0804, 0x13a6, 0x20a9, 0x0005, 0x2099, 0x4314, 0x2091, + 0x6023, 0x0000, 0x080c, 0x2296, 0x2091, 0x8001, 0x0005, 0x70c3, + 0x4005, 0x0804, 0x13b6, 0x20a9, 0x0005, 0x2099, 0x4514, 0x2091, 0x8000, 0x530a, 0x2091, 0x8001, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x0005, 0x71c4, 0x70c7, 0x0000, - 0x791e, 0x0804, 0x13a3, 0x71c4, 0x71c6, 0x2168, 0x0010, 0x2069, + 0x791e, 0x0804, 0x13b3, 0x71c4, 0x71c6, 0x2168, 0x0010, 0x2069, 0x1000, 0x690c, 0xa016, 0x2d04, 0xa210, 0x8d68, 0x8109, 0x1dd8, 0xa285, 0x0000, 0x1118, 0x70c3, 0x4000, 0x0010, 0x70c3, 0x4003, - 0x70ca, 0x0804, 0x13a6, 0x7964, 0x71c6, 0x71c4, 0xa182, 0x0003, - 0x1a04, 0x139c, 0x7966, 0x0804, 0x13a3, 0x7964, 0x71c6, 0x0804, - 0x13a3, 0x7900, 0x71c6, 0x71c4, 0x7902, 0x0804, 0x13a3, 0x7900, - 0x71c6, 0x0804, 0x13a3, 0x70c4, 0x2011, 0x0000, 0xa08c, 0x000d, + 0x70ca, 0x0804, 0x13b6, 0x7964, 0x71c6, 0x71c4, 0xa182, 0x0003, + 0x1a04, 0x13ac, 0x7966, 0x0804, 0x13b3, 0x7964, 0x71c6, 0x0804, + 0x13b3, 0x7900, 0x71c6, 0x71c4, 0x7902, 0x0804, 0x13b3, 0x7900, + 0x71c6, 0x0804, 0x13b3, 0x70c4, 0x2011, 0x0000, 0xa08c, 0x000d, 0x0160, 0x810c, 0x0230, 0x8210, 0x810c, 0x810c, 0x0210, 0x8210, - 0x810c, 0x81ff, 0x1904, 0x139d, 0x8210, 0x7a0e, 0xd28c, 0x0538, + 0x810c, 0x81ff, 0x1904, 0x13ad, 0x8210, 0x7a0e, 0xd28c, 0x0538, 0x7910, 0xc1cd, 0x7912, 0x2009, 0x0021, 0x2019, 0x0003, 0xd284, - 0x01c0, 0x8108, 0x2019, 0x0041, 0x2011, 0x8b4e, 0x2312, 0x2019, + 0x01c0, 0x8108, 0x2019, 0x0041, 0x2011, 0x8d4e, 0x2312, 0x2019, 0x0042, 0x8210, 0x2312, 0x2019, 0x0043, 0x8210, 0x2312, 0x2019, 0x0046, 0x8210, 0x2312, 0x2019, 0x0047, 0x8210, 0x2312, 0x2019, - 0x0006, 0x2011, 0x8b53, 0x2112, 0x2011, 0x8b73, 0x2312, 0x7904, - 0x7806, 0x0804, 0x13a2, 0x7804, 0x70c6, 0x0804, 0x13a3, 0x71c4, - 0xd1fc, 0x1118, 0x2011, 0x47c0, 0x0010, 0x2011, 0x4840, 0x8107, + 0x0006, 0x2011, 0x8d53, 0x2112, 0x2011, 0x8d73, 0x2312, 0x7904, + 0x7806, 0x0804, 0x13b2, 0x7804, 0x70c6, 0x0804, 0x13b3, 0x71c4, + 0xd1fc, 0x1118, 0x2011, 0x49c0, 0x0010, 0x2011, 0x4a40, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa268, 0x2011, 0x0000, 0x6814, 0xd0fc, 0x0110, 0xa295, 0x0200, 0xd0b4, 0x0110, 0xa295, - 0x0001, 0x6b0c, 0x0804, 0x13a0, 0x0016, 0x7814, 0xd0f4, 0x0138, - 0x2001, 0x4007, 0x70db, 0x0000, 0xa18d, 0x0001, 0x0050, 0xd0fc, - 0x0138, 0x2001, 0x4007, 0x70db, 0x0001, 0xa18d, 0x0001, 0x0008, - 0xa006, 0x001e, 0x0005, 0x0016, 0x7814, 0xd0f4, 0x0138, 0x2001, - 0x4007, 0x70db, 0x0000, 0xa18d, 0x0001, 0x0008, 0xa006, 0x001e, - 0x0005, 0x0016, 0x7814, 0xd0fc, 0x0138, 0x2001, 0x4007, 0x70db, - 0x0001, 0xa18d, 0x0001, 0x0008, 0xa006, 0x001e, 0x0005, 0x7112, - 0x721a, 0x731e, 0x7810, 0xd0c4, 0x0110, 0x7422, 0x7526, 0xac80, - 0x0001, 0x8108, 0x810c, 0x81a9, 0x8098, 0x20a1, 0x0030, 0x7003, - 0x0000, 0x6084, 0x20a2, 0x53a6, 0x7007, 0x0001, 0x7974, 0xa184, - 0xff00, 0x0140, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, - 0xa100, 0x0018, 0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, - 0xa006, 0xa211, 0x7d10, 0xd5c4, 0x0120, 0x7b84, 0xa319, 0x7c80, - 0xa421, 0x7008, 0xd0fc, 0x0de8, 0x7003, 0x0001, 0x7007, 0x0006, - 0x711a, 0x721e, 0x7d10, 0xd5c4, 0x0110, 0x7322, 0x7426, 0xa084, - 0x01e0, 0x0005, 0x7848, 0xa065, 0x0120, 0x2c04, 0x784a, 0x2063, - 0x0000, 0x0005, 0x00f6, 0x2079, 0x4300, 0x7848, 0x2062, 0x2c00, - 0xa005, 0x1110, 0x080c, 0x243b, 0x784a, 0x00fe, 0x0005, 0x2011, - 0x8d00, 0x7a4a, 0x7bc4, 0x8319, 0x0128, 0xa280, 0x0032, 0x2012, - 0x2010, 0x0cc8, 0x2013, 0x0000, 0x0005, 0x0016, 0x0026, 0xd7fc, - 0x1118, 0x2011, 0x48c0, 0x0010, 0x2011, 0x68c0, 0xa784, 0x0f00, - 0x800b, 0xa784, 0x001f, 0x0120, 0x8003, 0x8003, 0x8003, 0x8003, - 0xa105, 0xa268, 0x002e, 0x001e, 0x0005, 0x0c39, 0x2900, 0x682a, - 0x2a00, 0x682e, 0x6808, 0xa084, 0xf9ef, 0xa80d, 0x690a, 0x00e6, - 0xd7fc, 0x1128, 0x2009, 0x4353, 0x2071, 0x4340, 0x0020, 0x2009, - 0x4393, 0x2071, 0x4380, 0x210c, 0x6804, 0xa005, 0x0148, 0xa116, - 0x1138, 0x2060, 0x6000, 0x6806, 0x0016, 0x200b, 0x0000, 0x0018, - 0x2009, 0x0000, 0x0016, 0x6804, 0xa065, 0x0178, 0x6000, 0x6806, - 0x0421, 0x080c, 0x1d30, 0x6810, 0x7908, 0x8109, 0x790a, 0x8001, - 0x6812, 0x1d88, 0x7910, 0xc1a5, 0x7912, 0x001e, 0x6902, 0x6906, - 0x2d00, 0x2060, 0x080c, 0x2580, 0x00ee, 0x0005, 0xa065, 0x0160, - 0x2008, 0x609c, 0xa005, 0x0128, 0x2062, 0x609f, 0x0000, 0xa065, - 0x0cc0, 0x7848, 0x794a, 0x2062, 0x0005, 0x6007, 0x0103, 0x608f, - 0x0000, 0x20a9, 0x001c, 0xac80, 0x0005, 0x20a0, 0x2001, 0x0000, - 0x40a4, 0x6828, 0x601a, 0x682c, 0x6022, 0x0005, 0x00e6, 0xd7fc, - 0x1128, 0x2071, 0x4340, 0x2031, 0x43c0, 0x0020, 0x2071, 0x4380, - 0x2031, 0x45c0, 0x7050, 0xa08c, 0x0200, 0x1128, 0xa608, 0x2d0a, - 0x8000, 0x7052, 0xa006, 0x00ee, 0x0005, 0x00f6, 0xd7fc, 0x1118, - 0x2079, 0x4340, 0x0010, 0x2079, 0x4380, 0x080c, 0x1b1d, 0x2091, - 0x8000, 0x6804, 0x780a, 0xa065, 0x0904, 0x1bfe, 0x0030, 0x2c00, - 0x780a, 0x2060, 0x6000, 0xa065, 0x05c8, 0x6010, 0xa306, 0x1db8, - 0x600c, 0xa206, 0x1da0, 0x2c28, 0x784c, 0xac06, 0x1108, 0x0458, - 0x6804, 0xac06, 0x1140, 0x6000, 0x2060, 0x6806, 0xa005, 0x1118, - 0x6803, 0x0000, 0x0048, 0x6400, 0x7808, 0x2060, 0x6402, 0xa486, - 0x0000, 0x1110, 0x2c00, 0x6802, 0x2560, 0x00fe, 0x080c, 0x1b85, - 0x00f6, 0x601b, 0x0005, 0x6023, 0x0020, 0x00fe, 0x080c, 0x1d30, - 0x00f6, 0x7908, 0x8109, 0x790a, 0x6810, 0x8001, 0x6812, 0x1118, - 0x7810, 0xc0a5, 0x7812, 0x2001, 0xffff, 0xa005, 0x00fe, 0x0005, - 0x0076, 0x2700, 0x2039, 0x0000, 0xd0fc, 0x0108, 0xc7fd, 0x2041, - 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x2091, 0x8000, 0x080c, - 0x1b35, 0x8738, 0xa784, 0x001f, 0x1dd0, 0xa7bc, 0xff00, 0x873f, - 0x8738, 0x873f, 0xa784, 0x0f00, 0x1d90, 0x2091, 0x8001, 0x007e, - 0x0005, 0x786c, 0x2009, 0x8b74, 0x210c, 0xa10d, 0x0118, 0xa065, - 0x0804, 0x1ffe, 0x2061, 0x0000, 0x6018, 0xd084, 0x11b8, 0x7810, - 0xd08c, 0x0130, 0xc08c, 0x7812, 0xc7fc, 0x2069, 0x4340, 0x0028, - 0xc08d, 0x7812, 0x2069, 0x4380, 0xc7fd, 0x2091, 0x8000, 0x681c, - 0x681f, 0x0000, 0x2091, 0x8001, 0xa005, 0x1108, 0x0005, 0xa08c, - 0xfff0, 0x0110, 0x080c, 0x243b, 0x0002, 0x1c5d, 0x1c60, 0x1c66, - 0x1c6a, 0x1c5e, 0x1c6e, 0x1c5e, 0x1c5e, 0x1c5e, 0x1c73, 0x1c9f, - 0x1ca2, 0x1ca7, 0x1c5e, 0x1c5e, 0x1c5e, 0x0005, 0x080c, 0x243b, - 0x080c, 0x1c00, 0x2001, 0x8001, 0x0804, 0x1cb0, 0x2001, 0x8003, - 0x0804, 0x1cb0, 0x2001, 0x8004, 0x0804, 0x1cb0, 0x080c, 0x1c00, - 0x2001, 0x8006, 0x04e8, 0x2091, 0x8000, 0x0076, 0xd7fc, 0x1128, - 0x2069, 0x4340, 0x2039, 0x0009, 0x0020, 0x2069, 0x4380, 0x2039, - 0x0009, 0x6800, 0xa086, 0x0000, 0x0128, 0x000e, 0x6f1e, 0x2091, - 0x8001, 0x0005, 0x6874, 0x007e, 0xa0bc, 0xff00, 0x2041, 0x0021, - 0x2049, 0x0004, 0x2051, 0x0010, 0x080c, 0x1b35, 0x8738, 0xa784, - 0x001f, 0x1dd0, 0x2091, 0x8001, 0x2001, 0x800a, 0x0088, 0x2001, - 0x800c, 0x0070, 0x080c, 0x1c00, 0x2001, 0x800d, 0x0048, 0xd7fc, - 0x0110, 0x78ec, 0x0008, 0x78e4, 0x70c6, 0x2001, 0x800e, 0x0000, - 0x70c2, 0xd7fc, 0x1118, 0x70db, 0x0000, 0x0010, 0x70db, 0x0001, - 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x4080, 0x0005, 0xac80, - 0x0001, 0x81ff, 0x0518, 0x2099, 0x0030, 0x20a0, 0x700c, 0xa084, - 0x07ff, 0x0100, 0x7018, 0x0006, 0x701c, 0x0006, 0x7020, 0x0006, - 0x7024, 0x0006, 0x7112, 0x81ac, 0x721a, 0x731e, 0x7422, 0x7526, - 0x7003, 0x0001, 0x7007, 0x0001, 0x7008, 0x800b, 0x1ee8, 0x7007, - 0x0002, 0xa08c, 0x01e0, 0x1110, 0x53a5, 0xa006, 0x7003, 0x0000, - 0x7007, 0x0004, 0x000e, 0x7026, 0x000e, 0x7022, 0x000e, 0x701e, - 0x000e, 0x701a, 0x0005, 0x2011, 0x0020, 0x2009, 0x0010, 0x6b0a, - 0x6c0e, 0x681f, 0x0201, 0x6803, 0xfd20, 0x6807, 0x0038, 0x6a1a, - 0x2d00, 0xa0e8, 0x0008, 0xa290, 0x0004, 0x8109, 0x1d80, 0x0005, - 0x70ec, 0xd0dc, 0x1520, 0x2029, 0x0001, 0x7814, 0xd0cc, 0x1160, - 0x70ec, 0xd0e4, 0x2019, 0x0c0a, 0x2021, 0x000a, 0x1120, 0x2019, - 0x0c0c, 0x2021, 0x000c, 0x0070, 0x70ec, 0xd0e4, 0x1128, 0x2019, - 0x1c0c, 0x2021, 0x000c, 0x0030, 0x2019, 0x1c09, 0x2021, 0x0009, - 0xa5ad, 0x0200, 0x6b0a, 0x6c0e, 0x6d1e, 0x6807, 0x0038, 0x0005, - 0x6004, 0x6086, 0x2c08, 0x2063, 0x0000, 0x7868, 0xa005, 0x796a, - 0x0110, 0x2c02, 0x0008, 0x796e, 0x0005, 0x00c6, 0x2061, 0x4300, - 0x6887, 0x0103, 0x2d08, 0x206b, 0x0000, 0x6068, 0xa005, 0x616a, - 0x0110, 0x2d02, 0x0008, 0x616e, 0x00ce, 0x0005, 0x2091, 0x8000, - 0x2c04, 0x786e, 0xa005, 0x1108, 0x786a, 0x2091, 0x8001, 0x609c, - 0xa005, 0x0188, 0x00c6, 0x2060, 0x2008, 0x609c, 0xa005, 0x0138, - 0x2062, 0x609f, 0x0000, 0xa065, 0x609c, 0xa005, 0x1dc8, 0x7848, - 0x794a, 0x2062, 0x00ce, 0x7848, 0x2062, 0x609f, 0x0000, 0xac85, - 0x0000, 0x1110, 0x080c, 0x243b, 0x784a, 0x0005, 0x20a9, 0x0010, - 0xa006, 0x8004, 0x8086, 0x818e, 0x1208, 0xa200, 0x1f04, 0x1d7a, - 0x8086, 0x818e, 0x0005, 0x0156, 0x20a9, 0x0010, 0xa005, 0x01b8, - 0xa11a, 0x12a8, 0x8213, 0x818d, 0x0228, 0xa11a, 0x1220, 0x1f04, - 0x1d8a, 0x0028, 0xa11a, 0x2308, 0x8210, 0x1f04, 0x1d8a, 0x0006, - 0x3200, 0xa084, 0xefff, 0x2080, 0x000e, 0x015e, 0x0005, 0x0006, - 0x3200, 0xa085, 0x1000, 0x0cb8, 0x7d74, 0x70d0, 0xa506, 0x0904, - 0x1e5b, 0x7810, 0x2050, 0x7800, 0xd08c, 0x0100, 0x080c, 0x1afa, - 0x0904, 0x1e5b, 0xa046, 0x7970, 0x2500, 0x8000, 0xa112, 0x2009, - 0x0040, 0x1208, 0x0030, 0x72d0, 0xa206, 0x0118, 0x8840, 0x2009, - 0x0080, 0x00c6, 0x7112, 0x7007, 0x0001, 0x2099, 0x0030, 0x20a9, - 0x0020, 0xac80, 0x0001, 0x20a0, 0x2061, 0x0000, 0x88ff, 0x0110, - 0x080c, 0x1afa, 0x7008, 0xd0fc, 0x0de8, 0x7007, 0x0002, 0x2091, - 0x8001, 0xa08c, 0x01e0, 0x1538, 0x53a5, 0x8cff, 0x1120, 0x88ff, - 0x0904, 0x1e48, 0x0050, 0x2c00, 0x788e, 0x20a9, 0x0020, 0xac80, - 0x0001, 0x20a0, 0x53a5, 0x0804, 0x1e48, 0xa046, 0x7218, 0x731c, - 0xdac4, 0x0110, 0x7420, 0x7524, 0xa292, 0x0040, 0xa39b, 0x0000, - 0xa4a3, 0x0000, 0xa5ab, 0x0000, 0x721a, 0x731e, 0xdac4, 0x0118, - 0x7422, 0x7526, 0xa006, 0x7007, 0x0004, 0x0904, 0x1e48, 0x8cff, - 0x0110, 0x080c, 0x1b02, 0x00ce, 0x080c, 0x1b02, 0xa046, 0x7888, - 0x8000, 0x788a, 0xa086, 0x0002, 0x01c0, 0x7a7c, 0x7b78, 0xdac4, - 0x0110, 0x7c84, 0x7d80, 0x7974, 0x8107, 0x8004, 0x8004, 0xa210, - 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x721a, 0x731e, - 0xdac4, 0x0588, 0x7422, 0x7526, 0x0470, 0x6014, 0xd0fc, 0x1118, - 0x2069, 0x4340, 0x0010, 0x2069, 0x4380, 0x2091, 0x8000, 0x681f, - 0x0002, 0x88ff, 0x0120, 0xa046, 0x788c, 0x2060, 0x0c70, 0x788b, - 0x0000, 0x78ac, 0xa085, 0x0003, 0x78ae, 0x2091, 0x8001, 0x0098, - 0x00ce, 0x788b, 0x0000, 0x080c, 0x1fb9, 0x6004, 0xa084, 0x000f, - 0x0059, 0x88ff, 0x0130, 0x788c, 0x2060, 0x6004, 0xa084, 0x000f, - 0x0019, 0x0804, 0x1da4, 0x0005, 0x0002, 0x1e6d, 0x1e88, 0x1ea1, - 0x1e6d, 0x1eae, 0x1e7e, 0x1e6d, 0x1e6d, 0x1e6d, 0x1e86, 0x1e9f, - 0x1e6d, 0x1e6d, 0x1e6d, 0x1e6d, 0x1e6d, 0x2039, 0x0400, 0x78bc, - 0xa705, 0x78be, 0x6008, 0xa705, 0x600a, 0x080c, 0x1eea, 0x609c, - 0x78ba, 0x609f, 0x0000, 0x080c, 0x1fa5, 0x0005, 0x78bc, 0xd0c4, - 0x0108, 0x0c58, 0x601c, 0xc0bd, 0x601e, 0x0030, 0x080c, 0x1fe3, - 0x78bc, 0xd0c4, 0x0108, 0x0c08, 0x78bf, 0x0000, 0x6004, 0x8007, - 0xa084, 0x00ff, 0x78b2, 0x8001, 0x0138, 0x080c, 0x1eea, 0x0120, - 0x78bc, 0xc0c5, 0x78be, 0x0010, 0x0804, 0x1f05, 0x0005, 0x080c, - 0x1fe0, 0x78bc, 0xa08c, 0x0e00, 0x1110, 0xd0c4, 0x1108, 0x0828, - 0x080c, 0x1eea, 0x1110, 0x0804, 0x1f05, 0x0005, 0x78bc, 0xd0c4, - 0x0110, 0x0804, 0x1e6d, 0x78bf, 0x0000, 0x6714, 0x2011, 0x0001, - 0x22a8, 0x6018, 0xa084, 0x00ff, 0xa005, 0x0188, 0xa7bc, 0xff00, - 0x20a9, 0x0020, 0xa08e, 0x0001, 0x0150, 0xa7bc, 0x8000, 0x2011, - 0x0002, 0x20a9, 0x0100, 0xa08e, 0x0002, 0x0108, 0x00c0, 0x080c, - 0x1b1d, 0x2d00, 0x2091, 0x8000, 0x682b, 0x0000, 0x682f, 0x0000, - 0x6808, 0xa084, 0xffde, 0x680a, 0xade8, 0x0010, 0x2091, 0x8001, - 0x1f04, 0x1ed2, 0x8211, 0x0118, 0x20a9, 0x0100, 0x0c58, 0x080c, - 0x1b02, 0x0005, 0x609f, 0x0000, 0x78b4, 0xa06d, 0x2c00, 0x78b6, - 0x1110, 0x78ba, 0x0038, 0x689e, 0x2d00, 0x6002, 0x78b8, 0xad06, - 0x1108, 0x6002, 0x78b0, 0x8001, 0x78b2, 0x1130, 0x78bc, 0xc0c4, - 0x78be, 0x78b8, 0x2060, 0xa006, 0x0005, 0x00e6, 0xa02e, 0x2530, - 0x7dba, 0x7db6, 0x65ae, 0x65b2, 0x601c, 0x60a2, 0x2048, 0xa984, - 0xe1ff, 0x601e, 0xa984, 0x0060, 0x0110, 0x080c, 0x3de5, 0x6596, - 0x65a6, 0x669a, 0x66aa, 0x6714, 0x2071, 0x4380, 0xd7fc, 0x1110, - 0x2071, 0x4340, 0xa784, 0x0f00, 0x800b, 0xa784, 0x001f, 0x0120, - 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0x71c4, 0xa168, 0x2700, - 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0x71c8, 0xa100, - 0x60c2, 0x2091, 0x8000, 0x6e08, 0xd684, 0x0170, 0xd9fc, 0x1160, - 0x2091, 0x8001, 0x080c, 0x1b85, 0x2091, 0x8000, 0x080c, 0x1d30, - 0x2091, 0x8001, 0x0804, 0x1fa3, 0x6024, 0xa096, 0x0001, 0x1110, - 0x8000, 0x6026, 0x6a10, 0x6814, 0xa202, 0x0268, 0x0160, 0x2091, - 0x8001, 0x2039, 0x0200, 0x609c, 0x78ba, 0x609f, 0x0000, 0x080c, - 0x1fa5, 0x0804, 0x1fa3, 0x2c08, 0xd9fc, 0x01f0, 0x6800, 0xa065, - 0x01d8, 0x6a04, 0x7000, 0xa084, 0x0002, 0x0168, 0x704c, 0xa206, - 0x1150, 0x6b04, 0x2160, 0x2304, 0x6002, 0xa005, 0x1108, 0x6902, - 0x2260, 0x6102, 0x0098, 0x2d00, 0x2060, 0x080c, 0x2580, 0x6e08, - 0x2160, 0x6202, 0x6906, 0x0050, 0x6800, 0x6902, 0xa065, 0x0110, - 0x6102, 0x0008, 0x6906, 0x2160, 0x6003, 0x0000, 0x2160, 0xd9fc, - 0x0118, 0xa6b4, 0xfffc, 0x6e0a, 0x6810, 0x7d08, 0x8528, 0x7d0a, - 0x8000, 0x6812, 0x2091, 0x8001, 0xd6b4, 0x0128, 0xa6b6, 0x0040, - 0x6e0a, 0x080c, 0x1b96, 0x00ee, 0x0005, 0x6008, 0xa705, 0x600a, - 0x2091, 0x8000, 0x080c, 0x1d30, 0x2091, 0x8001, 0x78b8, 0xa065, - 0x0128, 0x609c, 0x78ba, 0x609f, 0x0000, 0x0c78, 0x78b6, 0x78ba, - 0x0005, 0x7970, 0x7874, 0x2818, 0xd384, 0x0118, 0x8000, 0xa112, - 0x0220, 0x8000, 0xa112, 0x1278, 0xc384, 0x7a7c, 0x721a, 0x7a78, - 0x721e, 0xdac4, 0x0120, 0x7a84, 0x7222, 0x7a80, 0x7226, 0xa006, - 0xd384, 0x0108, 0x8000, 0x7876, 0x70d2, 0x781c, 0xa005, 0x0138, - 0x8001, 0x781e, 0x1120, 0x0e04, 0x1fdf, 0x2091, 0x4080, 0x0005, - 0x2039, 0x1ff5, 0x0010, 0x2039, 0x1ffb, 0x2704, 0xa005, 0x0160, - 0xac00, 0x2068, 0x6908, 0x6810, 0x6912, 0x680a, 0x690c, 0x6814, - 0x6916, 0x680e, 0x8738, 0x0c88, 0x0005, 0x0003, 0x0009, 0x000f, - 0x0015, 0x001b, 0x0000, 0x0015, 0x001b, 0x0000, 0x2041, 0x0000, - 0x780c, 0x0002, 0x21a7, 0x2182, 0x2006, 0x2076, 0x2039, 0x8b74, - 0x2734, 0x7d10, 0x00c0, 0x6084, 0xa086, 0x0103, 0x1904, 0x2060, - 0x6114, 0x6018, 0xa105, 0x0120, 0x86ff, 0x11d8, 0x0804, 0x2060, - 0x8603, 0xa080, 0x8b55, 0x620c, 0x2202, 0x8000, 0x6210, 0x2202, - 0x080c, 0x1d4e, 0x8630, 0xa68e, 0x000f, 0x0904, 0x20e1, 0x786c, - 0xa065, 0x1d08, 0x7808, 0xa602, 0x1220, 0xd5ac, 0x1110, 0x263a, - 0x0005, 0xa682, 0x0003, 0x1a04, 0x20e1, 0x2091, 0x8000, 0x2069, - 0x0000, 0x6818, 0xd084, 0x11f8, 0x2011, 0x8b55, 0x2204, 0x70c6, - 0x8210, 0x2204, 0x70ca, 0xd684, 0x1130, 0x8210, 0x2204, 0x70da, - 0x8210, 0x2204, 0x70de, 0xa685, 0x8020, 0x70c2, 0x681b, 0x0001, - 0x2091, 0x4080, 0x7810, 0xa084, 0xffcf, 0x7812, 0x2091, 0x8001, - 0x203b, 0x0000, 0x0005, 0x7810, 0xc0ad, 0x7812, 0x0804, 0x20e1, - 0x263a, 0x080c, 0x21ad, 0x1904, 0x21c9, 0x786c, 0xa065, 0x1904, - 0x200b, 0x2091, 0x8000, 0x7810, 0xa084, 0xffcf, 0x86ff, 0x0108, - 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0804, 0x21c9, 0x2039, 0x8b74, - 0x2734, 0x7d10, 0x00a0, 0x6084, 0xa086, 0x0103, 0x1904, 0x20cb, - 0x6114, 0x6018, 0xa105, 0x0120, 0x86ff, 0x11b8, 0x0804, 0x20cb, - 0xa680, 0x8b55, 0x620c, 0x2202, 0x080c, 0x1d4e, 0x8630, 0xa68e, - 0x001e, 0x0904, 0x20e1, 0x786c, 0xa065, 0x1d28, 0x7808, 0xa602, - 0x1220, 0xd5ac, 0x1110, 0x263a, 0x0005, 0xa682, 0x0006, 0x1a04, - 0x20e1, 0x2091, 0x8000, 0x2069, 0x0000, 0x6818, 0xd084, 0x11f8, - 0x2011, 0x8b55, 0x2009, 0x8b4e, 0x26a8, 0x211c, 0x2204, 0x201a, - 0x8108, 0x8210, 0x1f04, 0x20ad, 0xa685, 0x8030, 0x70c2, 0x681b, - 0x0001, 0x2091, 0x4080, 0x7810, 0xa084, 0xffcf, 0x7812, 0x2091, - 0x8001, 0xa006, 0x2009, 0x8b75, 0x200a, 0x203a, 0x0005, 0x7810, - 0xc0ad, 0x7812, 0x00b0, 0x263a, 0x080c, 0x21ad, 0x1904, 0x21c9, - 0x786c, 0xa065, 0x1904, 0x207b, 0x2091, 0x8000, 0x7810, 0xa084, - 0xffcf, 0x86ff, 0x0108, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0804, - 0x21c9, 0x2091, 0x8000, 0x7007, 0x0004, 0x7994, 0x70d4, 0xa102, - 0x0228, 0x0168, 0x7b90, 0xa302, 0x1150, 0x0010, 0x8002, 0x1138, - 0x263a, 0x7810, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0005, 0xa184, - 0xff00, 0x0140, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, - 0xa100, 0x0018, 0x8107, 0x8004, 0x8004, 0x7a9c, 0xa210, 0x721a, - 0x7a98, 0xa006, 0xa211, 0x721e, 0xd4c4, 0x0130, 0x7aa4, 0xa211, - 0x7222, 0x7aa0, 0xa211, 0x7226, 0x20a1, 0x0030, 0x7003, 0x0000, - 0x2009, 0x8b54, 0x260a, 0x8109, 0x2198, 0x2104, 0xd084, 0x0108, - 0x8633, 0xa6b0, 0x0002, 0x26a8, 0x53a6, 0x8603, 0x7012, 0x7007, - 0x0001, 0x7990, 0x7894, 0x8000, 0xa10a, 0x1208, 0xa006, 0x2028, + 0x0001, 0x6b0c, 0x6800, 0x70da, 0x0804, 0x13b0, 0x0016, 0x7814, + 0xd0f4, 0x0138, 0x2001, 0x4007, 0x70db, 0x0000, 0xa18d, 0x0001, + 0x0050, 0xd0fc, 0x0138, 0x2001, 0x4007, 0x70db, 0x0001, 0xa18d, + 0x0001, 0x0008, 0xa006, 0x001e, 0x0005, 0x0016, 0x7814, 0xd0f4, + 0x0138, 0x2001, 0x4007, 0x70db, 0x0000, 0xa18d, 0x0001, 0x0008, + 0xa006, 0x001e, 0x0005, 0x0016, 0x7814, 0xd0fc, 0x0138, 0x2001, + 0x4007, 0x70db, 0x0001, 0xa18d, 0x0001, 0x0008, 0xa006, 0x001e, + 0x0005, 0x7112, 0x721a, 0x731e, 0x7810, 0xd0c4, 0x0110, 0x7422, + 0x7526, 0xac80, 0x0001, 0x8108, 0x810c, 0x81a9, 0x8098, 0x20a1, + 0x0030, 0x7003, 0x0000, 0x6084, 0x20a2, 0x53a6, 0x7007, 0x0001, 0x7974, 0xa184, 0xff00, 0x0140, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0018, 0x8107, 0x8004, 0x8004, 0x797c, - 0xa108, 0x7a78, 0xa006, 0xa211, 0xd4c4, 0x0120, 0x7b84, 0xa319, - 0x7c80, 0xa421, 0x7008, 0xd0fc, 0x0de8, 0xa084, 0x01e0, 0x01d0, - 0x7d10, 0x2031, 0x8b54, 0x2634, 0x78a8, 0x8000, 0x78aa, 0xd08c, - 0x1138, 0x7007, 0x0006, 0x7004, 0xd094, 0x1de8, 0x0804, 0x20e3, - 0x2069, 0x4347, 0x206b, 0x0003, 0x78ac, 0xa085, 0x0300, 0x78ae, - 0xa006, 0x0048, 0x2030, 0x75d6, 0x2091, 0x4080, 0x7d96, 0x7d10, - 0xa5ac, 0xffcf, 0x7d12, 0x2091, 0x8001, 0x78aa, 0x7007, 0x0006, - 0x263a, 0x7003, 0x0001, 0x711a, 0x721e, 0xd5c4, 0x0110, 0x7322, - 0x7426, 0x0005, 0x6084, 0xa086, 0x0103, 0x11d8, 0x6114, 0x6018, - 0xa105, 0x11b8, 0x2069, 0x0000, 0x6818, 0xd084, 0x1190, 0x600c, - 0x70c6, 0x6010, 0x70ca, 0x70c3, 0x8020, 0x681b, 0x0001, 0x2091, - 0x4080, 0x080c, 0x1d4e, 0x0e04, 0x21a0, 0x786c, 0xa065, 0x1d10, - 0x0005, 0x0059, 0x1530, 0x786c, 0xa065, 0x19e0, 0x0410, 0x0029, - 0x1500, 0x786c, 0xa065, 0x1dd8, 0x00e0, 0x6084, 0xa086, 0x0103, - 0x1168, 0x6018, 0xc0fc, 0x601a, 0xa086, 0x0004, 0x1138, 0x7804, - 0xd0a4, 0x0120, 0x080c, 0x1d4e, 0xa006, 0x0005, 0x0079, 0x1118, - 0xa085, 0x0001, 0x0005, 0x00b9, 0x1110, 0x2041, 0x0001, 0x7d10, - 0x0005, 0x88ff, 0x0110, 0x2091, 0x4080, 0x0005, 0x7b90, 0x7994, - 0x70d4, 0xa102, 0x1118, 0xa385, 0x0000, 0x0005, 0x0210, 0xa302, - 0x0005, 0x8002, 0x0005, 0xa184, 0xff00, 0x0140, 0x810f, 0x810c, - 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0018, 0x8107, 0x8004, - 0x8004, 0x7a9c, 0x7b98, 0x7ca4, 0x7da0, 0xa210, 0xa006, 0xa319, - 0xa421, 0xa529, 0x2009, 0x0018, 0x6028, 0xa005, 0x0110, 0x2009, - 0x0040, 0x080c, 0x1ab7, 0x01d0, 0x78a8, 0x8000, 0x78aa, 0xd08c, - 0x1510, 0x6014, 0xd0fc, 0x1118, 0x2069, 0x4340, 0x0010, 0x2069, - 0x4380, 0x2091, 0x8000, 0x681f, 0x0003, 0x78ab, 0x0000, 0x78ac, - 0xa085, 0x0300, 0x78ae, 0x2091, 0x8001, 0x0068, 0x78ab, 0x0000, - 0x080c, 0x1d4e, 0x7990, 0x7894, 0x8000, 0xa10a, 0x1208, 0xa006, - 0x7896, 0x70d6, 0xa006, 0x2071, 0x0010, 0x2091, 0x8001, 0x0005, - 0x2138, 0xd7fc, 0x1118, 0x2009, 0x4359, 0x0010, 0x2009, 0x4399, - 0x2091, 0x8000, 0x200a, 0x00f6, 0x2009, 0x4380, 0x2079, 0x0100, - 0xd7fc, 0x1120, 0x2009, 0x4340, 0x2079, 0x0200, 0x2104, 0xa086, - 0x0000, 0x1180, 0xd7fc, 0x1118, 0x2009, 0x4345, 0x0010, 0x2009, - 0x4385, 0x2104, 0xa005, 0x1130, 0x7830, 0xa084, 0x00c0, 0x1110, - 0x781b, 0x0052, 0x00fe, 0x0005, 0x2009, 0x0002, 0x2069, 0x4300, - 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x22a9, 0x2071, 0x4380, - 0x2079, 0x0100, 0x2021, 0x45bf, 0x784b, 0x000f, 0x2001, 0x01ff, - 0x2004, 0xd0fc, 0x0118, 0x2019, 0x3c3b, 0x0030, 0x20a1, 0x012b, - 0x2019, 0x3c3b, 0xd184, 0x0110, 0x20a1, 0x022b, 0x2304, 0xa005, - 0x0140, 0x789a, 0x8318, 0x23ac, 0x8318, 0x2398, 0x53a6, 0x3318, - 0x0ca8, 0x789b, 0x0000, 0x789b, 0x0020, 0x20a9, 0x0010, 0x78af, - 0x0000, 0x78af, 0x2020, 0x1f04, 0x2287, 0x7003, 0x0000, 0x0016, - 0xd18c, 0x2009, 0x0000, 0x0108, 0xc1bd, 0x080c, 0x23bd, 0x001e, - 0x7020, 0xa084, 0x000f, 0xa085, 0x6300, 0x7806, 0x780f, 0x9000, - 0x7843, 0x00d8, 0x7853, 0x0090, 0x780b, 0x0308, 0x7456, 0x7053, - 0x0000, 0x8109, 0x0140, 0x2071, 0x4340, 0x2079, 0x0200, 0x2021, - 0x43bf, 0x0804, 0x2264, 0x0005, 0x0016, 0x2011, 0x0101, 0xd1bc, - 0x1110, 0x2011, 0x0201, 0xa18c, 0x000f, 0x2204, 0xa084, 0xfff0, - 0xa105, 0x2012, 0x001e, 0x080c, 0x23bd, 0x0005, 0x2011, 0x0101, - 0xd3fc, 0x1110, 0x2011, 0x0201, 0x20a9, 0x0009, 0x810b, 0x1f04, - 0x22ce, 0xa18c, 0x0e00, 0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012, - 0x0005, 0x2019, 0x0002, 0x2009, 0x0101, 0x20a9, 0x0005, 0x8213, - 0x1f04, 0x22df, 0xa294, 0x00e0, 0x2104, 0xa084, 0xff1f, 0xa205, - 0x200a, 0x8319, 0x0118, 0x2009, 0x0201, 0x0c78, 0x0005, 0x2011, - 0x0101, 0xd3fc, 0x1110, 0x2011, 0x0201, 0x20a9, 0x000c, 0x810b, - 0x1f04, 0x22f7, 0xa18c, 0xf000, 0x2204, 0xa084, 0x0fff, 0xa105, - 0x2012, 0x0005, 0x2011, 0x0102, 0xd3fc, 0x1110, 0x2011, 0x0202, - 0x2204, 0xa084, 0xffcf, 0xa105, 0x2012, 0x0005, 0x00c6, 0x2061, - 0x0100, 0xd1bc, 0x1110, 0x2061, 0x0200, 0xc1bc, 0x8103, 0x8003, - 0xa080, 0x0020, 0x609a, 0x62ac, 0x63ac, 0x00ce, 0x0005, 0x00c6, + 0xa108, 0x7a78, 0xa006, 0xa211, 0x7d10, 0xd5c4, 0x0120, 0x7b84, + 0xa319, 0x7c80, 0xa421, 0x7008, 0xd0fc, 0x0de8, 0x7003, 0x0001, + 0x7007, 0x0006, 0x711a, 0x721e, 0x7d10, 0xd5c4, 0x0110, 0x7322, + 0x7426, 0xa084, 0x01e0, 0x0005, 0x7848, 0xa065, 0x0120, 0x2c04, + 0x784a, 0x2063, 0x0000, 0x0005, 0x00f6, 0x2079, 0x4500, 0x7848, + 0x2062, 0x2c00, 0xa005, 0x1110, 0x080c, 0x252b, 0x784a, 0x00fe, + 0x0005, 0x2011, 0x8f00, 0x7a4a, 0x7bc4, 0x8319, 0x0128, 0xa280, + 0x0032, 0x2012, 0x2010, 0x0cc8, 0x2013, 0x0000, 0x0005, 0x0016, + 0x0026, 0xd7fc, 0x1118, 0x2011, 0x4ac0, 0x0010, 0x2011, 0x6ac0, + 0xa784, 0x0f00, 0x800b, 0xa784, 0x001f, 0x0120, 0x8003, 0x8003, + 0x8003, 0x8003, 0xa105, 0xa268, 0x002e, 0x001e, 0x0005, 0x0c39, + 0x2900, 0x682a, 0x2a00, 0x682e, 0x6808, 0xa084, 0xf9ef, 0xa80d, + 0x690a, 0x00e6, 0xd7fc, 0x1128, 0x2009, 0x4552, 0x2071, 0x4540, + 0x0020, 0x2009, 0x4592, 0x2071, 0x4580, 0x210c, 0x6804, 0xa005, + 0x0148, 0xa116, 0x1138, 0x2060, 0x6000, 0x6806, 0x0016, 0x200b, + 0x0000, 0x0018, 0x2009, 0x0000, 0x0016, 0x6804, 0xa065, 0x0178, + 0x6000, 0x6806, 0x0421, 0x080c, 0x1d7c, 0x6810, 0x7908, 0x8109, + 0x790a, 0x8001, 0x6812, 0x1d88, 0x7910, 0xc1a5, 0x7912, 0x001e, + 0x6902, 0x6906, 0x2d00, 0x2060, 0x080c, 0x2672, 0x00ee, 0x0005, + 0xa065, 0x0160, 0x2008, 0x609c, 0xa005, 0x0128, 0x2062, 0x609f, + 0x0000, 0xa065, 0x0cc0, 0x7848, 0x794a, 0x2062, 0x0005, 0x6007, + 0x0103, 0x608f, 0x0000, 0x20a9, 0x001c, 0xac80, 0x0005, 0x20a0, + 0x2001, 0x0000, 0x40a4, 0x6828, 0x601a, 0x682c, 0x6022, 0x0005, + 0x00e6, 0xd7fc, 0x1128, 0x2071, 0x4540, 0x2031, 0x45c0, 0x0020, + 0x2071, 0x4580, 0x2031, 0x47c0, 0x704c, 0xa08c, 0x0200, 0x1128, + 0xa608, 0x2d0a, 0x8000, 0x704e, 0xa006, 0x00ee, 0x0005, 0x00f6, + 0xd7fc, 0x1118, 0x2079, 0x4540, 0x0010, 0x2079, 0x4580, 0x080c, + 0x1b5f, 0x2091, 0x8000, 0x6804, 0x780a, 0xa065, 0x0904, 0x1c40, + 0x0030, 0x2c00, 0x780a, 0x2060, 0x6000, 0xa065, 0x05c8, 0x6010, + 0xa306, 0x1db8, 0x600c, 0xa206, 0x1da0, 0x2c28, 0x7848, 0xac06, + 0x1108, 0x0458, 0x6804, 0xac06, 0x1140, 0x6000, 0x2060, 0x6806, + 0xa005, 0x1118, 0x6803, 0x0000, 0x0048, 0x6400, 0x7808, 0x2060, + 0x6402, 0xa486, 0x0000, 0x1110, 0x2c00, 0x6802, 0x2560, 0x00fe, + 0x080c, 0x1bc7, 0x00f6, 0x601b, 0x0005, 0x6023, 0x0020, 0x00fe, + 0x080c, 0x1d7c, 0x00f6, 0x7908, 0x8109, 0x790a, 0x6810, 0x8001, + 0x6812, 0x1118, 0x7810, 0xc0a5, 0x7812, 0x2001, 0xffff, 0xa005, + 0x00fe, 0x0005, 0x0076, 0x2700, 0x2039, 0x0000, 0xd0fc, 0x0108, + 0xc7fd, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x2091, + 0x8000, 0x080c, 0x1b77, 0x8738, 0xa784, 0x001f, 0x1dd0, 0xa7bc, + 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x1d90, 0x2091, + 0x8001, 0x007e, 0x0005, 0x786c, 0x2009, 0x8d74, 0x210c, 0xa10d, + 0x0118, 0xa065, 0x0804, 0x2061, 0x2061, 0x0000, 0x6018, 0xd084, + 0x11b8, 0x7810, 0xd08c, 0x0130, 0xc08c, 0x7812, 0xc7fc, 0x2069, + 0x4540, 0x0028, 0xc08d, 0x7812, 0x2069, 0x4580, 0xc7fd, 0x2091, + 0x8000, 0x681c, 0x681f, 0x0000, 0x2091, 0x8001, 0xa005, 0x1108, + 0x0005, 0xa08c, 0xfff0, 0x0110, 0x080c, 0x252b, 0x0002, 0x1c9f, + 0x1ca2, 0x1ca8, 0x1cac, 0x1ca0, 0x1cb0, 0x1ca0, 0x1ca0, 0x1ca0, + 0x1cb6, 0x1ce2, 0x1ce5, 0x1cea, 0x1cf3, 0x1ca0, 0x1ca0, 0x0005, + 0x080c, 0x252b, 0x080c, 0x1c42, 0x2001, 0x8001, 0x0804, 0x1cfc, + 0x2001, 0x8003, 0x0804, 0x1cfc, 0x2001, 0x8004, 0x0804, 0x1cfc, + 0x080c, 0x1c42, 0x2001, 0x8006, 0x0804, 0x1cfc, 0x2091, 0x8000, + 0x0076, 0xd7fc, 0x1128, 0x2069, 0x4540, 0x2039, 0x0009, 0x0020, + 0x2069, 0x4580, 0x2039, 0x0009, 0x6800, 0xa086, 0x0000, 0x0128, + 0x000e, 0x6f1e, 0x2091, 0x8001, 0x0005, 0x6870, 0x007e, 0xa0bc, + 0xff00, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0010, 0x080c, + 0x1b77, 0x8738, 0xa784, 0x001f, 0x1dd0, 0x2091, 0x8001, 0x2001, + 0x800a, 0x00d0, 0x2001, 0x800c, 0x00b8, 0x080c, 0x1c42, 0x2001, + 0x800d, 0x0090, 0xd7fc, 0x0110, 0x78e4, 0x0008, 0x78e0, 0x70c6, + 0x2001, 0x800e, 0x0048, 0xd7fc, 0x0110, 0x78ec, 0x0008, 0x78e8, + 0x70c6, 0x2001, 0x000d, 0x0000, 0x70c2, 0xd7fc, 0x1118, 0x70db, + 0x0000, 0x0010, 0x70db, 0x0001, 0x2061, 0x0000, 0x601b, 0x0001, + 0x2091, 0x4080, 0x0005, 0xac80, 0x0001, 0x81ff, 0x0518, 0x2099, + 0x0030, 0x20a0, 0x700c, 0xa084, 0x07ff, 0x0100, 0x7018, 0x0006, + 0x701c, 0x0006, 0x7020, 0x0006, 0x7024, 0x0006, 0x7112, 0x81ac, + 0x721a, 0x731e, 0x7422, 0x7526, 0x7003, 0x0001, 0x7007, 0x0001, + 0x7008, 0x800b, 0x1ee8, 0x7007, 0x0002, 0xa08c, 0x01e0, 0x1110, + 0x53a5, 0xa006, 0x7003, 0x0000, 0x7007, 0x0004, 0x000e, 0x7026, + 0x000e, 0x7022, 0x000e, 0x701e, 0x000e, 0x701a, 0x0005, 0x2011, + 0x0020, 0x2009, 0x0010, 0x6b0a, 0x6c0e, 0x681f, 0x0201, 0x6803, + 0xfd20, 0x6807, 0x0038, 0x6a1a, 0x2d00, 0xa0e8, 0x0008, 0xa290, + 0x0004, 0x8109, 0x1d80, 0x0005, 0x70ec, 0xd0dc, 0x1520, 0x2029, + 0x0001, 0x7814, 0xd0cc, 0x1160, 0x70ec, 0xd0e4, 0x2019, 0x0c0a, + 0x2021, 0x000a, 0x1120, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x0070, + 0x70ec, 0xd0e4, 0x1128, 0x2019, 0x1c0c, 0x2021, 0x000c, 0x0030, + 0x2019, 0x1c09, 0x2021, 0x0009, 0xa5ad, 0x0200, 0x6b0a, 0x6c0e, + 0x6d1e, 0x6807, 0x0038, 0x0005, 0x6004, 0x6086, 0x2c08, 0x2063, + 0x0000, 0x7868, 0xa005, 0x796a, 0x0110, 0x2c02, 0x0008, 0x796e, + 0x0005, 0x00c6, 0x2061, 0x4500, 0x6887, 0x0103, 0x2d08, 0x206b, + 0x0000, 0x6068, 0xa005, 0x616a, 0x0110, 0x2d02, 0x0008, 0x616e, + 0x00ce, 0x0005, 0x2091, 0x8000, 0x2c04, 0x786e, 0xa005, 0x1108, + 0x786a, 0x2091, 0x8001, 0x609c, 0xa005, 0x0188, 0x00c6, 0x2060, + 0x2008, 0x609c, 0xa005, 0x0138, 0x2062, 0x609f, 0x0000, 0xa065, + 0x609c, 0xa005, 0x1dc8, 0x7848, 0x794a, 0x2062, 0x00ce, 0x7848, + 0x2062, 0x609f, 0x0000, 0xac85, 0x0000, 0x1110, 0x080c, 0x252b, + 0x784a, 0x0005, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e, + 0x1208, 0xa200, 0x1f04, 0x1dc6, 0x8086, 0x818e, 0x0005, 0x0156, + 0x20a9, 0x0010, 0xa005, 0x01b8, 0xa11a, 0x12a8, 0x8213, 0x818d, + 0x0228, 0xa11a, 0x1220, 0x1f04, 0x1dd6, 0x0028, 0xa11a, 0x2308, + 0x8210, 0x1f04, 0x1dd6, 0x0006, 0x3200, 0xa084, 0xefff, 0x2080, + 0x000e, 0x015e, 0x0005, 0x0006, 0x3200, 0xa085, 0x1000, 0x0cb8, + 0x7d74, 0x70d0, 0xa506, 0x0904, 0x1ea4, 0x7810, 0x2050, 0x080c, + 0x1b3c, 0x0904, 0x1ea4, 0xa046, 0x7970, 0x2500, 0x8000, 0xa112, + 0x2009, 0x0040, 0x1208, 0x0030, 0x72d0, 0xa206, 0x0118, 0x8840, + 0x2009, 0x0080, 0x00c6, 0x7112, 0x7007, 0x0001, 0x2099, 0x0030, + 0x20a9, 0x0020, 0xac80, 0x0001, 0x20a0, 0x2061, 0x0000, 0x88ff, + 0x0110, 0x080c, 0x1b3c, 0x7008, 0xd0fc, 0x0de8, 0x7007, 0x0002, + 0x2091, 0x8001, 0xa08c, 0x01e0, 0x1538, 0x53a5, 0x8cff, 0x1120, + 0x88ff, 0x0904, 0x1e91, 0x0050, 0x2c00, 0x788e, 0x20a9, 0x0020, + 0xac80, 0x0001, 0x20a0, 0x53a5, 0x0804, 0x1e91, 0xa046, 0x7218, + 0x731c, 0xdac4, 0x0110, 0x7420, 0x7524, 0xa292, 0x0040, 0xa39b, + 0x0000, 0xa4a3, 0x0000, 0xa5ab, 0x0000, 0x721a, 0x731e, 0xdac4, + 0x0118, 0x7422, 0x7526, 0xa006, 0x7007, 0x0004, 0x0904, 0x1e91, + 0x8cff, 0x0110, 0x080c, 0x1b44, 0x00ce, 0x080c, 0x1b44, 0xa046, + 0x7888, 0x8000, 0x788a, 0xa086, 0x0002, 0x01c0, 0x7a7c, 0x7b78, + 0xdac4, 0x0110, 0x7c84, 0x7d80, 0x7974, 0x8107, 0x8004, 0x8004, + 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x721a, + 0x731e, 0xdac4, 0x0588, 0x7422, 0x7526, 0x0470, 0x6014, 0xd0fc, + 0x1118, 0x2069, 0x4540, 0x0010, 0x2069, 0x4580, 0x2091, 0x8000, + 0x681f, 0x0002, 0x88ff, 0x0120, 0xa046, 0x788c, 0x2060, 0x0c70, + 0x788b, 0x0000, 0x78ac, 0xa085, 0x0003, 0x78ae, 0x2091, 0x8001, + 0x0098, 0x00ce, 0x788b, 0x0000, 0x080c, 0x201c, 0x6004, 0xa084, + 0x000f, 0x0059, 0x88ff, 0x0130, 0x788c, 0x2060, 0x6004, 0xa084, + 0x000f, 0x0019, 0x0804, 0x1df0, 0x0005, 0x0002, 0x1eb6, 0x1ed1, + 0x1eea, 0x1eb6, 0x1ef7, 0x1ec7, 0x1eb6, 0x1eb6, 0x1eb6, 0x1ecf, + 0x1ee8, 0x1eb6, 0x1eb6, 0x1eb6, 0x1eb6, 0x1eb6, 0x2039, 0x0400, + 0x78bc, 0xa705, 0x78be, 0x6008, 0xa705, 0x600a, 0x080c, 0x1f33, + 0x609c, 0x78ba, 0x609f, 0x0000, 0x080c, 0x2008, 0x0005, 0x78bc, + 0xd0c4, 0x0108, 0x0c58, 0x601c, 0xc0bd, 0x601e, 0x0030, 0x080c, + 0x2046, 0x78bc, 0xd0c4, 0x0108, 0x0c08, 0x78bf, 0x0000, 0x6004, + 0x8007, 0xa084, 0x00ff, 0x78b2, 0x8001, 0x0138, 0x080c, 0x1f33, + 0x0120, 0x78bc, 0xc0c5, 0x78be, 0x0010, 0x0804, 0x1f4e, 0x0005, + 0x080c, 0x2043, 0x78bc, 0xa08c, 0x0e00, 0x1110, 0xd0c4, 0x1108, + 0x0828, 0x080c, 0x1f33, 0x1110, 0x0804, 0x1f4e, 0x0005, 0x78bc, + 0xd0c4, 0x0110, 0x0804, 0x1eb6, 0x78bf, 0x0000, 0x6714, 0x2011, + 0x0001, 0x22a8, 0x6018, 0xa084, 0x00ff, 0xa005, 0x0188, 0xa7bc, + 0xff00, 0x20a9, 0x0020, 0xa08e, 0x0001, 0x0150, 0xa7bc, 0x8000, + 0x2011, 0x0002, 0x20a9, 0x0100, 0xa08e, 0x0002, 0x0108, 0x00c0, + 0x080c, 0x1b5f, 0x2d00, 0x2091, 0x8000, 0x682b, 0x0000, 0x682f, + 0x0000, 0x6808, 0xa084, 0xffde, 0x680a, 0xade8, 0x0010, 0x2091, + 0x8001, 0x1f04, 0x1f1b, 0x8211, 0x0118, 0x20a9, 0x0100, 0x0c58, + 0x080c, 0x1b44, 0x0005, 0x609f, 0x0000, 0x78b4, 0xa06d, 0x2c00, + 0x78b6, 0x1110, 0x78ba, 0x0038, 0x689e, 0x2d00, 0x6002, 0x78b8, + 0xad06, 0x1108, 0x6002, 0x78b0, 0x8001, 0x78b2, 0x1130, 0x78bc, + 0xc0c4, 0x78be, 0x78b8, 0x2060, 0xa006, 0x0005, 0x00e6, 0xa02e, + 0x2530, 0x7dba, 0x7db6, 0x65ae, 0x65b2, 0x601c, 0x60a2, 0x2048, + 0xa984, 0xe1ff, 0x601e, 0xa984, 0x0060, 0x0110, 0x080c, 0x3f66, + 0x6596, 0x65a6, 0x669a, 0x66aa, 0x6714, 0x2071, 0x4580, 0xd7fc, + 0x1110, 0x2071, 0x4540, 0xa784, 0x0f00, 0x800b, 0xa784, 0x001f, + 0x0120, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0x71c0, 0xa168, + 0x2700, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0x71c4, + 0xa100, 0x60c2, 0x2091, 0x8000, 0x7814, 0xd0c4, 0x0138, 0xd7fc, + 0x1118, 0xd0f4, 0x1140, 0x0010, 0xd0fc, 0x1128, 0x6e08, 0xd684, + 0x01f0, 0xd9fc, 0x11e0, 0x2091, 0x8001, 0x080c, 0x1bc7, 0x2091, + 0x8000, 0x080c, 0x1d7c, 0x2091, 0x8001, 0x7814, 0xd0c4, 0x0904, + 0x2006, 0xd7fc, 0x1120, 0xd0f4, 0x1130, 0x0804, 0x2006, 0xd0fc, + 0x1110, 0x0804, 0x2006, 0x601b, 0x0021, 0x0804, 0x2006, 0x6024, + 0xa096, 0x0001, 0x1110, 0x8000, 0x6026, 0x6a10, 0x6814, 0xa202, + 0x0268, 0x0160, 0x2091, 0x8001, 0x2039, 0x0200, 0x609c, 0x78ba, + 0x609f, 0x0000, 0x080c, 0x2008, 0x0804, 0x2006, 0x2c08, 0xd9fc, + 0x01f0, 0x6800, 0xa065, 0x01d8, 0x6a04, 0x7000, 0xa084, 0x0002, + 0x0168, 0x7048, 0xa206, 0x1150, 0x6b04, 0x2160, 0x2304, 0x6002, + 0xa005, 0x1108, 0x6902, 0x2260, 0x6102, 0x0098, 0x2d00, 0x2060, + 0x080c, 0x2672, 0x6e08, 0x2160, 0x6202, 0x6906, 0x0050, 0x6800, + 0x6902, 0xa065, 0x0110, 0x6102, 0x0008, 0x6906, 0x2160, 0x6003, + 0x0000, 0x2160, 0xd9fc, 0x0118, 0xa6b4, 0xfffc, 0x6e0a, 0x6810, + 0x7d08, 0x8528, 0x7d0a, 0x8000, 0x6812, 0x2091, 0x8001, 0xd6b4, + 0x0128, 0xa6b6, 0x0040, 0x6e0a, 0x080c, 0x1bd8, 0x00ee, 0x0005, + 0x6008, 0xa705, 0x600a, 0x2091, 0x8000, 0x080c, 0x1d7c, 0x2091, + 0x8001, 0x78b8, 0xa065, 0x0128, 0x609c, 0x78ba, 0x609f, 0x0000, + 0x0c78, 0x78b6, 0x78ba, 0x0005, 0x7970, 0x7874, 0x2818, 0xd384, + 0x0118, 0x8000, 0xa112, 0x0220, 0x8000, 0xa112, 0x1278, 0xc384, + 0x7a7c, 0x721a, 0x7a78, 0x721e, 0xdac4, 0x0120, 0x7a84, 0x7222, + 0x7a80, 0x7226, 0xa006, 0xd384, 0x0108, 0x8000, 0x7876, 0x70d2, + 0x781c, 0xa005, 0x0138, 0x8001, 0x781e, 0x1120, 0x0e04, 0x2042, + 0x2091, 0x4080, 0x0005, 0x2039, 0x2058, 0x0010, 0x2039, 0x205e, + 0x2704, 0xa005, 0x0160, 0xac00, 0x2068, 0x6908, 0x6810, 0x6912, + 0x680a, 0x690c, 0x6814, 0x6916, 0x680e, 0x8738, 0x0c88, 0x0005, + 0x0003, 0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0015, 0x001b, + 0x0000, 0x2041, 0x0000, 0x780c, 0x0002, 0x220a, 0x21e5, 0x2069, + 0x20d9, 0x2039, 0x8d74, 0x2734, 0x7d10, 0x00c0, 0x6084, 0xa086, + 0x0103, 0x1904, 0x20c3, 0x6114, 0x6018, 0xa105, 0x0120, 0x86ff, + 0x11d8, 0x0804, 0x20c3, 0x8603, 0xa080, 0x8d55, 0x620c, 0x2202, + 0x8000, 0x6210, 0x2202, 0x080c, 0x1d9a, 0x8630, 0xa68e, 0x000f, + 0x0904, 0x2144, 0x786c, 0xa065, 0x1d08, 0x7808, 0xa602, 0x1220, + 0xd5ac, 0x1110, 0x263a, 0x0005, 0xa682, 0x0003, 0x1a04, 0x2144, + 0x2091, 0x8000, 0x2069, 0x0000, 0x6818, 0xd084, 0x11f8, 0x2011, + 0x8d55, 0x2204, 0x70c6, 0x8210, 0x2204, 0x70ca, 0xd684, 0x1130, + 0x8210, 0x2204, 0x70da, 0x8210, 0x2204, 0x70de, 0xa685, 0x8020, + 0x70c2, 0x681b, 0x0001, 0x2091, 0x4080, 0x7810, 0xa084, 0xffcf, + 0x7812, 0x2091, 0x8001, 0x203b, 0x0000, 0x0005, 0x7810, 0xc0ad, + 0x7812, 0x0804, 0x2144, 0x263a, 0x080c, 0x2210, 0x1904, 0x222c, + 0x786c, 0xa065, 0x1904, 0x206e, 0x2091, 0x8000, 0x7810, 0xa084, + 0xffcf, 0x86ff, 0x0108, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0804, + 0x222c, 0x2039, 0x8d74, 0x2734, 0x7d10, 0x00a0, 0x6084, 0xa086, + 0x0103, 0x1904, 0x212e, 0x6114, 0x6018, 0xa105, 0x0120, 0x86ff, + 0x11b8, 0x0804, 0x212e, 0xa680, 0x8d55, 0x620c, 0x2202, 0x080c, + 0x1d9a, 0x8630, 0xa68e, 0x001e, 0x0904, 0x2144, 0x786c, 0xa065, + 0x1d28, 0x7808, 0xa602, 0x1220, 0xd5ac, 0x1110, 0x263a, 0x0005, + 0xa682, 0x0006, 0x1a04, 0x2144, 0x2091, 0x8000, 0x2069, 0x0000, + 0x6818, 0xd084, 0x11f8, 0x2011, 0x8d55, 0x2009, 0x8d4e, 0x26a8, + 0x211c, 0x2204, 0x201a, 0x8108, 0x8210, 0x1f04, 0x2110, 0xa685, + 0x8030, 0x70c2, 0x681b, 0x0001, 0x2091, 0x4080, 0x7810, 0xa084, + 0xffcf, 0x7812, 0x2091, 0x8001, 0xa006, 0x2009, 0x8d75, 0x200a, + 0x203a, 0x0005, 0x7810, 0xc0ad, 0x7812, 0x00b0, 0x263a, 0x080c, + 0x2210, 0x1904, 0x222c, 0x786c, 0xa065, 0x1904, 0x20de, 0x2091, + 0x8000, 0x7810, 0xa084, 0xffcf, 0x86ff, 0x0108, 0xc0ad, 0x7812, + 0x2091, 0x8001, 0x0804, 0x222c, 0x2091, 0x8000, 0x7007, 0x0004, + 0x7994, 0x70d4, 0xa102, 0x0228, 0x0168, 0x7b90, 0xa302, 0x1150, + 0x0010, 0x8002, 0x1138, 0x263a, 0x7810, 0xc0ad, 0x7812, 0x2091, + 0x8001, 0x0005, 0xa184, 0xff00, 0x0140, 0x810f, 0x810c, 0x810c, + 0x8004, 0x8004, 0x8007, 0xa100, 0x0018, 0x8107, 0x8004, 0x8004, + 0x7a9c, 0xa210, 0x721a, 0x7a98, 0xa006, 0xa211, 0x721e, 0xd4c4, + 0x0130, 0x7aa4, 0xa211, 0x7222, 0x7aa0, 0xa211, 0x7226, 0x20a1, + 0x0030, 0x7003, 0x0000, 0x2009, 0x8d54, 0x260a, 0x8109, 0x2198, + 0x2104, 0xd084, 0x0108, 0x8633, 0xa6b0, 0x0002, 0x26a8, 0x53a6, + 0x8603, 0x7012, 0x7007, 0x0001, 0x7990, 0x7894, 0x8000, 0xa10a, + 0x1208, 0xa006, 0x2028, 0x7974, 0xa184, 0xff00, 0x0140, 0x810f, + 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0018, 0x8107, + 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, 0xa006, 0xa211, 0xd4c4, + 0x0120, 0x7b84, 0xa319, 0x7c80, 0xa421, 0x7008, 0xd0fc, 0x0de8, + 0xa084, 0x01e0, 0x01d0, 0x7d10, 0x2031, 0x8d54, 0x2634, 0x78a8, + 0x8000, 0x78aa, 0xd08c, 0x1138, 0x7007, 0x0006, 0x7004, 0xd094, + 0x1de8, 0x0804, 0x2146, 0x2069, 0x4547, 0x206b, 0x0003, 0x78ac, + 0xa085, 0x0300, 0x78ae, 0xa006, 0x0048, 0x2030, 0x75d6, 0x2091, + 0x4080, 0x7d96, 0x7d10, 0xa5ac, 0xffcf, 0x7d12, 0x2091, 0x8001, + 0x78aa, 0x7007, 0x0006, 0x263a, 0x7003, 0x0001, 0x711a, 0x721e, + 0xd5c4, 0x0110, 0x7322, 0x7426, 0x0005, 0x6084, 0xa086, 0x0103, + 0x11d8, 0x6114, 0x6018, 0xa105, 0x11b8, 0x2069, 0x0000, 0x6818, + 0xd084, 0x1190, 0x600c, 0x70c6, 0x6010, 0x70ca, 0x70c3, 0x8020, + 0x681b, 0x0001, 0x2091, 0x4080, 0x080c, 0x1d9a, 0x0e04, 0x2203, + 0x786c, 0xa065, 0x1d10, 0x0005, 0x0059, 0x1530, 0x786c, 0xa065, + 0x19e0, 0x0410, 0x0029, 0x1500, 0x786c, 0xa065, 0x1dd8, 0x00e0, + 0x6084, 0xa086, 0x0103, 0x1168, 0x6018, 0xc0fc, 0x601a, 0xa086, + 0x0004, 0x1138, 0x7804, 0xd0a4, 0x0120, 0x080c, 0x1d9a, 0xa006, + 0x0005, 0x0079, 0x1118, 0xa085, 0x0001, 0x0005, 0x00b9, 0x1110, + 0x2041, 0x0001, 0x7d10, 0x0005, 0x88ff, 0x0110, 0x2091, 0x4080, + 0x0005, 0x7b90, 0x7994, 0x70d4, 0xa102, 0x1118, 0xa385, 0x0000, + 0x0005, 0x0210, 0xa302, 0x0005, 0x8002, 0x0005, 0xa184, 0xff00, + 0x0140, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, + 0x0018, 0x8107, 0x8004, 0x8004, 0x7a9c, 0x7b98, 0x7ca4, 0x7da0, + 0xa210, 0xa006, 0xa319, 0xa421, 0xa529, 0x2009, 0x0018, 0x6028, + 0xa005, 0x0110, 0x2009, 0x0040, 0x080c, 0x1af9, 0x01d0, 0x78a8, + 0x8000, 0x78aa, 0xd08c, 0x1510, 0x6014, 0xd0fc, 0x1118, 0x2069, + 0x4540, 0x0010, 0x2069, 0x4580, 0x2091, 0x8000, 0x681f, 0x0003, + 0x78ab, 0x0000, 0x78ac, 0xa085, 0x0300, 0x78ae, 0x2091, 0x8001, + 0x0068, 0x78ab, 0x0000, 0x080c, 0x1d9a, 0x7990, 0x7894, 0x8000, + 0xa10a, 0x1208, 0xa006, 0x7896, 0x70d6, 0xa006, 0x2071, 0x0010, + 0x2091, 0x8001, 0x0005, 0x2138, 0xd7fc, 0x1118, 0x2009, 0x4558, + 0x0010, 0x2009, 0x4598, 0x2091, 0x8000, 0x200a, 0x00f6, 0x2009, + 0x4580, 0x2079, 0x0100, 0xd7fc, 0x1120, 0x2009, 0x4540, 0x2079, + 0x0200, 0x2104, 0xa086, 0x0000, 0x1180, 0xd7fc, 0x1118, 0x2009, + 0x4545, 0x0010, 0x2009, 0x4585, 0x2104, 0xa005, 0x1130, 0x7830, + 0xa084, 0x00c0, 0x1110, 0x781b, 0x0052, 0x00fe, 0x0005, 0x2009, + 0x0002, 0x2069, 0x4500, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, + 0x230c, 0x2071, 0x4580, 0x2079, 0x0100, 0x2021, 0x47bf, 0x784b, + 0x000f, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x0118, 0x2019, 0x3dc2, + 0x0030, 0x20a1, 0x012b, 0x2019, 0x3dc2, 0xd184, 0x0110, 0x20a1, + 0x022b, 0x2304, 0xa005, 0x0140, 0x789a, 0x8318, 0x23ac, 0x8318, + 0x2398, 0x53a6, 0x3318, 0x0ca8, 0x789b, 0x0000, 0x789b, 0x0020, + 0x20a9, 0x0010, 0x78af, 0x0000, 0x78af, 0x2020, 0x1f04, 0x22ea, + 0x7003, 0x0000, 0x0016, 0xd18c, 0x2009, 0x0000, 0x0108, 0xc1bd, + 0x080c, 0x2422, 0x001e, 0x7020, 0xa084, 0x000f, 0xa085, 0x6300, + 0x7806, 0x780f, 0x9000, 0x7843, 0x00d8, 0x7853, 0x0090, 0x780b, + 0x2f08, 0x7452, 0x704f, 0x0000, 0x8109, 0x0140, 0x2071, 0x4540, + 0x2079, 0x0200, 0x2021, 0x45bf, 0x0804, 0x22c7, 0x080c, 0x24dc, + 0x0005, 0x0016, 0x2011, 0x0101, 0xd1bc, 0x1110, 0x2011, 0x0201, + 0xa18c, 0x000f, 0x2204, 0xa084, 0xfff0, 0xa105, 0x2012, 0x001e, + 0x080c, 0x2422, 0x0005, 0x2011, 0x0101, 0xd3fc, 0x1110, 0x2011, + 0x0201, 0x20a9, 0x0009, 0x810b, 0x1f04, 0x2333, 0xa18c, 0x0e00, + 0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012, 0x0005, 0x2019, 0x0002, + 0x2009, 0x0101, 0x20a9, 0x0005, 0x8213, 0x1f04, 0x2344, 0xa294, + 0x00e0, 0x2104, 0xa084, 0xff1f, 0xa205, 0x200a, 0x8319, 0x0118, + 0x2009, 0x0201, 0x0c78, 0x0005, 0x2011, 0x0101, 0xd3fc, 0x1110, + 0x2011, 0x0201, 0x20a9, 0x000c, 0x810b, 0x1f04, 0x235c, 0xa18c, + 0xf000, 0x2204, 0xa084, 0x0fff, 0xa105, 0x2012, 0x0005, 0x2011, + 0x0102, 0xd3fc, 0x1110, 0x2011, 0x0202, 0x2204, 0xa084, 0xf0cf, + 0xa105, 0x2012, 0x0005, 0x00c6, 0x2061, 0x0100, 0xd1bc, 0x1110, + 0x2061, 0x0200, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0020, 0x609a, + 0x62ac, 0x63ac, 0x00ce, 0x0005, 0x00c6, 0x2061, 0x0100, 0xd1bc, + 0x1110, 0x2061, 0x0200, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0022, + 0x609a, 0x60a4, 0xa084, 0xffdf, 0x60ae, 0x00ce, 0x0005, 0x00c6, 0x2061, 0x0100, 0xd1bc, 0x1110, 0x2061, 0x0200, 0xc1bc, 0x8103, - 0x8003, 0xa080, 0x0022, 0x609a, 0x60a4, 0xa084, 0xffdf, 0x60ae, - 0x00ce, 0x0005, 0x00c6, 0x2061, 0x0100, 0xd1bc, 0x1110, 0x2061, - 0x0200, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0020, 0x609a, 0x60a4, - 0xa28c, 0x0020, 0x0118, 0xc2ac, 0xa39d, 0x4000, 0xc3ec, 0xd3b4, - 0x1108, 0xc3ed, 0x62ae, 0x2010, 0x60a4, 0x63ae, 0x2018, 0x00ce, - 0x0005, 0x2091, 0x8000, 0x00c6, 0x00e6, 0x6818, 0xa005, 0x0904, - 0x23a1, 0xd1fc, 0x0118, 0x2061, 0x8ad0, 0x0010, 0x2061, 0x89c0, - 0x080c, 0x23a9, 0x0538, 0x20a9, 0x0101, 0xd1fc, 0x0118, 0x2061, - 0x89d0, 0x0010, 0x2061, 0x88c0, 0x00c6, 0x04d9, 0x0128, 0x00ce, - 0x8c60, 0x1f04, 0x236c, 0x0468, 0x000e, 0xd1fc, 0x0128, 0xa082, - 0x89d0, 0x2071, 0x4380, 0x0020, 0xa082, 0x88c0, 0x2071, 0x4340, - 0x707a, 0x7176, 0x2001, 0x0004, 0x7066, 0x7083, 0x000f, 0x080c, - 0x2228, 0x00a0, 0xd1fc, 0x1118, 0x2071, 0x4340, 0x0010, 0x2071, - 0x4380, 0x6020, 0xc0dd, 0x6022, 0x7176, 0x2c00, 0x707e, 0x2001, - 0x0006, 0x7066, 0x7083, 0x000f, 0x080c, 0x2228, 0x2001, 0x0000, - 0x0010, 0x2001, 0x0001, 0x2091, 0x8001, 0xa005, 0x00ee, 0x00ce, - 0x0005, 0x2c04, 0xa005, 0x0170, 0x2060, 0x6010, 0xa306, 0x1140, - 0x600c, 0xa206, 0x1128, 0x6014, 0xa106, 0x1110, 0xa006, 0x0020, - 0x6000, 0x0c80, 0xa085, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x0016, - 0x2079, 0x4380, 0x2071, 0x0100, 0xd1bc, 0x1120, 0x2079, 0x4340, - 0x2071, 0x0200, 0x7920, 0xa18c, 0x000f, 0x70ec, 0xd0c4, 0x1110, - 0x001e, 0x0060, 0x810b, 0x810b, 0x810b, 0x810b, 0x000e, 0xa18d, - 0x0800, 0xd0bc, 0x1110, 0xa18d, 0x0f00, 0x2104, 0x00ee, 0x00fe, - 0x0005, 0x00e6, 0x2001, 0x4301, 0x2004, 0xd0ac, 0x1904, 0x2439, - 0x68e4, 0xd0ac, 0x0904, 0x2439, 0xa084, 0x0006, 0x1904, 0x2439, - 0x6014, 0xd0fc, 0x1118, 0x2071, 0x47c0, 0x0010, 0x2071, 0x4840, - 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xae70, 0x7004, - 0xa084, 0x000a, 0x15b0, 0x7108, 0xa194, 0xff00, 0x0590, 0xa18c, - 0x00ff, 0x2001, 0x000a, 0xa106, 0x01a8, 0x2001, 0x000c, 0xa106, - 0x01a0, 0x2001, 0x0012, 0xa106, 0x0198, 0x2001, 0x0014, 0xa106, - 0x0190, 0x2001, 0x0019, 0xa106, 0x0188, 0x2001, 0x0032, 0xa106, - 0x0180, 0x0090, 0x2009, 0x000c, 0x0088, 0x2009, 0x0012, 0x0070, - 0x2009, 0x0014, 0x0058, 0x2009, 0x0019, 0x0040, 0x2009, 0x0020, - 0x0028, 0x2009, 0x003f, 0x0010, 0x2011, 0x0000, 0x2100, 0xa205, - 0x700a, 0x00ee, 0x0005, 0x0e04, 0x243b, 0x2091, 0x8000, 0x2071, + 0x8003, 0xa080, 0x0020, 0x609a, 0x60a4, 0xa28c, 0x0020, 0x0118, + 0xc2ac, 0xa39d, 0x4000, 0xc3ec, 0xd3b4, 0x1108, 0xc3ed, 0x62ae, + 0x2010, 0x60a4, 0x63ae, 0x2018, 0x00ce, 0x0005, 0x2091, 0x8000, + 0x00c6, 0x00e6, 0x6818, 0xa005, 0x0904, 0x2406, 0xd1fc, 0x0118, + 0x2061, 0x8cd0, 0x0010, 0x2061, 0x8bc0, 0x080c, 0x240e, 0x0538, + 0x20a9, 0x0101, 0xd1fc, 0x0118, 0x2061, 0x8bd0, 0x0010, 0x2061, + 0x8ac0, 0x00c6, 0x04d9, 0x0128, 0x00ce, 0x8c60, 0x1f04, 0x23d1, + 0x0468, 0x000e, 0xd1fc, 0x0128, 0xa082, 0x8bd0, 0x2071, 0x4580, + 0x0020, 0xa082, 0x8ac0, 0x2071, 0x4540, 0x7076, 0x7172, 0x2001, + 0x0004, 0x7062, 0x707f, 0x000f, 0x080c, 0x228b, 0x00a0, 0xd1fc, + 0x1118, 0x2071, 0x4540, 0x0010, 0x2071, 0x4580, 0x6020, 0xc0dd, + 0x6022, 0x7172, 0x2c00, 0x707a, 0x2001, 0x0006, 0x7062, 0x707f, + 0x000f, 0x080c, 0x228b, 0x2001, 0x0000, 0x0010, 0x2001, 0x0001, + 0x2091, 0x8001, 0xa005, 0x00ee, 0x00ce, 0x0005, 0x2c04, 0xa005, + 0x0170, 0x2060, 0x6010, 0xa306, 0x1140, 0x600c, 0xa206, 0x1128, + 0x6014, 0xa106, 0x1110, 0xa006, 0x0020, 0x6000, 0x0c80, 0xa085, + 0x0001, 0x0005, 0x00f6, 0x00e6, 0x0016, 0x2079, 0x4580, 0x2071, + 0x0100, 0xd1bc, 0x1120, 0x2079, 0x4540, 0x2071, 0x0200, 0x7920, + 0xa18c, 0x000f, 0x70ec, 0xd0c4, 0x1110, 0x001e, 0x0060, 0x810b, + 0x810b, 0x810b, 0x810b, 0x000e, 0xa18d, 0x0800, 0xd0bc, 0x1110, + 0xa18d, 0x0f00, 0x2104, 0x00ee, 0x00fe, 0x0005, 0x2001, 0x4501, + 0x2004, 0xd0ac, 0x1138, 0x68e4, 0xd0ac, 0x0120, 0xa084, 0x0006, + 0x1108, 0x0009, 0x0005, 0x6014, 0x00e6, 0x0036, 0x2018, 0x2071, + 0x4a40, 0xd0fc, 0x1110, 0x2071, 0x49c0, 0x8007, 0xa084, 0x000f, + 0x8003, 0x8003, 0x8003, 0xae70, 0x7004, 0xa084, 0x000a, 0x1904, + 0x24d9, 0x7108, 0xa194, 0xff00, 0x0904, 0x24d9, 0xa18c, 0x00ff, + 0x701c, 0xa084, 0xff00, 0x01c0, 0x7004, 0xa085, 0x003a, 0x7006, + 0x2001, 0x0009, 0xa102, 0x16d8, 0x2001, 0x000a, 0xa102, 0x16d0, + 0x2001, 0x000c, 0xa102, 0x16c8, 0x701c, 0xa084, 0x00ff, 0x701e, + 0x7004, 0xa084, 0xffdf, 0x7006, 0x2001, 0x000a, 0xa106, 0x01a8, + 0x2001, 0x000c, 0xa106, 0x01a0, 0x2001, 0x0012, 0xa106, 0x0198, + 0x2001, 0x0014, 0xa106, 0x0190, 0x2001, 0x0019, 0xa106, 0x0188, + 0x2001, 0x0032, 0xa106, 0x0180, 0x00d8, 0x2009, 0x000c, 0x00d0, + 0x2009, 0x0012, 0x00b8, 0x2009, 0x0014, 0x00a0, 0x2009, 0x0019, + 0x0088, 0x2009, 0x0020, 0x0070, 0x2009, 0x003f, 0x0058, 0x2009, + 0x000a, 0x0040, 0x2009, 0x000c, 0x0028, 0x2009, 0x0019, 0x0010, + 0x2011, 0x0000, 0x2100, 0xa205, 0x700a, 0x7004, 0xa085, 0x000a, + 0x7006, 0x2071, 0x4500, 0x7004, 0xd0bc, 0x0158, 0xd3fc, 0x1120, + 0x73ea, 0x2071, 0x4540, 0x0018, 0x73ee, 0x2071, 0x4580, 0x701f, + 0x800f, 0x003e, 0x00ee, 0x0005, 0x2001, 0x01ff, 0x2004, 0xd0fc, + 0x11d0, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x12a0, 0x2071, + 0x0200, 0x71ec, 0xa18c, 0x1c00, 0x810f, 0x810c, 0x810c, 0x2079, + 0x0100, 0x78ec, 0xa084, 0x1c00, 0x8007, 0x8004, 0x8004, 0xa105, + 0xa08a, 0x0007, 0x0208, 0x0005, 0x0002, 0x252a, 0x2511, 0x252a, + 0x2511, 0x2504, 0x251e, 0x2504, 0x7008, 0xa084, 0xc3ff, 0xa085, + 0x3000, 0x700a, 0x7808, 0xa084, 0xc3ff, 0xa085, 0x3000, 0x780a, + 0x0005, 0x7008, 0xa084, 0xc3ff, 0xa085, 0x2000, 0x700a, 0x7808, + 0xa084, 0xc3ff, 0xa085, 0x2000, 0x780a, 0x0005, 0x7008, 0xa084, + 0xc3ff, 0xa085, 0x0c00, 0x700a, 0x7808, 0xa084, 0xc3ff, 0xa085, + 0x0c00, 0x780a, 0x0005, 0x0e04, 0x252b, 0x2091, 0x8000, 0x2071, 0x0000, 0x0006, 0x7018, 0xd084, 0x1de8, 0x000e, 0x2071, 0x0010, - 0x70ca, 0x000e, 0x70c6, 0x70c3, 0x8002, 0x70db, 0x0a01, 0x70df, - 0x0013, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0cf8, - 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x78a0, 0x708e, 0x7592, 0x7496, - 0x769a, 0x779e, 0xa594, 0x003f, 0xd4f4, 0x0138, 0xd7bc, 0x1128, - 0xa784, 0x007d, 0x1904, 0x3ace, 0x0871, 0xa49c, 0x000f, 0xa382, + 0x70ca, 0x000e, 0x70c6, 0x70c3, 0x8002, 0x70db, 0x0a04, 0x70df, + 0x0008, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0cf8, + 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x78a0, 0x708a, 0x758e, 0x7492, + 0x7696, 0x779a, 0xa594, 0x003f, 0xd4f4, 0x0138, 0xd7bc, 0x1128, + 0xa784, 0x007d, 0x1904, 0x3c3a, 0x0871, 0xa49c, 0x000f, 0xa382, 0x0004, 0x0320, 0xa3a6, 0x0007, 0x1930, 0x2418, 0x8507, 0xa084, - 0x000f, 0x0002, 0x2a4f, 0x2b10, 0x2b38, 0x2d71, 0x30cc, 0x3112, - 0x31a7, 0x3220, 0x32db, 0x33a6, 0x248d, 0x248a, 0x285b, 0x295c, - 0x30a0, 0x248a, 0x080c, 0x243b, 0x0005, 0xa006, 0x0038, 0x7808, - 0xc08d, 0x780a, 0xa006, 0x7002, 0x704e, 0x7046, 0x70d2, 0x7060, - 0xa005, 0x1904, 0x25d9, 0x7064, 0xa084, 0x0007, 0x0002, 0x24a7, - 0x2513, 0x251b, 0x2524, 0x252d, 0x25bf, 0x2536, 0x2513, 0x7830, - 0xd0bc, 0x1d10, 0x71d4, 0xd1b4, 0x1904, 0x24f0, 0x70a4, 0xa086, - 0x0001, 0x09d0, 0x70b4, 0xa06d, 0x6800, 0xa065, 0xa055, 0x789b, - 0x0080, 0x6b0c, 0x7baa, 0x6808, 0xa045, 0x6d10, 0x6804, 0xa06d, - 0xa05d, 0xa886, 0x0001, 0x0118, 0x69bc, 0x7daa, 0x79aa, 0x68c0, - 0xa04d, 0x6e1c, 0x2001, 0x0010, 0x0804, 0x270a, 0x7060, 0xa005, - 0x1904, 0x248c, 0x00c6, 0x00d6, 0x70b4, 0xa06d, 0x6800, 0xa065, + 0x000f, 0x0002, 0x2b40, 0x2c01, 0x2c29, 0x2e64, 0x31f1, 0x3243, + 0x32e8, 0x3361, 0x341f, 0x34f6, 0x257d, 0x257a, 0x294d, 0x2a4d, + 0x31c5, 0x257a, 0x080c, 0x252b, 0x0005, 0xa006, 0x0038, 0x7808, + 0xc08d, 0x780a, 0xa006, 0x7002, 0x704a, 0x7042, 0x70ce, 0x705c, + 0xa005, 0x1904, 0x26cb, 0x7060, 0xa084, 0x0007, 0x0002, 0x2597, + 0x2605, 0x260d, 0x2616, 0x261f, 0x26b1, 0x2628, 0x2605, 0x7830, + 0xd0bc, 0x1d10, 0x71d0, 0xd1bc, 0x19f8, 0xd1b4, 0x1904, 0x25e2, + 0x70a0, 0xa086, 0x0001, 0x09c0, 0x70b0, 0xa06d, 0x6800, 0xa065, 0xa055, 0x789b, 0x0080, 0x6b0c, 0x7baa, 0x6808, 0xa045, 0x6d10, 0x6804, 0xa06d, 0xa05d, 0xa886, 0x0001, 0x0118, 0x69bc, 0x7daa, - 0x79aa, 0x68c0, 0xa04d, 0x6e1c, 0x2001, 0x0020, 0x0804, 0x270a, - 0x080c, 0x3a8d, 0x1904, 0x248c, 0x781b, 0x0068, 0x70bc, 0xa06d, + 0x79aa, 0x68c0, 0xa04d, 0x6e1c, 0x2001, 0x0010, 0x0804, 0x27fc, + 0x705c, 0xa005, 0x1904, 0x257c, 0x00c6, 0x00d6, 0x70b0, 0xa06d, + 0x6800, 0xa065, 0xa055, 0x789b, 0x0080, 0x6b0c, 0x7baa, 0x6808, + 0xa045, 0x6d10, 0x6804, 0xa06d, 0xa05d, 0xa886, 0x0001, 0x0118, + 0x69bc, 0x7daa, 0x79aa, 0x68c0, 0xa04d, 0x6e1c, 0x2001, 0x0020, + 0x0804, 0x27fc, 0x080c, 0x3bf9, 0x1904, 0x257c, 0x781b, 0x0068, + 0x70b8, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, + 0x78d2, 0x78da, 0x7808, 0xc08d, 0x780a, 0x68bc, 0x703e, 0xc1b4, + 0x71d2, 0x70b4, 0xa065, 0x68c0, 0x7056, 0x7003, 0x0002, 0x2d00, + 0x704a, 0xad80, 0x0009, 0x7042, 0x0005, 0x080c, 0x3bf9, 0x1120, + 0x781b, 0x0054, 0x7003, 0x0004, 0x0005, 0x080c, 0x3bf9, 0x1128, + 0x2011, 0x000c, 0x0419, 0x7003, 0x0004, 0x0005, 0x080c, 0x3bf9, + 0x1128, 0x2011, 0x0006, 0x00d1, 0x7003, 0x0004, 0x0005, 0x080c, + 0x3bf9, 0x1128, 0x2011, 0x000d, 0x0089, 0x7003, 0x0004, 0x0005, + 0x080c, 0x3bf9, 0x1150, 0x2011, 0x0006, 0x0041, 0x7078, 0x707b, + 0x0000, 0x2068, 0x704a, 0x7003, 0x0001, 0x0005, 0x7170, 0xc1fc, + 0x8107, 0x7882, 0x789b, 0x0080, 0xa286, 0x000c, 0x1120, 0x7aaa, + 0x2001, 0x0001, 0x0098, 0xa18c, 0x001f, 0xa18d, 0x00c0, 0x79aa, + 0xa286, 0x000d, 0x0120, 0x7aaa, 0x2001, 0x0002, 0x0038, 0x78ab, + 0x0020, 0x7174, 0x79aa, 0x7aaa, 0x2001, 0x0004, 0x789b, 0x0060, + 0x78aa, 0x785b, 0x0004, 0x781b, 0x0113, 0x080c, 0x3c0c, 0x707f, + 0x000f, 0x70d0, 0xd0b4, 0x0168, 0xc0b4, 0x70d2, 0x00c6, 0x70b4, + 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, + 0x00ce, 0x0005, 0x7014, 0xa005, 0x1138, 0x70d0, 0xd0b4, 0x0128, + 0x70b4, 0xac06, 0x1110, 0x0c29, 0x0005, 0x0016, 0x71a0, 0xa186, + 0x0001, 0x0528, 0x00d6, 0x0026, 0x2100, 0x2011, 0x0001, 0xa212, + 0x70b0, 0x2068, 0x6800, 0xac06, 0x0120, 0x8211, 0x01b0, 0x00c9, + 0x0cc8, 0x00c6, 0x2100, 0x2011, 0x0001, 0xa212, 0x70b0, 0x2068, + 0x6800, 0x2060, 0x6008, 0xa084, 0xfbef, 0x600a, 0x8211, 0x0110, + 0x0041, 0x0cb0, 0x70a3, 0x0001, 0x00ce, 0x002e, 0x00de, 0x001e, + 0x0005, 0xade8, 0x0005, 0x70a8, 0xad06, 0x1110, 0x70a4, 0x2068, + 0x0005, 0x080c, 0x3bf9, 0x1904, 0x257c, 0x7078, 0x2068, 0x7770, + 0x080c, 0x3b35, 0x2c50, 0x080c, 0x3c94, 0x789b, 0x0080, 0x6814, + 0xa084, 0x001f, 0xc0bd, 0x78aa, 0x6e1c, 0x2041, 0x0001, 0x2001, + 0x0004, 0x0804, 0x2801, 0x080c, 0x3bf9, 0x1904, 0x257c, 0x789b, + 0x0080, 0x705c, 0x2068, 0x6f14, 0x70d0, 0xd0b4, 0x0168, 0xc0b4, + 0x70d2, 0x00c6, 0x70b4, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, + 0x6018, 0x8001, 0x601a, 0x00ce, 0x080c, 0x3b35, 0x2c50, 0x080c, + 0x3c94, 0x6824, 0xa005, 0x0130, 0xa082, 0x0006, 0x0208, 0x0010, + 0x6827, 0x0005, 0x6814, 0xa084, 0x001f, 0xc0bd, 0x78aa, 0x2031, + 0x0020, 0x2041, 0x0001, 0x2001, 0x0003, 0x0804, 0x2801, 0xc28d, + 0x72d2, 0x72bc, 0xa200, 0xa015, 0x7150, 0x8108, 0xa12a, 0x0208, + 0x71bc, 0x2164, 0x6504, 0x85ff, 0x1170, 0x7152, 0x8421, 0x1da8, + 0x70d0, 0xd08c, 0x0128, 0x70cc, 0xa005, 0x1110, 0x70cf, 0x000a, + 0x0005, 0x2200, 0x0c90, 0x70d0, 0xc08c, 0x70d2, 0x70cf, 0x0000, + 0x6034, 0xa005, 0x1db0, 0x6708, 0xa784, 0x073f, 0x01d0, 0xd7d4, + 0x1d80, 0xa784, 0x0021, 0x1d68, 0xa784, 0x0002, 0x0130, 0xa784, + 0x0004, 0x0d38, 0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0218, 0x1d08, + 0xa784, 0x0100, 0x0130, 0x6018, 0xa005, 0x19d8, 0xa7bc, 0xfeff, + 0x670a, 0x2568, 0x6823, 0x0000, 0x6e1c, 0xa684, 0x000e, 0x6318, + 0x0128, 0x601c, 0xa302, 0x0220, 0x0118, 0x0858, 0x83ff, 0x1948, + 0x2d58, 0x2c50, 0x7152, 0xd7bc, 0x1110, 0x7028, 0x6022, 0xc7bc, + 0x670a, 0x68c0, 0xa065, 0xa04d, 0x6100, 0x2a60, 0x2041, 0x0001, + 0x6b14, 0xa39c, 0x001f, 0xa39d, 0x00c0, 0xd1fc, 0x0110, 0xd684, + 0x0110, 0xa39c, 0xffbf, 0xd6a4, 0x0110, 0xa39d, 0x0020, 0xa684, + 0x000e, 0x1904, 0x27b3, 0xc7a5, 0x670a, 0x2c00, 0x68c6, 0x77a0, + 0xa786, 0x0001, 0x1178, 0x70d0, 0xd0b4, 0x1160, 0x7000, 0xa082, + 0x0002, 0x1240, 0x7830, 0xd0bc, 0x1128, 0x789b, 0x0080, 0x7baa, + 0x0804, 0x27fa, 0x8739, 0x77a2, 0x2750, 0x77ac, 0xa7b0, 0x0005, + 0x70a8, 0xa606, 0x1108, 0x76a4, 0x76ae, 0x2c3a, 0x8738, 0x2d3a, + 0x8738, 0x283a, 0x8738, 0x233a, 0x8738, 0x253a, 0x7830, 0xd0bc, + 0x0150, 0x2091, 0x8000, 0x2091, 0x303d, 0x70d0, 0xa084, 0x303d, + 0x2091, 0x8000, 0x2090, 0xaad5, 0x0000, 0x0120, 0x8421, 0x2200, + 0x1904, 0x2704, 0x0005, 0xd1dc, 0x0904, 0x3796, 0x2029, 0x0020, + 0xd69c, 0x1120, 0x8528, 0xd68c, 0x1108, 0x8528, 0x8840, 0x6f14, + 0x610c, 0x8108, 0xa18c, 0x00ff, 0x70c8, 0xa160, 0x2c64, 0x8cff, + 0x0188, 0x6014, 0xa706, 0x1dd0, 0x60b8, 0x8001, 0x60ba, 0x1d88, + 0x2a60, 0x6008, 0xa085, 0x0100, 0x600a, 0x2200, 0x8421, 0x1904, + 0x2704, 0x0005, 0x2a60, 0x610e, 0x69be, 0x2c00, 0x68c6, 0x8840, + 0x6008, 0xc0d5, 0x600a, 0x77a0, 0xa786, 0x0001, 0x1904, 0x278a, + 0x70d0, 0xd0b4, 0x1904, 0x278a, 0x7000, 0xa082, 0x0002, 0x1a04, + 0x278a, 0x7830, 0xd0bc, 0x1904, 0x278a, 0x789b, 0x0080, 0x7baa, + 0x7daa, 0x79aa, 0x2001, 0x0002, 0x0006, 0x6018, 0x8000, 0x601a, + 0x0008, 0x0006, 0x2960, 0x6104, 0x2a60, 0x080c, 0x3ca7, 0x1590, + 0xa184, 0x0018, 0x0180, 0xa184, 0x0010, 0x0118, 0x080c, 0x393d, + 0x1548, 0xa184, 0x0008, 0x0138, 0x69a0, 0xa184, 0x0600, 0x1118, + 0x080c, 0x385d, 0x00f8, 0x69a0, 0xa184, 0x1e00, 0x0528, 0xa184, + 0x0800, 0x0178, 0x00c6, 0x2960, 0x6000, 0xa085, 0x2000, 0x6002, + 0x6104, 0xa18d, 0x0010, 0x6106, 0x00ce, 0x080c, 0x393d, 0x1150, + 0x69a0, 0xa184, 0x0200, 0x0118, 0x080c, 0x38a0, 0x0018, 0xa184, + 0x0400, 0x19f0, 0x69a0, 0xa184, 0x1000, 0x0130, 0x6914, 0xa18c, + 0xff00, 0x810f, 0x080c, 0x2384, 0x002e, 0xa68c, 0x00e0, 0xa684, + 0x0060, 0x0128, 0xa086, 0x0060, 0x1110, 0xa18d, 0x4000, 0xa18d, + 0x0104, 0x69b6, 0x789b, 0x0060, 0x2800, 0x78aa, 0x6818, 0xc0fd, + 0x681a, 0xd6bc, 0x0168, 0xc0fc, 0x7083, 0x0000, 0xa08a, 0x000d, + 0x0328, 0xa08a, 0x000c, 0x7182, 0x2001, 0x000c, 0x800c, 0x7186, + 0x78aa, 0x3518, 0x3340, 0x3428, 0x8000, 0x80ac, 0xaf80, 0x002b, + 0x20a0, 0x789b, 0x0000, 0xad80, 0x000b, 0x2098, 0x53a6, 0x23a8, + 0x2898, 0x25a0, 0xa286, 0x0020, 0x1508, 0x70d0, 0xc0b5, 0x70d2, + 0x2c00, 0x70b6, 0x2d00, 0x70ba, 0x6814, 0xc0fc, 0x8007, 0x7882, + 0xa286, 0x0002, 0x0904, 0x28d2, 0x70a0, 0x8000, 0x70a2, 0x74b0, + 0xa498, 0x0005, 0x70a8, 0xa306, 0x1108, 0x73a4, 0x73b2, 0xa286, + 0x0010, 0x0904, 0x257c, 0x00de, 0x00ce, 0x0005, 0x7000, 0xa005, + 0x19e0, 0xa286, 0x0002, 0x1904, 0x28e9, 0x080c, 0x3bf9, 0x19a8, + 0x6814, 0xc0fc, 0x8007, 0x7882, 0x2091, 0x8000, 0x781b, 0x0068, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, - 0x7808, 0xc08d, 0x780a, 0x68bc, 0x7042, 0xc1b4, 0x71d6, 0x70b8, - 0xa065, 0x68c0, 0x705a, 0x7003, 0x0002, 0x2d00, 0x704e, 0xad80, - 0x0009, 0x7046, 0x0005, 0x080c, 0x3a8d, 0x1120, 0x781b, 0x0054, - 0x7003, 0x0004, 0x0005, 0x080c, 0x3a8d, 0x1128, 0x2011, 0x000c, - 0x0419, 0x7003, 0x0004, 0x0005, 0x080c, 0x3a8d, 0x1128, 0x2011, - 0x0006, 0x00d1, 0x7003, 0x0004, 0x0005, 0x080c, 0x3a8d, 0x1128, - 0x2011, 0x000d, 0x0089, 0x7003, 0x0004, 0x0005, 0x080c, 0x3a8d, - 0x1150, 0x2011, 0x0006, 0x0041, 0x707c, 0x707f, 0x0000, 0x2068, - 0x704e, 0x7003, 0x0001, 0x0005, 0x7174, 0xc1fc, 0x8107, 0x7882, - 0x789b, 0x0080, 0xa286, 0x000c, 0x1120, 0x7aaa, 0x2001, 0x0001, - 0x0098, 0xa18c, 0x001f, 0xa18d, 0x00c0, 0x79aa, 0xa286, 0x000d, - 0x0120, 0x7aaa, 0x2001, 0x0002, 0x0038, 0x78ab, 0x0020, 0x7178, - 0x79aa, 0x7aaa, 0x2001, 0x0004, 0x789b, 0x0060, 0x78aa, 0x785b, - 0x0004, 0x781b, 0x0113, 0x080c, 0x3aa0, 0x7083, 0x000f, 0x70d4, - 0xd0b4, 0x0168, 0xc0b4, 0x70d6, 0x00c6, 0x70b8, 0xa065, 0x6008, - 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x00ce, 0x0005, - 0x7014, 0xa005, 0x1138, 0x70d4, 0xd0b4, 0x0128, 0x70b8, 0xac06, - 0x1110, 0x0c29, 0x0005, 0x0016, 0x71a4, 0xa186, 0x0001, 0x0528, - 0x00d6, 0x0026, 0x2100, 0x2011, 0x0001, 0xa212, 0x70b4, 0x2068, - 0x6800, 0xac06, 0x0120, 0x8211, 0x01b0, 0x00c9, 0x0cc8, 0x00c6, - 0x2100, 0x2011, 0x0001, 0xa212, 0x70b4, 0x2068, 0x6800, 0x2060, - 0x6008, 0xa084, 0xfbef, 0x600a, 0x8211, 0x0110, 0x0041, 0x0cb0, - 0x70a7, 0x0001, 0x00ce, 0x002e, 0x00de, 0x001e, 0x0005, 0xade8, - 0x0005, 0x70ac, 0xad06, 0x1110, 0x70a8, 0x2068, 0x0005, 0x080c, - 0x3a8d, 0x1904, 0x248c, 0x707c, 0x2068, 0x7774, 0x080c, 0x396d, - 0x2c50, 0x080c, 0x3b28, 0x789b, 0x0080, 0x6814, 0xa084, 0x001f, - 0xc0bd, 0x78aa, 0x6e1c, 0x2041, 0x0001, 0x2001, 0x0004, 0x0804, - 0x270f, 0x080c, 0x3a8d, 0x1904, 0x248c, 0x789b, 0x0080, 0x7060, - 0x2068, 0x6f14, 0x70d4, 0xd0b4, 0x0168, 0xc0b4, 0x70d6, 0x00c6, - 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, - 0x601a, 0x00ce, 0x080c, 0x396d, 0x2c50, 0x080c, 0x3b28, 0x6824, - 0xa005, 0x0130, 0xa082, 0x0006, 0x0208, 0x0010, 0x6827, 0x0005, - 0x6814, 0xa084, 0x001f, 0xc0bd, 0x78aa, 0x2031, 0x0020, 0x2041, - 0x0001, 0x2001, 0x0003, 0x0804, 0x270f, 0xc28d, 0x72d6, 0x72c0, - 0xa200, 0xa015, 0x7154, 0x8108, 0xa12a, 0x0208, 0x71c0, 0x2164, - 0x6504, 0x85ff, 0x1170, 0x7156, 0x8421, 0x1da8, 0x70d4, 0xd08c, - 0x0128, 0x70d0, 0xa005, 0x1110, 0x70d3, 0x000a, 0x0005, 0x2200, - 0x0c90, 0x70d4, 0xc08c, 0x70d6, 0x70d3, 0x0000, 0x6034, 0xa005, - 0x1db0, 0x6708, 0xa784, 0x073f, 0x01d0, 0xd7d4, 0x1d80, 0xa784, - 0x0021, 0x1d68, 0xa784, 0x0002, 0x0130, 0xa784, 0x0004, 0x0d38, - 0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0218, 0x1d08, 0xa784, 0x0100, - 0x0130, 0x6018, 0xa005, 0x19d8, 0xa7bc, 0xfeff, 0x670a, 0x2568, - 0x6823, 0x0000, 0x6e1c, 0xa684, 0x000e, 0x6318, 0x0128, 0x601c, - 0xa302, 0x0220, 0x0118, 0x0858, 0x83ff, 0x1948, 0x2d58, 0x2c50, - 0x7156, 0xd7bc, 0x1110, 0x7028, 0x6022, 0xc7bc, 0x670a, 0x68c0, - 0xa065, 0xa04d, 0x6100, 0x2a60, 0x2041, 0x0001, 0x6b14, 0xa39c, - 0x001f, 0xa39d, 0x00c0, 0xd1fc, 0x0110, 0xd684, 0x0110, 0xa39c, - 0xffbf, 0xd6a4, 0x0110, 0xa39d, 0x0020, 0xa684, 0x000e, 0x1904, - 0x26c1, 0xc7a5, 0x670a, 0x2c00, 0x68c6, 0x77a4, 0xa786, 0x0001, - 0x1178, 0x70d4, 0xd0b4, 0x1160, 0x7000, 0xa082, 0x0002, 0x1240, - 0x7830, 0xd0bc, 0x1128, 0x789b, 0x0080, 0x7baa, 0x0804, 0x2708, - 0x8739, 0x77a6, 0x2750, 0x77b0, 0xa7b0, 0x0005, 0x70ac, 0xa606, - 0x1108, 0x76a8, 0x76b2, 0x2c3a, 0x8738, 0x2d3a, 0x8738, 0x283a, - 0x8738, 0x233a, 0x8738, 0x253a, 0x7830, 0xd0bc, 0x0150, 0x2091, - 0x8000, 0x2091, 0x303d, 0x70d4, 0xa084, 0x303d, 0x2091, 0x8000, - 0x2090, 0xaad5, 0x0000, 0x0120, 0x8421, 0x2200, 0x1904, 0x2612, - 0x0005, 0xd1dc, 0x0904, 0x35d5, 0x2029, 0x0020, 0xd69c, 0x1120, - 0x8528, 0xd68c, 0x1108, 0x8528, 0x8840, 0x6f14, 0x610c, 0x8108, - 0xa18c, 0x00ff, 0x70cc, 0xa160, 0x2c64, 0x8cff, 0x0188, 0x6014, - 0xa706, 0x1dd0, 0x60b8, 0x8001, 0x60ba, 0x1d88, 0x2a60, 0x6008, - 0xa085, 0x0100, 0x600a, 0x2200, 0x8421, 0x1904, 0x2612, 0x0005, - 0x2a60, 0x610e, 0x69be, 0x2c00, 0x68c6, 0x8840, 0x6008, 0xc0d5, - 0x600a, 0x77a4, 0xa786, 0x0001, 0x1904, 0x2698, 0x70d4, 0xd0b4, - 0x1904, 0x2698, 0x7000, 0xa082, 0x0002, 0x1a04, 0x2698, 0x7830, - 0xd0bc, 0x1904, 0x2698, 0x789b, 0x0080, 0x7baa, 0x7daa, 0x79aa, - 0x2001, 0x0002, 0x0006, 0x6018, 0x8000, 0x601a, 0x0008, 0x0006, - 0x2960, 0x6104, 0x2a60, 0x080c, 0x3b3b, 0x1590, 0xa184, 0x0018, - 0x0180, 0xa184, 0x0010, 0x0118, 0x080c, 0x3776, 0x1548, 0xa184, - 0x0008, 0x0138, 0x69a0, 0xa184, 0x0600, 0x1118, 0x080c, 0x3696, - 0x00f8, 0x69a0, 0xa184, 0x1e00, 0x0528, 0xa184, 0x0800, 0x0178, - 0x00c6, 0x2960, 0x6000, 0xa085, 0x2000, 0x6002, 0x6104, 0xa18d, - 0x0010, 0x6106, 0x00ce, 0x080c, 0x3776, 0x1150, 0x69a0, 0xa184, - 0x0200, 0x0118, 0x080c, 0x36d9, 0x0018, 0xa184, 0x0400, 0x19f0, - 0x69a0, 0xa184, 0x1000, 0x0130, 0x6914, 0xa18c, 0xff00, 0x810f, - 0x080c, 0x231f, 0x002e, 0xa68c, 0x00e0, 0xa684, 0x0060, 0x0128, - 0xa086, 0x0060, 0x1110, 0xa18d, 0x4000, 0xa18d, 0x0104, 0x69b6, - 0x789b, 0x0060, 0x2800, 0x78aa, 0x6818, 0xc0fd, 0x681a, 0xd6bc, - 0x0168, 0xc0fc, 0x7087, 0x0000, 0xa08a, 0x000d, 0x0328, 0xa08a, - 0x000c, 0x7186, 0x2001, 0x000c, 0x800c, 0x718a, 0x78aa, 0x3518, - 0x3340, 0x3428, 0x8000, 0x80ac, 0xaf80, 0x002b, 0x20a0, 0x789b, - 0x0000, 0xad80, 0x000b, 0x2098, 0x53a6, 0x23a8, 0x2898, 0x25a0, - 0xa286, 0x0020, 0x1508, 0x70d4, 0xc0b5, 0x70d6, 0x2c00, 0x70ba, - 0x2d00, 0x70be, 0x6814, 0xc0fc, 0x8007, 0x7882, 0xa286, 0x0002, - 0x0904, 0x27e0, 0x70a4, 0x8000, 0x70a6, 0x74b4, 0xa498, 0x0005, - 0x70ac, 0xa306, 0x1108, 0x73a8, 0x73b6, 0xa286, 0x0010, 0x0904, - 0x248c, 0x00de, 0x00ce, 0x0005, 0x7000, 0xa005, 0x19e0, 0xa286, - 0x0002, 0x1904, 0x27f7, 0x080c, 0x3a8d, 0x19a8, 0x6814, 0xc0fc, - 0x8007, 0x7882, 0x2091, 0x8000, 0x781b, 0x0068, 0x68b4, 0x785a, - 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x2091, 0x8001, - 0x7808, 0xc08d, 0x780a, 0x0126, 0x00d6, 0x00c6, 0x70d4, 0xa084, - 0x2e00, 0x2090, 0x00ce, 0x00de, 0x012e, 0x2900, 0x705a, 0x68bc, - 0x7042, 0x7003, 0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, - 0x7830, 0xd0bc, 0x0140, 0x2091, 0x303d, 0x70d4, 0xa084, 0x303d, - 0x2091, 0x8000, 0x2090, 0x70a4, 0xa005, 0x1108, 0x0005, 0x8421, - 0x0de8, 0x7250, 0x70c0, 0xa200, 0xa015, 0x0804, 0x2612, 0xa286, - 0x0010, 0x1560, 0x080c, 0x3a8d, 0x1904, 0x278b, 0x6814, 0xc0fc, - 0x8007, 0x7882, 0x781b, 0x0068, 0x68b4, 0x785a, 0x6894, 0x78d6, - 0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d, 0x780a, 0x70a4, - 0x8000, 0x70a6, 0x74b4, 0xa490, 0x0005, 0x70ac, 0xa206, 0x1108, - 0x72a8, 0x72b6, 0x2900, 0x705a, 0x68bc, 0x7042, 0x7003, 0x0002, - 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x0005, 0x6bb4, 0xa39d, - 0x2000, 0x7b5a, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x6b94, 0x7bd6, - 0x7bde, 0x6e98, 0x7ed2, 0x7eda, 0x781b, 0x0068, 0x2900, 0x705a, - 0x7202, 0x7808, 0xc08d, 0x780a, 0x2300, 0xa605, 0x0170, 0x70d4, - 0xa084, 0x2e00, 0xa086, 0x2600, 0x1118, 0x2009, 0x0000, 0x0010, - 0x2009, 0x0001, 0xa284, 0x000f, 0x0023, 0xad80, 0x0009, 0x7046, - 0x0005, 0x2859, 0x3fb8, 0x3fb8, 0x3fa6, 0x3fb8, 0x2859, 0x2859, - 0x2859, 0x080c, 0x243b, 0x7808, 0xa084, 0xfffd, 0x780a, 0x00f6, - 0x2079, 0x4300, 0x78ac, 0x00fe, 0xd084, 0x01c0, 0x7064, 0xa086, - 0x0001, 0x1118, 0x7066, 0x0804, 0x293a, 0x7064, 0xa086, 0x0005, - 0x1158, 0x707c, 0x2068, 0x681b, 0x0004, 0x6817, 0x0000, 0x6820, - 0xa084, 0x00ff, 0xc09d, 0x6822, 0x7067, 0x0000, 0x70a7, 0x0000, - 0x70a8, 0x70b2, 0x70b6, 0x080c, 0x256f, 0x0156, 0x2011, 0x0004, - 0x7164, 0xa186, 0x0001, 0x0170, 0xa186, 0x0007, 0x1118, 0x701f, - 0x0005, 0x0040, 0x701f, 0x0001, 0x7067, 0x0000, 0x70d4, 0xc0c5, - 0x70d6, 0x0010, 0x7067, 0x0000, 0x2001, 0x430a, 0x2004, 0xa084, - 0x00ff, 0xa086, 0x0018, 0x0130, 0x7018, 0x7016, 0xa005, 0x1110, - 0x70a7, 0x0001, 0x0066, 0x080c, 0x3d52, 0x20a9, 0x0010, 0x2039, - 0x0000, 0x080c, 0x3861, 0xa7b8, 0x0100, 0x1f04, 0x28b1, 0x006e, - 0x7000, 0x0002, 0x28ee, 0x28cc, 0x28cc, 0x28c4, 0x28ee, 0x28ee, - 0x28ee, 0x28c2, 0x080c, 0x243b, 0x7060, 0xa005, 0x0538, 0xad06, - 0x1118, 0x6800, 0x7062, 0x0080, 0x6820, 0xd084, 0x1148, 0x6f14, - 0x080c, 0x396d, 0x6008, 0xc0d4, 0x600a, 0x080c, 0x35ab, 0x0020, - 0x705c, 0x2060, 0x6800, 0x6002, 0xa684, 0x5f00, 0x681e, 0x6818, - 0xd0fc, 0x0108, 0x6a1a, 0x6817, 0x0000, 0x682b, 0x0000, 0x6820, - 0xa084, 0x00ff, 0xc09d, 0x6822, 0x080c, 0x1d3d, 0xb284, 0x0800, - 0x0118, 0x2021, 0x8ad0, 0x0010, 0x2021, 0x89c0, 0x080c, 0x293f, - 0xb284, 0x0800, 0x0118, 0x2021, 0x4398, 0x0010, 0x2021, 0x4358, - 0x04f1, 0x20a9, 0x0101, 0xb284, 0x0800, 0x0118, 0x2021, 0x89d0, - 0x0010, 0x2021, 0x88c0, 0x0499, 0x8420, 0x1f04, 0x290b, 0xb284, - 0x0600, 0x0118, 0x2061, 0x48c0, 0x0010, 0x2061, 0x68c0, 0x2021, - 0x0002, 0x20a9, 0x0100, 0x6110, 0x81ff, 0x0198, 0x6018, 0x0016, - 0x0006, 0x2011, 0x4302, 0x220c, 0xa102, 0x2012, 0x000e, 0x001e, - 0xa102, 0x0338, 0x6012, 0x1128, 0x2011, 0x4304, 0x2204, 0xc0a5, - 0x2012, 0x601b, 0x0000, 0xace0, 0x0010, 0x1f04, 0x291b, 0x8421, - 0x1d00, 0x015e, 0x7003, 0x0000, 0x704f, 0x0000, 0x0005, 0x0046, - 0x2404, 0xa005, 0x01a8, 0x2068, 0x6800, 0x0006, 0x6a1a, 0x6817, + 0x2091, 0x8001, 0x7808, 0xc08d, 0x780a, 0x0126, 0x00d6, 0x00c6, + 0x70d0, 0xa084, 0x2e00, 0x2090, 0x00ce, 0x00de, 0x012e, 0x2900, + 0x7056, 0x68bc, 0x703e, 0x7003, 0x0002, 0x2d00, 0x704a, 0xad80, + 0x0009, 0x7042, 0x7830, 0xd0bc, 0x0140, 0x2091, 0x303d, 0x70d0, + 0xa084, 0x303d, 0x2091, 0x8000, 0x2090, 0x70a0, 0xa005, 0x1108, + 0x0005, 0x8421, 0x0de8, 0x724c, 0x70bc, 0xa200, 0xa015, 0x0804, + 0x2704, 0xa286, 0x0010, 0x1560, 0x080c, 0x3bf9, 0x1904, 0x287d, + 0x6814, 0xc0fc, 0x8007, 0x7882, 0x781b, 0x0068, 0x68b4, 0x785a, + 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d, + 0x780a, 0x70a0, 0x8000, 0x70a2, 0x74b0, 0xa490, 0x0005, 0x70a8, + 0xa206, 0x1108, 0x72a4, 0x72b2, 0x2900, 0x7056, 0x68bc, 0x703e, + 0x7003, 0x0002, 0x2d00, 0x704a, 0xad80, 0x0009, 0x7042, 0x0005, + 0x6bb4, 0xa39d, 0x2000, 0x7b5a, 0x6814, 0xc0fc, 0x8007, 0x7882, + 0x6b94, 0x7bd6, 0x7bde, 0x6e98, 0x7ed2, 0x7eda, 0x781b, 0x0068, + 0x2900, 0x7056, 0x7202, 0x7808, 0xc08d, 0x780a, 0x2300, 0xa605, + 0x0170, 0x70d0, 0xa084, 0x2e00, 0xa086, 0x2600, 0x1118, 0x2009, + 0x0000, 0x0010, 0x2009, 0x0001, 0xa284, 0x000f, 0x0023, 0xad80, + 0x0009, 0x7042, 0x0005, 0x294b, 0x4180, 0x4180, 0x416e, 0x4180, + 0x294b, 0x294b, 0x294b, 0x080c, 0x252b, 0x7808, 0xa084, 0xfffd, + 0x780a, 0x00f6, 0x2079, 0x4500, 0x78ac, 0x00fe, 0xd084, 0x01b0, + 0x7060, 0xa086, 0x0001, 0x0904, 0x2a29, 0x7060, 0xa086, 0x0005, + 0x1158, 0x7078, 0x2068, 0x681b, 0x0004, 0x6817, 0x0000, 0x6820, + 0xa084, 0x00ff, 0xc09d, 0x6822, 0x7063, 0x0000, 0x70a3, 0x0000, + 0x70a4, 0x70ae, 0x70b2, 0x080c, 0x2661, 0x0156, 0x2011, 0x0004, + 0x7160, 0xa186, 0x0001, 0x0160, 0xa186, 0x0007, 0x1118, 0x701f, + 0x0005, 0x0030, 0x701f, 0x0001, 0x70d0, 0xc0c5, 0x70d2, 0x0000, + 0x2001, 0x450a, 0x2004, 0xa084, 0x00ff, 0xa086, 0x0018, 0x0130, + 0x7018, 0x7016, 0xa005, 0x1110, 0x70a3, 0x0001, 0x0066, 0x080c, + 0x3ed9, 0x20a9, 0x0010, 0x2039, 0x0000, 0x080c, 0x3a29, 0xa7b8, + 0x0100, 0x1f04, 0x299d, 0x006e, 0x7000, 0x0002, 0x29da, 0x29b8, + 0x29b8, 0x29b0, 0x29da, 0x29da, 0x29da, 0x29ae, 0x080c, 0x252b, + 0x705c, 0xa005, 0x0538, 0xad06, 0x1118, 0x6800, 0x705e, 0x0080, + 0x6820, 0xd084, 0x1148, 0x6f14, 0x080c, 0x3b35, 0x6008, 0xc0d4, + 0x600a, 0x080c, 0x376c, 0x0020, 0x7058, 0x2060, 0x6800, 0x6002, + 0xa684, 0x5f00, 0x681e, 0x6818, 0xd0fc, 0x0108, 0x6a1a, 0x6817, + 0x0000, 0x682b, 0x0000, 0x6820, 0xa084, 0x00ff, 0xc09d, 0x6822, + 0x080c, 0x1d89, 0x2011, 0x0004, 0xb284, 0x0800, 0x0118, 0x2021, + 0x8cd0, 0x0010, 0x2021, 0x8bc0, 0x080c, 0x2a30, 0xb284, 0x0800, + 0x0118, 0x2021, 0x4597, 0x0010, 0x2021, 0x4557, 0x080c, 0x2a30, + 0x20a9, 0x0101, 0xb284, 0x0800, 0x0118, 0x2021, 0x8bd0, 0x0010, + 0x2021, 0x8ac0, 0x04a9, 0x8420, 0x1f04, 0x29fa, 0xb284, 0x0600, + 0x0118, 0x2061, 0x4ac0, 0x0010, 0x2061, 0x6ac0, 0x2021, 0x0002, + 0x20a9, 0x0100, 0x6110, 0x81ff, 0x0198, 0x6018, 0x0016, 0x0006, + 0x2011, 0x4502, 0x220c, 0xa102, 0x2012, 0x000e, 0x001e, 0xa102, + 0x0338, 0x6012, 0x1128, 0x2011, 0x4504, 0x2204, 0xc0a5, 0x2012, + 0x601b, 0x0000, 0xace0, 0x0010, 0x1f04, 0x2a0a, 0x8421, 0x1d00, + 0x015e, 0x7063, 0x0000, 0x7003, 0x0000, 0x704b, 0x0000, 0x0005, + 0x0046, 0x2404, 0xa005, 0x01a8, 0x2068, 0x6800, 0x0006, 0x6a1a, + 0x6817, 0x0000, 0x682b, 0x0000, 0x68b4, 0xa084, 0x5f00, 0x681e, + 0x6820, 0xa084, 0x00ff, 0xc09d, 0x6822, 0x080c, 0x1d89, 0x000e, + 0x0c48, 0x004e, 0x2023, 0x0000, 0x0005, 0xa282, 0x0003, 0x0310, + 0x080c, 0x252b, 0x2300, 0x0002, 0x2a57, 0x2ad4, 0x2aee, 0xa282, + 0x0002, 0x0110, 0x080c, 0x252b, 0x7060, 0x7063, 0x0000, 0x707f, + 0x0000, 0x0022, 0x77d0, 0xc7c5, 0x77d2, 0x0002, 0x2a6e, 0x2a6e, + 0x2a70, 0x2aa8, 0x37a0, 0x2a6e, 0x2aa8, 0x2a6e, 0x080c, 0x252b, + 0x7770, 0x080c, 0x3a29, 0x7770, 0xa7bc, 0x8f00, 0x080c, 0x3b35, + 0x6018, 0xa005, 0x0528, 0xd7fc, 0x1118, 0x2021, 0x8bc0, 0x0010, + 0x2021, 0x8cd0, 0x2009, 0x0005, 0x2011, 0x0010, 0x080c, 0x2b08, + 0x01b8, 0x0156, 0x20a9, 0x0101, 0xd7fc, 0x1118, 0x2021, 0x8ac0, + 0x0010, 0x2021, 0x8bd0, 0x0046, 0x2009, 0x0005, 0x2011, 0x0010, + 0x080c, 0x2b08, 0x004e, 0x0118, 0x8420, 0x1f04, 0x2a93, 0x015e, + 0x8738, 0xa784, 0x001f, 0x1990, 0x0804, 0x257f, 0x0804, 0x257f, + 0x7770, 0x080c, 0x3b35, 0x6018, 0xa005, 0x0520, 0xd7fc, 0x1118, + 0x2021, 0x8bc0, 0x0010, 0x2021, 0x8cd0, 0x2009, 0x0005, 0x2011, + 0x0020, 0x080c, 0x2b08, 0x01b0, 0x0156, 0x20a9, 0x0101, 0xd7fc, + 0x1118, 0x2021, 0x8ac0, 0x0010, 0x2021, 0x8bd0, 0x0046, 0x2009, + 0x0005, 0x2011, 0x0020, 0x04e1, 0x004e, 0x0118, 0x8420, 0x1f04, + 0x2ac6, 0x015e, 0x0804, 0x257f, 0x2200, 0x0002, 0x2ad9, 0x2adb, + 0x2adb, 0x080c, 0x252b, 0x2009, 0x0012, 0x7060, 0xa086, 0x0002, + 0x0110, 0x2009, 0x000e, 0x6818, 0xd0fc, 0x0108, 0x691a, 0x7063, + 0x0000, 0x70d0, 0xc0c5, 0x70d2, 0x0804, 0x3bab, 0x2200, 0x0002, + 0x2af5, 0x2adb, 0x2af3, 0x080c, 0x252b, 0x080c, 0x3ed9, 0x7000, + 0xa086, 0x0002, 0x1904, 0x3725, 0x080c, 0x3786, 0x6008, 0xa084, + 0xfbef, 0x600a, 0x080c, 0x3717, 0x0904, 0x3725, 0x0804, 0x257f, + 0x2404, 0xa005, 0x0590, 0x2068, 0x2d04, 0x0006, 0x6814, 0xa706, + 0x0118, 0x2d20, 0x000e, 0x0ca8, 0x000e, 0x2022, 0x691a, 0x6817, 0x0000, 0x682b, 0x0000, 0x68b4, 0xa084, 0x5f00, 0x681e, 0x6820, - 0xa084, 0x00ff, 0xc09d, 0x6822, 0x080c, 0x1d3d, 0x000e, 0x0c48, - 0x004e, 0x2023, 0x0000, 0x0005, 0xa282, 0x0003, 0x0310, 0x080c, - 0x243b, 0x2300, 0x0002, 0x2966, 0x29e3, 0x29fd, 0xa282, 0x0002, - 0x0110, 0x080c, 0x243b, 0x7064, 0x7067, 0x0000, 0x7083, 0x0000, - 0x0022, 0x77d4, 0xc7c5, 0x77d6, 0x0002, 0x297d, 0x297d, 0x297f, - 0x29b7, 0x35df, 0x297d, 0x29b7, 0x297d, 0x080c, 0x243b, 0x7774, - 0x080c, 0x3861, 0x7774, 0xa7bc, 0x8f00, 0x080c, 0x396d, 0x6018, - 0xa005, 0x0528, 0xd7fc, 0x1118, 0x2021, 0x89c0, 0x0010, 0x2021, - 0x8ad0, 0x2009, 0x0005, 0x2011, 0x0010, 0x080c, 0x2a17, 0x01b8, - 0x0156, 0x20a9, 0x0101, 0xd7fc, 0x1118, 0x2021, 0x88c0, 0x0010, - 0x2021, 0x89d0, 0x0046, 0x2009, 0x0005, 0x2011, 0x0010, 0x080c, - 0x2a17, 0x004e, 0x0118, 0x8420, 0x1f04, 0x29a2, 0x015e, 0x8738, - 0xa784, 0x001f, 0x1990, 0x0804, 0x248f, 0x0804, 0x248f, 0x7774, - 0x080c, 0x396d, 0x6018, 0xa005, 0x0520, 0xd7fc, 0x1118, 0x2021, - 0x89c0, 0x0010, 0x2021, 0x8ad0, 0x2009, 0x0005, 0x2011, 0x0020, - 0x080c, 0x2a17, 0x01b0, 0x0156, 0x20a9, 0x0101, 0xd7fc, 0x1118, - 0x2021, 0x88c0, 0x0010, 0x2021, 0x89d0, 0x0046, 0x2009, 0x0005, - 0x2011, 0x0020, 0x04e1, 0x004e, 0x0118, 0x8420, 0x1f04, 0x29d5, - 0x015e, 0x0804, 0x248f, 0x2200, 0x0002, 0x29e8, 0x29ea, 0x29ea, - 0x080c, 0x243b, 0x2009, 0x0012, 0x7064, 0xa086, 0x0002, 0x0110, - 0x2009, 0x000e, 0x6818, 0xd0fc, 0x0108, 0x691a, 0x7067, 0x0000, - 0x70d4, 0xc0c5, 0x70d6, 0x0804, 0x3a3f, 0x2200, 0x0002, 0x2a04, - 0x29ea, 0x2a02, 0x080c, 0x243b, 0x080c, 0x3d52, 0x7000, 0xa086, - 0x0002, 0x1904, 0x356d, 0x080c, 0x35c5, 0x6008, 0xa084, 0xfbef, - 0x600a, 0x080c, 0x355f, 0x0904, 0x356d, 0x0804, 0x248f, 0x2404, - 0xa005, 0x0590, 0x2068, 0x2d04, 0x0006, 0x6814, 0xa706, 0x0118, - 0x2d20, 0x000e, 0x0ca8, 0x000e, 0x2022, 0x691a, 0x6817, 0x0000, - 0x682b, 0x0000, 0x68b4, 0xa084, 0x5f00, 0x681e, 0x6820, 0xa084, - 0x00ff, 0xa205, 0x6822, 0x080c, 0x1d3d, 0x2021, 0x4302, 0x241c, - 0x8319, 0x2322, 0x6010, 0x8001, 0x6012, 0x1128, 0x2021, 0x4304, - 0x2404, 0xc0a5, 0x2022, 0x6008, 0xa084, 0xf9ef, 0x600a, 0x080c, - 0x258b, 0x080c, 0x35c5, 0x0005, 0xa085, 0x0001, 0x0ce0, 0x2300, - 0x0002, 0x2a56, 0x2a54, 0x2abc, 0x080c, 0x243b, 0x78e4, 0xa005, - 0x1708, 0x3208, 0xa18c, 0x0800, 0x0118, 0x0104, 0x248c, 0x0010, - 0x0304, 0x248c, 0x2008, 0xa084, 0x0030, 0x1110, 0x0804, 0x30a0, - 0x78ec, 0xa084, 0x0003, 0x0dd0, 0x2100, 0xa084, 0x0007, 0x0002, - 0x2a9f, 0x2aa8, 0x2a95, 0x2a78, 0x3a83, 0x3a83, 0x2a78, 0x2ab2, - 0x080c, 0x243b, 0x7000, 0xa086, 0x0004, 0x1190, 0x7064, 0xa086, - 0x0002, 0x1130, 0x2011, 0x0002, 0x2019, 0x0000, 0x0804, 0x295c, - 0x7064, 0xa086, 0x0006, 0x0db0, 0x7064, 0xa086, 0x0004, 0x0d90, - 0x79e4, 0x2001, 0x0003, 0x0804, 0x2daa, 0x6818, 0xd0fc, 0x0110, - 0x681b, 0x001d, 0x080c, 0x3837, 0x781b, 0x006e, 0x0005, 0x6818, - 0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c, 0x3837, 0x0804, 0x3a61, - 0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c, 0x3837, 0x781b, - 0x00fa, 0x0005, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c, - 0x3837, 0x781b, 0x00cb, 0x0005, 0xa584, 0x000f, 0x11c0, 0x7000, - 0x0002, 0x248f, 0x2ac9, 0x2acb, 0x356d, 0x356d, 0x356d, 0x2ac9, - 0x2ac9, 0x080c, 0x243b, 0x080c, 0x35c5, 0x6008, 0xa084, 0xfbef, - 0x600a, 0x080c, 0x355f, 0x0904, 0x356d, 0x0804, 0x248f, 0x78e4, - 0xa005, 0x1b04, 0x2a7a, 0x3208, 0xa18c, 0x0800, 0x0118, 0x0104, - 0x2a7a, 0x0010, 0x0304, 0x2a7a, 0x2008, 0xa084, 0x0030, 0x1118, - 0x781b, 0x0068, 0x0005, 0x78ec, 0xa084, 0x0003, 0x0dc8, 0x2100, - 0xa184, 0x0007, 0x0002, 0x2b02, 0x2b06, 0x2afd, 0x2afb, 0x3a83, - 0x3a83, 0x2afb, 0x3a7d, 0x080c, 0x243b, 0x080c, 0x383d, 0x781b, - 0x006e, 0x0005, 0x080c, 0x383d, 0x0804, 0x3a61, 0x080c, 0x383d, - 0x781b, 0x00fa, 0x0005, 0x080c, 0x383d, 0x781b, 0x00cb, 0x0005, - 0x2300, 0x0002, 0x2b17, 0x2b15, 0x2b19, 0x080c, 0x243b, 0x0804, - 0x3220, 0x681b, 0x0016, 0x78a3, 0x0000, 0x79e4, 0xa184, 0x0030, - 0x0904, 0x3220, 0x78ec, 0xa084, 0x0003, 0x0904, 0x3220, 0xa184, - 0x0100, 0x0d98, 0xa184, 0x0007, 0x0002, 0x2b35, 0x2b06, 0x2a95, - 0x3a3f, 0x3a83, 0x3a83, 0x3a3f, 0x3a7d, 0x080c, 0x3a4b, 0x0005, - 0xa282, 0x0005, 0x0310, 0x080c, 0x243b, 0x7898, 0x2040, 0x2300, - 0x0002, 0x2b44, 0x2d41, 0x2d4b, 0x2200, 0x0002, 0x2b60, 0x2b4d, - 0x2b60, 0x2b4b, 0x2d25, 0x080c, 0x243b, 0x789b, 0x0018, 0x78a8, - 0x2010, 0xa084, 0x00ff, 0xa082, 0x0020, 0x0a04, 0x3809, 0xa08a, - 0x0004, 0x1a04, 0x3809, 0x0002, 0x3809, 0x3809, 0x3809, 0x37bf, - 0x789b, 0x0018, 0x79a8, 0xa184, 0x0080, 0x0148, 0x0804, 0x3809, - 0x7000, 0xa005, 0x1dd8, 0x2011, 0x0004, 0x0804, 0x33b2, 0xa184, - 0x00ff, 0xa08a, 0x0010, 0x1a04, 0x3809, 0x0002, 0x2b88, 0x2b86, - 0x2b9a, 0x2b9e, 0x2c3c, 0x3809, 0x3809, 0x2c3e, 0x3809, 0x3809, - 0x2d21, 0x2d21, 0x3809, 0x3809, 0x3809, 0x2d23, 0x080c, 0x243b, - 0xd6e4, 0x0140, 0x2001, 0x0300, 0x8000, 0x8000, 0x783a, 0x781b, - 0x00c6, 0x0005, 0x6818, 0xd0fc, 0x0118, 0x681b, 0x001d, 0x0c90, - 0x0804, 0x3a3f, 0x681b, 0x001d, 0x0804, 0x3831, 0x6920, 0x6922, - 0xa684, 0x1800, 0x15e0, 0x6820, 0xd084, 0x1904, 0x2be7, 0x6818, - 0xa086, 0x0008, 0x1110, 0x681b, 0x0000, 0xd6d4, 0x0568, 0xd6bc, - 0x0558, 0x7087, 0x0000, 0x6818, 0xa084, 0x003f, 0xa08a, 0x000d, - 0x0718, 0xa08a, 0x000c, 0x7186, 0x2001, 0x000c, 0x800c, 0x718a, - 0x789b, 0x0061, 0x78aa, 0x0156, 0x0136, 0x0146, 0x0016, 0x3208, - 0xa18c, 0x0600, 0x0118, 0x20a1, 0x022b, 0x0010, 0x20a1, 0x012b, - 0x001e, 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, - 0x53a6, 0x014e, 0x013e, 0x015e, 0x781b, 0x0071, 0x0005, 0xd6e4, - 0x0130, 0x781b, 0x0083, 0x0005, 0x781b, 0x0083, 0x0005, 0xa684, - 0x0060, 0x0dd0, 0xd6dc, 0x0dc0, 0xd6fc, 0x01a0, 0xc6fc, 0x7e5a, - 0x6eb6, 0x7adc, 0x79d8, 0x78d0, 0x8007, 0xa084, 0x007f, 0xa108, - 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, - 0xa303, 0x68ae, 0xd6f4, 0x0118, 0xc6f4, 0x7e5a, 0x6eb6, 0x7000, - 0xa086, 0x0003, 0x1148, 0x0006, 0x080c, 0x3d52, 0x080c, 0x3fb8, - 0x000e, 0x781b, 0x0080, 0x0005, 0xa006, 0x080c, 0x4083, 0x6ab0, - 0x69ac, 0x6c98, 0x6b94, 0x2200, 0xa105, 0x0120, 0x2200, 0xa422, - 0x2100, 0xa31b, 0x6caa, 0x7cd2, 0x7cda, 0x6ba6, 0x7bd6, 0x7bde, - 0x2300, 0xa405, 0x1130, 0xc6f5, 0x7e5a, 0x6eb6, 0x781b, 0x0080, - 0x0005, 0x781b, 0x0080, 0x2200, 0xa115, 0x1118, 0x080c, 0x3fb8, - 0x0005, 0x080c, 0x3fe5, 0x0005, 0x080c, 0x243b, 0x0804, 0x2cbd, - 0x00c6, 0x7058, 0x2060, 0x7aa8, 0xa294, 0x00ff, 0xa286, 0x0004, - 0x11d8, 0x6920, 0xd1e4, 0x1170, 0x2039, 0x0000, 0x2041, 0x0000, - 0x2031, 0x0000, 0xa006, 0x2010, 0x080c, 0x36f6, 0x080c, 0x379a, - 0x0804, 0x2cb1, 0xa18c, 0xecff, 0x6922, 0x6104, 0xa18c, 0xffdd, - 0x6106, 0x6000, 0xc0ac, 0x6002, 0xa286, 0x0003, 0x01d0, 0x6104, - 0xa18c, 0x0010, 0x0548, 0x080c, 0x3969, 0x080c, 0x3776, 0x88ff, - 0x0518, 0x00ce, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695, - 0x7e5a, 0xd6d4, 0x1118, 0x781b, 0x006e, 0x0005, 0x781b, 0x0082, - 0x0005, 0x6920, 0xd1cc, 0x0130, 0xa18c, 0xfdff, 0x6922, 0x6000, - 0xc0ec, 0x6002, 0x2039, 0x0000, 0x2041, 0x0000, 0x2031, 0x0000, - 0xa006, 0x2010, 0x080c, 0x379a, 0xa286, 0x0001, 0x0158, 0x6104, - 0xa18c, 0x0008, 0x01b0, 0x080c, 0x3969, 0x080c, 0x3696, 0x88ff, - 0x1980, 0x0078, 0x6920, 0xd1c4, 0x0130, 0xa18c, 0xfeff, 0x6922, - 0x6000, 0xc0e4, 0x6002, 0x2031, 0x0000, 0xa006, 0x2010, 0x080c, - 0x36f6, 0x00ce, 0x7e58, 0xd6d4, 0x1118, 0x781b, 0x0071, 0x0005, - 0x781b, 0x0083, 0x0005, 0x0804, 0x382d, 0x2808, 0x789b, 0x0080, - 0x2019, 0x0080, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001, 0x1188, - 0x7ca8, 0xa4a4, 0x00ff, 0xa480, 0x0002, 0xa300, 0x2018, 0xa102, - 0x0a04, 0x2c40, 0x0904, 0x2c40, 0x24a8, 0x7aa8, 0x1f04, 0x2cd5, - 0x0c48, 0xa284, 0x00f0, 0xa082, 0x0020, 0x06b8, 0x2200, 0xa082, - 0x0021, 0x1698, 0x7aa8, 0x8318, 0x8318, 0x2100, 0xa302, 0x0ad0, - 0xa286, 0x0023, 0x0980, 0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58, - 0xa684, 0xfff1, 0xc0a5, 0x2030, 0x7e5a, 0x6008, 0xc0a5, 0x600a, - 0x78a0, 0x8001, 0x0904, 0x2cb1, 0x20a8, 0x7998, 0x789b, 0x0060, - 0x78aa, 0x2011, 0x0080, 0x799a, 0x78a8, 0x7998, 0x7a9a, 0x78aa, - 0x7a98, 0x1f04, 0x2d03, 0xc695, 0x7e5a, 0xd6d4, 0x1118, 0x781b, - 0x006e, 0x0005, 0x781b, 0x0082, 0x0005, 0x8318, 0x2100, 0xa302, - 0x0a04, 0x2cc2, 0xa284, 0x0080, 0x1904, 0x3831, 0x78a0, 0xa005, - 0x08c8, 0x0804, 0x3831, 0x0804, 0x3809, 0x7058, 0xa04d, 0x789b, - 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa08e, 0x0001, 0x0110, 0x080c, - 0x243b, 0x7aa8, 0xa294, 0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a, - 0x0005, 0x1a04, 0x3809, 0x0002, 0x3809, 0x3615, 0x3809, 0x3726, - 0x3b83, 0xa282, 0x0000, 0x1110, 0x080c, 0x243b, 0x080c, 0x3837, - 0x781b, 0x0082, 0x0005, 0xa282, 0x0003, 0x1110, 0x080c, 0x243b, - 0xd4fc, 0x11d0, 0x7064, 0xa005, 0x0110, 0x080c, 0x243b, 0x6f14, - 0x7776, 0xa7bc, 0x8f00, 0x080c, 0x396d, 0x6008, 0xa085, 0x0021, - 0x600a, 0x8738, 0xa784, 0x001f, 0x1db0, 0x080c, 0x383a, 0x7067, - 0x0002, 0x701f, 0x0009, 0x0010, 0x080c, 0x3846, 0x781b, 0x0082, - 0x0005, 0xa282, 0x0004, 0x0310, 0x080c, 0x243b, 0x2300, 0x0002, - 0x2d7b, 0x2eff, 0x2f3b, 0xa286, 0x0003, 0x0560, 0x7200, 0x7cd8, - 0x7ddc, 0x7fd0, 0x71d4, 0xd1b4, 0x00f0, 0x7868, 0xa084, 0x00ff, - 0x11d0, 0xa282, 0x0002, 0x12b8, 0x00d6, 0x783b, 0x8300, 0x781b, - 0x0059, 0x70bc, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, - 0x6898, 0x78d2, 0x78da, 0xc1b4, 0x71d6, 0x7003, 0x0030, 0x00de, - 0x2001, 0x0000, 0x0058, 0x783b, 0x1300, 0x781b, 0x0057, 0x2001, - 0x0000, 0x0020, 0x7200, 0x7cd8, 0x7ddc, 0x7fd0, 0x704a, 0x68a0, - 0xd0ec, 0x0118, 0x6008, 0xc08d, 0x600a, 0xa284, 0x000f, 0x0002, - 0x2ee0, 0x2dc5, 0x2dc2, 0x3012, 0x3085, 0x248f, 0x2dc0, 0x2dc0, - 0x080c, 0x243b, 0x6008, 0xc0d4, 0x600a, 0xd6e4, 0x0120, 0x7048, - 0xa086, 0x0014, 0x11e8, 0x080c, 0x3d52, 0x2009, 0x0000, 0x6818, - 0xd0fc, 0x0108, 0x7048, 0xa086, 0x0014, 0x0168, 0x6818, 0xa086, - 0x0008, 0x1904, 0x2ea2, 0x7858, 0xd09c, 0x0904, 0x2ea2, 0x6820, - 0xd0ac, 0x0904, 0x2ea2, 0x681b, 0x0014, 0x2009, 0x0002, 0x04a8, - 0x7868, 0xa08c, 0x00ff, 0x0588, 0xa186, 0x0008, 0x1158, 0x6008, - 0xc0a4, 0x600a, 0x080c, 0x355f, 0x0540, 0x080c, 0x35c5, 0x080c, - 0x3d52, 0x0060, 0xa186, 0x0028, 0x1500, 0x6018, 0xa005, 0x0d78, - 0x8001, 0x0d68, 0x8001, 0x0d58, 0x601e, 0x0c48, 0x6820, 0xd084, - 0x0904, 0x248f, 0xc084, 0x6822, 0x080c, 0x2580, 0x705c, 0x00c6, - 0x2060, 0x6800, 0x6002, 0x00ce, 0x6004, 0x6802, 0xa005, 0x2d00, - 0x1108, 0x6002, 0x6006, 0x0804, 0x248f, 0x0016, 0x81ff, 0x15e0, - 0x7000, 0xa086, 0x0030, 0x05c0, 0x71d4, 0xd1b4, 0x11e8, 0x7060, - 0xa005, 0x1590, 0x70a4, 0xa086, 0x0001, 0x0570, 0x7003, 0x0000, - 0x0046, 0x0056, 0x0076, 0x0066, 0x00c6, 0x00d6, 0x080c, 0x24b2, - 0x00de, 0x00ce, 0x006e, 0x007e, 0x005e, 0x004e, 0x71d4, 0xd1b4, - 0x11d8, 0x7003, 0x0040, 0x00c0, 0x080c, 0x3a8d, 0x11a8, 0x781b, - 0x0068, 0x00d6, 0x70bc, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, - 0x78de, 0x6898, 0x78d2, 0x78da, 0xc1b4, 0x71d6, 0x7003, 0x0030, - 0x7808, 0xc08d, 0x780a, 0x00de, 0x080c, 0x2f63, 0x001e, 0x81ff, - 0x0904, 0x2ea2, 0xa684, 0xdf00, 0x681e, 0x682b, 0x0000, 0x6f14, - 0xa186, 0x0002, 0x15c0, 0x6818, 0xa086, 0x0014, 0x1130, 0x2008, - 0xd6e4, 0x0118, 0x7868, 0xa08c, 0x00ff, 0x080c, 0x3850, 0x080c, - 0x258b, 0x6820, 0xd0dc, 0x1538, 0x8717, 0xa294, 0x000f, 0x8213, - 0x8213, 0x8213, 0xb284, 0x0600, 0x0118, 0xa290, 0x47c0, 0x0010, - 0xa290, 0x4840, 0xa290, 0x0000, 0x221c, 0xd3c4, 0x0130, 0x8210, - 0x2204, 0xa085, 0x0038, 0x2012, 0x8211, 0xd3d4, 0x0138, 0x68a0, - 0xd0c4, 0x1120, 0x080c, 0x2fcb, 0x0804, 0x248f, 0x6008, 0xc08d, - 0x600a, 0x0008, 0x692a, 0x6916, 0x6818, 0xd0fc, 0x0110, 0x7048, - 0x681a, 0xa68c, 0xdf00, 0x691e, 0x6410, 0x84ff, 0x0168, 0x2009, - 0x4302, 0x2104, 0x8001, 0x200a, 0x8421, 0x6412, 0x1128, 0x2021, - 0x4304, 0x2404, 0xc0a5, 0x2022, 0x6018, 0xa005, 0x0118, 0x8001, - 0x601a, 0x1118, 0x6008, 0xc0a4, 0x600a, 0x6820, 0xd084, 0x1130, - 0x6800, 0xa005, 0x1108, 0x6002, 0x6006, 0x0020, 0x705c, 0x2060, - 0x6800, 0x6002, 0x2061, 0x4300, 0x6887, 0x0103, 0x2d08, 0x206b, - 0x0000, 0x6068, 0xa005, 0x616a, 0x0110, 0x2d02, 0x0008, 0x616e, - 0x7200, 0xa286, 0x0030, 0x0158, 0xa286, 0x0040, 0x1904, 0x248f, - 0x7003, 0x0002, 0x704c, 0x2068, 0x68c4, 0x2060, 0x0005, 0x7003, - 0x0002, 0x70bc, 0xa06d, 0x68bc, 0x7042, 0x70b8, 0xa065, 0x68c0, - 0x705a, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x0005, 0xa282, - 0x0004, 0x0210, 0x080c, 0x243b, 0x2200, 0x0002, 0x2f0a, 0x2f19, - 0x2f25, 0x2f19, 0xa586, 0x1300, 0x0160, 0xa586, 0x8300, 0x1d90, - 0x7003, 0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084, 0xfbef, - 0x600a, 0x7000, 0xa086, 0x0005, 0x0128, 0x080c, 0x3837, 0x781b, - 0x0082, 0x0005, 0x781b, 0x0083, 0x0005, 0x7890, 0x8007, 0x8001, - 0xa084, 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c, 0x00ff, - 0xa186, 0x0003, 0x0128, 0xa186, 0x0000, 0x0110, 0x0804, 0x3809, - 0x781b, 0x0083, 0x0005, 0x6820, 0xc095, 0x6822, 0x82ff, 0x1118, - 0x080c, 0x3837, 0x0030, 0x8211, 0x0110, 0x080c, 0x243b, 0x080c, - 0x3846, 0x781b, 0x0082, 0x0005, 0x080c, 0x3aa0, 0x7830, 0xa084, - 0x00c0, 0x1170, 0x0016, 0x3208, 0xa18c, 0x0800, 0x001e, 0x0118, - 0x0104, 0x2f60, 0x0010, 0x0304, 0x2f60, 0x791a, 0xa006, 0x0005, - 0xa085, 0x0001, 0x0005, 0xa684, 0x0060, 0x1130, 0x682f, 0x0000, - 0x6833, 0x0000, 0x0804, 0x2fca, 0xd6dc, 0x1198, 0x68b4, 0xd0dc, - 0x1180, 0x6998, 0x6a94, 0x692e, 0x6a32, 0x7048, 0xa005, 0x1130, - 0x2200, 0xa105, 0x0904, 0x3d52, 0x704b, 0x0015, 0x0804, 0x3d52, - 0x0005, 0xd6ac, 0x01f0, 0xd6f4, 0x0130, 0x682f, 0x0000, 0x6833, - 0x0000, 0x0804, 0x3d52, 0x68b4, 0xa084, 0x4000, 0xa635, 0xd6f4, - 0x1da0, 0x7048, 0xa005, 0x1110, 0x704b, 0x0015, 0xd6dc, 0x1128, - 0x68b4, 0xd0dc, 0x0110, 0x6ca8, 0x6da4, 0x6c2e, 0x6d32, 0x0804, - 0x3d52, 0xd6f4, 0x0130, 0x682f, 0x0000, 0x6833, 0x0000, 0x0804, - 0x3d52, 0x68b4, 0xa084, 0x4800, 0xa635, 0xd6f4, 0x1da0, 0x7048, - 0xa005, 0x1110, 0x704b, 0x0015, 0x2408, 0x2510, 0x2700, 0x8007, - 0xa084, 0x007f, 0xa108, 0xa291, 0x0000, 0x692e, 0x6a32, 0x2100, - 0xa205, 0x1110, 0x0804, 0x3d52, 0x7000, 0xa086, 0x0006, 0x0110, - 0x0804, 0x3d52, 0x0005, 0x6946, 0x6008, 0xc0cd, 0xd3cc, 0x0108, - 0xc08d, 0x600a, 0x6818, 0x683a, 0x681b, 0x0006, 0x688f, 0x0000, - 0x6893, 0x0000, 0x6a30, 0x692c, 0x6a3e, 0x6942, 0x682f, 0x0003, - 0x6833, 0x0000, 0x6837, 0x0020, 0x6897, 0x0000, 0x689b, 0x0020, - 0x7000, 0x0002, 0x248f, 0x2ffa, 0x2ff4, 0x2ff2, 0x2ff2, 0x2ff2, - 0x2ff2, 0x2ff2, 0x080c, 0x243b, 0x6820, 0xd084, 0x1118, 0x080c, - 0x35ab, 0x0030, 0x705c, 0x2c50, 0x2060, 0x6800, 0x6002, 0x2a60, - 0x3208, 0xa18c, 0x0600, 0x0118, 0x2021, 0x4358, 0x0010, 0x2021, - 0x4398, 0x2404, 0xa005, 0x0110, 0x2020, 0x0cd8, 0x2d22, 0x206b, - 0x0000, 0x0005, 0x080c, 0x35b1, 0x080c, 0x35c5, 0x6008, 0xc0cc, - 0x600a, 0x682b, 0x0000, 0x789b, 0x000e, 0x6f14, 0x6938, 0x691a, - 0x6944, 0x6916, 0x3208, 0xa18c, 0x0600, 0x0118, 0x2009, 0x0000, - 0x0010, 0x2009, 0x0001, 0x080c, 0x40b1, 0xd6dc, 0x0118, 0x691c, - 0xc1ed, 0x691e, 0x6818, 0xd0fc, 0x0148, 0x7868, 0xa08c, 0x00ff, - 0x0118, 0x681b, 0x001e, 0x0010, 0x681b, 0x0000, 0xb284, 0x0600, - 0x1118, 0x2021, 0x4398, 0x0010, 0x2021, 0x4358, 0x6800, 0x2022, - 0x6a3c, 0x6940, 0x6a32, 0x692e, 0x68c0, 0x2060, 0x6000, 0xd0a4, - 0x0580, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x00d6, - 0x00f6, 0x0156, 0x0146, 0x2079, 0x4300, 0x080c, 0x1b35, 0x014e, - 0x015e, 0x00fe, 0x70cc, 0x2010, 0x2009, 0x0101, 0x0026, 0x2204, - 0xa06d, 0x0140, 0x6814, 0xa706, 0x0110, 0x6800, 0x0cc8, 0x6820, - 0xc0d5, 0x6822, 0x002e, 0x8210, 0x8109, 0x1d80, 0x00de, 0x7067, - 0x0003, 0x707f, 0x0000, 0x7776, 0x7083, 0x000f, 0x71d4, 0xc1c4, - 0x71d6, 0x080c, 0x1d3d, 0x0804, 0x248f, 0x7cd8, 0x7ddc, 0x7fd0, - 0x080c, 0x2f63, 0x682b, 0x0000, 0x789b, 0x000e, 0x6f14, 0x080c, - 0x3aa4, 0xa08c, 0x00ff, 0x6916, 0x6818, 0xd0fc, 0x0110, 0x7048, - 0x681a, 0xa68c, 0xdf00, 0x691e, 0x7067, 0x0000, 0x0804, 0x248f, - 0x7000, 0xa005, 0x1110, 0x0804, 0x248f, 0xa006, 0x080c, 0x3d52, - 0x6920, 0xd1ac, 0x1110, 0x681b, 0x0014, 0xa68c, 0xdf00, 0x691e, - 0x682b, 0x0000, 0x6820, 0xa084, 0x00ff, 0x6822, 0x7000, 0x0002, - 0x248f, 0x30c2, 0x30c2, 0x30c5, 0x30c5, 0x30c5, 0x30c0, 0x30c0, - 0x080c, 0x243b, 0x6818, 0x0804, 0x2daa, 0x6008, 0xc0a4, 0x600a, - 0x6817, 0x0000, 0x0804, 0x357a, 0x2300, 0x0002, 0x30d1, 0x30d3, - 0x3110, 0x080c, 0x243b, 0xd6fc, 0x1904, 0x2bee, 0x7000, 0xa00d, - 0x0002, 0x248f, 0x30e3, 0x30e3, 0x3104, 0x30e3, 0x310d, 0x30e1, - 0x30e1, 0x080c, 0x243b, 0xa684, 0x0060, 0xa086, 0x0060, 0x11d0, - 0xc6ac, 0xc6f4, 0xc6ed, 0x7e5a, 0x681c, 0xc0ac, 0x681e, 0xa186, - 0x0002, 0x0110, 0x080c, 0x3d52, 0x080c, 0x3fb8, 0x781b, 0x0083, - 0x71d4, 0xd1b4, 0x1904, 0x248c, 0x70a4, 0xa086, 0x0001, 0x1904, - 0x24ce, 0x0005, 0xd6ec, 0x0d30, 0x6818, 0xd0fc, 0x0130, 0x681b, - 0x0015, 0xd6f4, 0x0110, 0x681b, 0x0007, 0x080c, 0x3a4b, 0x0005, - 0x080c, 0x243b, 0x2300, 0x0002, 0x3119, 0x3134, 0x3182, 0x080c, - 0x243b, 0x7000, 0x0002, 0x3123, 0x3125, 0x3125, 0x3123, 0x3123, - 0x3123, 0x3123, 0x3123, 0x080c, 0x243b, 0x080c, 0x3fb8, 0x681c, - 0xc0b4, 0x681e, 0x70d4, 0xd0b4, 0x1904, 0x248c, 0x70a4, 0xa086, - 0x0001, 0x1904, 0x24ce, 0x0005, 0xd6fc, 0x15e0, 0x7000, 0xa00d, - 0x0002, 0x248f, 0x3149, 0x3143, 0x316a, 0x3149, 0x316f, 0x3141, - 0x3141, 0x080c, 0x243b, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, - 0x78da, 0xa684, 0x0060, 0xa086, 0x0060, 0x11d0, 0xa6b4, 0xbfbf, - 0xc6ed, 0x7e5a, 0xa186, 0x0002, 0x0110, 0x080c, 0x3d52, 0x080c, - 0x3fb8, 0x781b, 0x0083, 0x681c, 0xc0b4, 0x681e, 0x71d4, 0xd1b4, - 0x1904, 0x248c, 0x70a4, 0xa086, 0x0001, 0x1904, 0x24ce, 0x0005, - 0xd6ec, 0x0d30, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x0007, 0x781b, - 0x00fb, 0x0005, 0xc6fc, 0x7e5a, 0x7adc, 0x79d8, 0x6b98, 0x2100, - 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x79d2, 0x781b, - 0x0083, 0x0005, 0xd6dc, 0x0130, 0x782b, 0x3009, 0x781b, 0x0083, - 0x0804, 0x248c, 0x7884, 0xc0ac, 0x7886, 0x78e4, 0xa084, 0x0008, - 0x1150, 0xa484, 0x0200, 0x0108, 0xc6f5, 0xc6dd, 0x7e5a, 0x781b, - 0x0083, 0x0804, 0x248c, 0x6820, 0xc095, 0x6822, 0x080c, 0x39ca, - 0xc6dd, 0x080c, 0x3837, 0x781b, 0x0082, 0x0804, 0x248c, 0x2300, - 0x0002, 0x31ac, 0x31ae, 0x31b0, 0x080c, 0x243b, 0x0804, 0x3831, - 0x7d98, 0xd6d4, 0x11f8, 0x79e4, 0xd1ac, 0x0130, 0x78ec, 0xa084, - 0x0003, 0x0110, 0x782b, 0x3009, 0x789b, 0x0060, 0x78ab, 0x0000, - 0xa684, 0xfffb, 0x785a, 0x7d9a, 0x79e4, 0xd1ac, 0x0120, 0x78ec, - 0xa084, 0x0003, 0x1120, 0x2001, 0x0014, 0x0804, 0x2daa, 0xa184, - 0x0007, 0x04c2, 0x7a90, 0xa294, 0x0007, 0x789b, 0x0060, 0x79a8, - 0x81ff, 0x0568, 0x789b, 0x0080, 0x7ba8, 0xa384, 0x0001, 0x11d0, - 0x7ba8, 0x7ba8, 0xa386, 0x0004, 0x1118, 0x2009, 0xffdf, 0x0058, - 0xa386, 0x0001, 0x1118, 0x2009, 0xfff7, 0x0028, 0xa386, 0x0003, - 0x1148, 0x2009, 0xffef, 0x00c6, 0x7058, 0x2060, 0x6004, 0xa104, - 0x6006, 0x00ce, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, - 0x785a, 0x782b, 0x3009, 0x6920, 0xa18c, 0xecff, 0x6922, 0x7d9a, - 0x0804, 0x3a3f, 0x2a9f, 0x2aa8, 0x3214, 0x321a, 0x3212, 0x3212, - 0x3a3f, 0x3a3f, 0x080c, 0x243b, 0x6920, 0xa18c, 0xfcff, 0x6922, - 0x0804, 0x3a45, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0804, 0x3a3f, - 0x79e4, 0xa184, 0x0030, 0x0120, 0x78ec, 0xa084, 0x0003, 0x1558, - 0x7000, 0xa086, 0x0004, 0x1190, 0x7064, 0xa086, 0x0002, 0x1130, - 0x2011, 0x0002, 0x2019, 0x0000, 0x0804, 0x295c, 0x7064, 0xa086, - 0x0006, 0x0db0, 0x7064, 0xa086, 0x0004, 0x0d90, 0x7000, 0xa086, - 0x0000, 0x0904, 0x248c, 0x6920, 0xa184, 0x0420, 0x0128, 0xc1d4, - 0x6922, 0x6818, 0x0804, 0x2daa, 0x6818, 0xc0fd, 0x681a, 0x2001, - 0x0014, 0x0804, 0x2daa, 0xa184, 0x0007, 0x0002, 0x3a3f, 0x3a3f, - 0x325e, 0x3a3f, 0x3a83, 0x3a83, 0x3a3f, 0x3a3f, 0xd6bc, 0x0570, - 0x7184, 0x81ff, 0x0558, 0xa182, 0x000d, 0x1318, 0x7087, 0x0000, - 0x0028, 0xa182, 0x000c, 0x7086, 0x2009, 0x000c, 0x789b, 0x0061, - 0x79aa, 0x0156, 0x0136, 0x0146, 0x7088, 0x8114, 0xa210, 0x728a, - 0xa080, 0x000b, 0xad00, 0x2098, 0xb284, 0x0600, 0x0118, 0x20a1, - 0x022b, 0x0010, 0x20a1, 0x012b, 0x789b, 0x0000, 0x8108, 0x81ac, - 0x53a6, 0x014e, 0x013e, 0x015e, 0x0804, 0x3a45, 0xd6d4, 0x1904, - 0x32d1, 0x6820, 0xd084, 0x0904, 0x3a45, 0xa68c, 0x0060, 0xa684, - 0x0060, 0x0120, 0xa086, 0x0060, 0x1108, 0xc1f5, 0xc194, 0x795a, - 0x69b6, 0x789b, 0x0060, 0x78ab, 0x0000, 0x789b, 0x0061, 0x6818, - 0xc0fd, 0x681a, 0x78aa, 0x8008, 0x810c, 0x0904, 0x35da, 0xa18c, - 0x00f8, 0x1904, 0x35da, 0x0156, 0x0136, 0x0146, 0x0016, 0x20a1, - 0x012b, 0x3208, 0xa18c, 0x0600, 0x0110, 0x20a1, 0x022b, 0x001e, - 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, - 0x014e, 0x013e, 0x015e, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x0804, - 0x3a45, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x0008, 0x080c, 0x3837, - 0x781b, 0x00ed, 0x0005, 0x2300, 0x0002, 0x32e2, 0x3398, 0x32e0, - 0x080c, 0x243b, 0x7cd8, 0x7ddc, 0x7fd0, 0x82ff, 0x11f0, 0x7200, - 0xa286, 0x0003, 0x0904, 0x2d7f, 0x71d4, 0xd1b4, 0x00c0, 0x00d6, - 0x783b, 0x8800, 0x781b, 0x0059, 0x70bc, 0xa06d, 0x68b4, 0xc0a5, - 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0xc1b4, - 0x71d6, 0x7003, 0x0030, 0x00de, 0x0030, 0x7200, 0x0020, 0x783b, - 0x1800, 0x781b, 0x0057, 0xa284, 0x000f, 0x0002, 0x3383, 0x3344, - 0x3318, 0x2da7, 0x3316, 0x3383, 0x3316, 0x3316, 0x080c, 0x243b, - 0x681c, 0xd0ec, 0x0118, 0x6008, 0xc08d, 0x600a, 0x6920, 0xc185, - 0x6922, 0x6800, 0x6006, 0xa005, 0x1108, 0x6002, 0x6008, 0xc0d4, - 0x600a, 0x681c, 0xa084, 0x000e, 0x1148, 0xb284, 0x0600, 0x0118, - 0x2009, 0x89c0, 0x0040, 0x2009, 0x8ad0, 0x0028, 0x7030, 0x68ba, - 0x7140, 0x70cc, 0xa108, 0x2104, 0x6802, 0x2d0a, 0x715e, 0xd6dc, - 0x1118, 0xc6fc, 0x6eb6, 0x04f8, 0x6eb6, 0xa684, 0x0060, 0x05d8, + 0xa084, 0x00ff, 0xa205, 0x6822, 0x080c, 0x1d89, 0x2021, 0x4502, + 0x241c, 0x8319, 0x2322, 0x6010, 0x8001, 0x6012, 0x1128, 0x2021, + 0x4504, 0x2404, 0xc0a5, 0x2022, 0x6008, 0xa084, 0xf9ef, 0x600a, + 0x080c, 0x267d, 0x080c, 0x3786, 0x0005, 0xa085, 0x0001, 0x0ce0, + 0x2300, 0x0002, 0x2b47, 0x2b45, 0x2bad, 0x080c, 0x252b, 0x78e4, + 0xa005, 0x1708, 0x3208, 0xa18c, 0x0800, 0x0118, 0x0104, 0x257c, + 0x0010, 0x0304, 0x257c, 0x2008, 0xa084, 0x0030, 0x1110, 0x0804, + 0x31c5, 0x78ec, 0xa084, 0x0003, 0x0dd0, 0x2100, 0xa084, 0x0007, + 0x0002, 0x2b90, 0x2b99, 0x2b86, 0x2b69, 0x3bef, 0x3bef, 0x2b69, + 0x2ba3, 0x080c, 0x252b, 0x7000, 0xa086, 0x0004, 0x1190, 0x7060, + 0xa086, 0x0002, 0x1130, 0x2011, 0x0002, 0x2019, 0x0000, 0x0804, + 0x2a4d, 0x7060, 0xa086, 0x0006, 0x0db0, 0x7060, 0xa086, 0x0004, + 0x0d90, 0x79e4, 0x2001, 0x0003, 0x0804, 0x2ea4, 0x6818, 0xd0fc, + 0x0110, 0x681b, 0x001d, 0x080c, 0x39ff, 0x781b, 0x006e, 0x0005, + 0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c, 0x39ff, 0x0804, + 0x3bcd, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c, 0x39ff, + 0x781b, 0x00fa, 0x0005, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d, + 0x080c, 0x39ff, 0x781b, 0x00cb, 0x0005, 0xa584, 0x000f, 0x11c0, + 0x7000, 0x0002, 0x257f, 0x2bba, 0x2bbc, 0x3725, 0x3725, 0x3725, + 0x2bba, 0x2bba, 0x080c, 0x252b, 0x080c, 0x3786, 0x6008, 0xa084, + 0xfbef, 0x600a, 0x080c, 0x3717, 0x0904, 0x3725, 0x0804, 0x257f, + 0x78e4, 0xa005, 0x1b04, 0x2b6b, 0x3208, 0xa18c, 0x0800, 0x0118, + 0x0104, 0x2b6b, 0x0010, 0x0304, 0x2b6b, 0x2008, 0xa084, 0x0030, + 0x1118, 0x781b, 0x0068, 0x0005, 0x78ec, 0xa084, 0x0003, 0x0dc8, + 0x2100, 0xa184, 0x0007, 0x0002, 0x2bf3, 0x2bf7, 0x2bee, 0x2bec, + 0x3bef, 0x3bef, 0x2bec, 0x3be9, 0x080c, 0x252b, 0x080c, 0x3a05, + 0x781b, 0x006e, 0x0005, 0x080c, 0x3a05, 0x0804, 0x3bcd, 0x080c, + 0x3a05, 0x781b, 0x00fa, 0x0005, 0x080c, 0x3a05, 0x781b, 0x00cb, + 0x0005, 0x2300, 0x0002, 0x2c08, 0x2c06, 0x2c0a, 0x080c, 0x252b, + 0x0804, 0x3361, 0x681b, 0x0016, 0x78a3, 0x0000, 0x79e4, 0xa184, + 0x0030, 0x0904, 0x3361, 0x78ec, 0xa084, 0x0003, 0x0904, 0x3361, + 0xa184, 0x0100, 0x0d98, 0xa184, 0x0007, 0x0002, 0x2c26, 0x2bf7, + 0x2b86, 0x3bab, 0x3bef, 0x3bef, 0x3bab, 0x3be9, 0x080c, 0x3bb7, + 0x0005, 0xa282, 0x0005, 0x0310, 0x080c, 0x252b, 0x7898, 0x2040, + 0x2300, 0x0002, 0x2c35, 0x2e34, 0x2e3e, 0x2200, 0x0002, 0x2c51, + 0x2c3e, 0x2c51, 0x2c3c, 0x2e16, 0x080c, 0x252b, 0x789b, 0x0018, + 0x78a8, 0x2010, 0xa084, 0x00ff, 0xa082, 0x0020, 0x0a04, 0x39d0, + 0xa08a, 0x0004, 0x1a04, 0x39d0, 0x0002, 0x39d0, 0x39d0, 0x39d0, + 0x3986, 0x789b, 0x0018, 0x79a8, 0xa184, 0x0080, 0x0148, 0x0804, + 0x39d0, 0x7000, 0xa005, 0x1dd8, 0x2011, 0x0004, 0x0804, 0x3502, + 0xa184, 0x00ff, 0xa08a, 0x0010, 0x1a04, 0x39d0, 0x0002, 0x2c79, + 0x2c77, 0x2c8b, 0x2c8f, 0x2d2d, 0x39d0, 0x39d0, 0x2d2f, 0x39d0, + 0x39d0, 0x2e12, 0x2e12, 0x39d0, 0x39d0, 0x39d0, 0x2e14, 0x080c, + 0x252b, 0xd6e4, 0x0140, 0x2001, 0x0300, 0x8000, 0x8000, 0x783a, + 0x781b, 0x00c7, 0x0005, 0x6818, 0xd0fc, 0x0118, 0x681b, 0x001d, + 0x0c90, 0x0804, 0x3bab, 0x681b, 0x001d, 0x0804, 0x39f9, 0x6920, + 0x6922, 0xa684, 0x1800, 0x15e0, 0x6820, 0xd084, 0x1904, 0x2cd8, + 0x6818, 0xa086, 0x0008, 0x1110, 0x681b, 0x0000, 0xd6d4, 0x0568, + 0xd6bc, 0x0558, 0x7083, 0x0000, 0x6818, 0xa084, 0x003f, 0xa08a, + 0x000d, 0x0718, 0xa08a, 0x000c, 0x7182, 0x2001, 0x000c, 0x800c, + 0x7186, 0x789b, 0x0061, 0x78aa, 0x0156, 0x0136, 0x0146, 0x0016, + 0x3208, 0xa18c, 0x0600, 0x0118, 0x20a1, 0x022b, 0x0010, 0x20a1, + 0x012b, 0x001e, 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, + 0x2098, 0x53a6, 0x014e, 0x013e, 0x015e, 0x781b, 0x0071, 0x0005, + 0xd6e4, 0x0130, 0x781b, 0x0083, 0x0005, 0x781b, 0x0083, 0x0005, + 0xa684, 0x0060, 0x0dd0, 0xd6dc, 0x0dc0, 0xd6fc, 0x01a0, 0xc6fc, + 0x7e5a, 0x6eb6, 0x7adc, 0x79d8, 0x78d0, 0x8007, 0xa084, 0x007f, + 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, + 0x2200, 0xa303, 0x68ae, 0xd6f4, 0x0118, 0xc6f4, 0x7e5a, 0x6eb6, + 0x7000, 0xa086, 0x0003, 0x1148, 0x0006, 0x080c, 0x3ed9, 0x080c, + 0x4180, 0x000e, 0x781b, 0x0080, 0x0005, 0xa006, 0x080c, 0x425d, + 0x6ab0, 0x69ac, 0x6c98, 0x6b94, 0x2200, 0xa105, 0x0120, 0x2200, + 0xa422, 0x2100, 0xa31b, 0x6caa, 0x7cd2, 0x7cda, 0x6ba6, 0x7bd6, + 0x7bde, 0x2300, 0xa405, 0x1130, 0xc6f5, 0x7e5a, 0x6eb6, 0x781b, + 0x0080, 0x0005, 0x781b, 0x0080, 0x2200, 0xa115, 0x1118, 0x080c, + 0x4180, 0x0005, 0x080c, 0x41ad, 0x0005, 0x080c, 0x252b, 0x0804, + 0x2dae, 0x00c6, 0x7054, 0x2060, 0x7aa8, 0xa294, 0x00ff, 0xa286, + 0x0004, 0x11d8, 0x6920, 0xd1e4, 0x1170, 0x2039, 0x0000, 0x2041, + 0x0000, 0x2031, 0x0000, 0xa006, 0x2010, 0x080c, 0x38bd, 0x080c, + 0x3961, 0x0804, 0x2da2, 0xa18c, 0xecff, 0x6922, 0x6104, 0xa18c, + 0xffdd, 0x6106, 0x6000, 0xc0ac, 0x6002, 0xa286, 0x0003, 0x01d0, + 0x6104, 0xa184, 0x0010, 0x0548, 0x080c, 0x3b31, 0x080c, 0x393d, + 0x88ff, 0x0518, 0x00ce, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, + 0xc695, 0x7e5a, 0xd6d4, 0x1118, 0x781b, 0x006e, 0x0005, 0x781b, + 0x0082, 0x0005, 0x6920, 0xd1cc, 0x0130, 0xa18c, 0xfdff, 0x6922, + 0x6000, 0xc0ec, 0x6002, 0x2039, 0x0000, 0x2041, 0x0000, 0x2031, + 0x0000, 0xa006, 0x2010, 0x080c, 0x3961, 0xa286, 0x0001, 0x0158, + 0x6104, 0xa184, 0x0008, 0x01b0, 0x080c, 0x3b31, 0x080c, 0x385d, + 0x88ff, 0x1980, 0x0078, 0x6920, 0xd1c4, 0x0130, 0xa18c, 0xfeff, + 0x6922, 0x6000, 0xc0e4, 0x6002, 0x2031, 0x0000, 0xa006, 0x2010, + 0x080c, 0x38bd, 0x00ce, 0x7e58, 0xd6d4, 0x1118, 0x781b, 0x0071, + 0x0005, 0x781b, 0x0083, 0x0005, 0x0804, 0x39f5, 0x2808, 0x789b, + 0x0080, 0x2019, 0x0080, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001, + 0x1188, 0x7ca8, 0xa4a4, 0x00ff, 0xa480, 0x0002, 0xa300, 0x2018, + 0xa102, 0x0a04, 0x2d31, 0x0904, 0x2d31, 0x24a8, 0x7aa8, 0x1f04, + 0x2dc6, 0x0c48, 0xa284, 0x00f0, 0xa082, 0x0020, 0x06b8, 0x2200, + 0xa082, 0x0021, 0x1698, 0x7aa8, 0x8318, 0x8318, 0x2100, 0xa302, + 0x0ad0, 0xa286, 0x0023, 0x0980, 0x681c, 0xa084, 0xfff1, 0x681e, + 0x7e58, 0xa684, 0xfff1, 0xc0a5, 0x2030, 0x7e5a, 0x6008, 0xc0a5, + 0x600a, 0x78a0, 0x8001, 0x0904, 0x2da2, 0x20a8, 0x7998, 0x789b, + 0x0060, 0x78aa, 0x2011, 0x0080, 0x799a, 0x78a8, 0x7998, 0x7a9a, + 0x78aa, 0x7a98, 0x1f04, 0x2df4, 0xc695, 0x7e5a, 0xd6d4, 0x1118, + 0x781b, 0x006e, 0x0005, 0x781b, 0x0082, 0x0005, 0x8318, 0x2100, + 0xa302, 0x0a04, 0x2db3, 0xa284, 0x0080, 0x1904, 0x39f9, 0x78a0, + 0xa005, 0x08c8, 0x0804, 0x39f9, 0x0804, 0x39d0, 0x7054, 0xa04d, + 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa08e, 0x0001, 0x0110, + 0x080c, 0x252b, 0x7aa8, 0xa294, 0x00ff, 0x784b, 0x0008, 0x78a8, + 0xa084, 0x00ff, 0xa08a, 0x0005, 0x1a04, 0x39d0, 0x0002, 0x39d0, + 0x37d4, 0x39d0, 0x38ed, 0x3cef, 0xa282, 0x0000, 0x1110, 0x080c, + 0x252b, 0x080c, 0x39ff, 0x781b, 0x0082, 0x0005, 0xa282, 0x0003, + 0x1110, 0x080c, 0x252b, 0xd4fc, 0x11d0, 0x7060, 0xa005, 0x0110, + 0x080c, 0x252b, 0x6f14, 0x7772, 0xa7bc, 0x8f00, 0x080c, 0x3b35, + 0x6008, 0xa085, 0x0021, 0x600a, 0x8738, 0xa784, 0x001f, 0x1db0, + 0x080c, 0x3a02, 0x7063, 0x0002, 0x701f, 0x0009, 0x0010, 0x080c, + 0x3a0e, 0x781b, 0x0082, 0x0005, 0xa282, 0x0004, 0x0310, 0x080c, + 0x252b, 0x2300, 0x0002, 0x2e6e, 0x3004, 0x3040, 0xa286, 0x0003, + 0x0598, 0x7200, 0x7cd8, 0x7ddc, 0x7fd0, 0x71d0, 0xd1bc, 0x1528, + 0xd1b4, 0x0518, 0x2001, 0x4501, 0x2004, 0xd0c4, 0x11f0, 0x7868, + 0xa084, 0x00ff, 0x11d0, 0xa282, 0x0002, 0x12b8, 0x00d6, 0x783b, + 0x8300, 0x781b, 0x0059, 0x70b8, 0xa06d, 0x68b4, 0x785a, 0x6894, + 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0xc1b4, 0x71d2, 0x7003, + 0x0030, 0x00de, 0x2001, 0x0000, 0x0058, 0x783b, 0x1300, 0x781b, + 0x0057, 0x2001, 0x0000, 0x0020, 0x7200, 0x7cd8, 0x7ddc, 0x7fd0, + 0x7046, 0x68a0, 0xd0ec, 0x0118, 0x6008, 0xc08d, 0x600a, 0xa284, + 0x000f, 0x0002, 0x2fe5, 0x2ebf, 0x2ebc, 0x3117, 0x31aa, 0x257f, + 0x2eba, 0x2eba, 0x080c, 0x252b, 0x6008, 0xc0d4, 0x600a, 0xd6e4, + 0x0120, 0x7044, 0xa086, 0x0014, 0x11e8, 0x080c, 0x3ed9, 0x2009, + 0x0000, 0x6818, 0xd0fc, 0x0108, 0x7044, 0xa086, 0x0014, 0x0168, + 0x6818, 0xa086, 0x0008, 0x1904, 0x2fa7, 0x7858, 0xd09c, 0x0904, + 0x2fa7, 0x6820, 0xd0ac, 0x0904, 0x2fa7, 0x681b, 0x0014, 0x2009, + 0x0002, 0x04a8, 0x7868, 0xa08c, 0x00ff, 0x0588, 0xa186, 0x0008, + 0x1158, 0x6008, 0xc0a4, 0x600a, 0x080c, 0x3717, 0x0540, 0x080c, + 0x3786, 0x080c, 0x3ed9, 0x0060, 0xa186, 0x0028, 0x1500, 0x6018, + 0xa005, 0x0d78, 0x8001, 0x0d68, 0x8001, 0x0d58, 0x601e, 0x0c48, + 0x6820, 0xd084, 0x0904, 0x257f, 0xc084, 0x6822, 0x080c, 0x2672, + 0x7058, 0x00c6, 0x2060, 0x6800, 0x6002, 0x00ce, 0x6004, 0x6802, + 0xa005, 0x2d00, 0x1108, 0x6002, 0x6006, 0x0804, 0x257f, 0x0016, + 0x81ff, 0x15f0, 0x7000, 0xa086, 0x0030, 0x05d0, 0x71d0, 0xd1bc, + 0x15b8, 0xd1b4, 0x11e8, 0x705c, 0xa005, 0x1590, 0x70a0, 0xa086, + 0x0001, 0x0570, 0x7003, 0x0000, 0x0046, 0x0056, 0x0076, 0x0066, + 0x00c6, 0x00d6, 0x080c, 0x25a4, 0x00de, 0x00ce, 0x006e, 0x007e, + 0x005e, 0x004e, 0x71d0, 0xd1b4, 0x11d8, 0x7003, 0x0040, 0x00c0, + 0x080c, 0x3bf9, 0x11a8, 0x781b, 0x0068, 0x00d6, 0x70b8, 0xa06d, + 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, + 0xc1b4, 0x71d2, 0x7003, 0x0030, 0x7808, 0xc08d, 0x780a, 0x00de, + 0x080c, 0x3068, 0x001e, 0x81ff, 0x0904, 0x2fa7, 0xa684, 0xdf00, + 0x681e, 0x682b, 0x0000, 0x6f14, 0xa186, 0x0002, 0x1904, 0x2fa8, + 0x6818, 0xa086, 0x0014, 0x1130, 0x2008, 0xd6e4, 0x0118, 0x7868, + 0xa08c, 0x00ff, 0x080c, 0x3a18, 0x080c, 0x267d, 0x6820, 0xd0dc, + 0x1578, 0x8717, 0xa294, 0x000f, 0x8213, 0x8213, 0x8213, 0xb284, + 0x0600, 0x0118, 0xa290, 0x49c0, 0x0010, 0xa290, 0x4a40, 0xa290, + 0x0000, 0x221c, 0xd3c4, 0x0170, 0x6820, 0xd0e4, 0x0128, 0xa084, + 0xefff, 0x6822, 0xc3ac, 0x2312, 0x8210, 0x2204, 0xa085, 0x0038, + 0x2012, 0x8211, 0xd3d4, 0x0138, 0x68a0, 0xd0c4, 0x1120, 0x080c, + 0x30d0, 0x0804, 0x257f, 0x6008, 0xc08d, 0x600a, 0x0008, 0x692a, + 0x6916, 0x6818, 0xd0fc, 0x0110, 0x7044, 0x681a, 0xa68c, 0xdf00, + 0x691e, 0x6410, 0x84ff, 0x0168, 0x2009, 0x4502, 0x2104, 0x8001, + 0x200a, 0x8421, 0x6412, 0x1128, 0x2021, 0x4504, 0x2404, 0xc0a5, + 0x2022, 0x6018, 0xa005, 0x0118, 0x8001, 0x601a, 0x1118, 0x6008, + 0xc0a4, 0x600a, 0x6820, 0xd084, 0x1130, 0x6800, 0xa005, 0x1108, + 0x6002, 0x6006, 0x0020, 0x7058, 0x2060, 0x6800, 0x6002, 0x2061, + 0x4500, 0x6887, 0x0103, 0x2d08, 0x206b, 0x0000, 0x6068, 0xa005, + 0x616a, 0x0110, 0x2d02, 0x0008, 0x616e, 0x7200, 0xa286, 0x0030, + 0x0158, 0xa286, 0x0040, 0x1904, 0x257f, 0x7003, 0x0002, 0x7048, + 0x2068, 0x68c4, 0x2060, 0x0005, 0x7003, 0x0002, 0x70b8, 0xa06d, + 0x68bc, 0x703e, 0x70b4, 0xa065, 0x68c0, 0x7056, 0x2d00, 0x704a, + 0xad80, 0x0009, 0x7042, 0x0005, 0xa282, 0x0004, 0x0210, 0x080c, + 0x252b, 0x2200, 0x0002, 0x300f, 0x301e, 0x302a, 0x301e, 0xa586, + 0x1300, 0x0160, 0xa586, 0x8300, 0x1d90, 0x7003, 0x0000, 0x6018, + 0x8001, 0x601a, 0x6008, 0xa084, 0xfbef, 0x600a, 0x7000, 0xa086, + 0x0005, 0x0128, 0x080c, 0x39ff, 0x781b, 0x0082, 0x0005, 0x781b, + 0x0083, 0x0005, 0x7890, 0x8007, 0x8001, 0xa084, 0x0007, 0xa080, + 0x0018, 0x789a, 0x79a8, 0xa18c, 0x00ff, 0xa186, 0x0003, 0x0128, + 0xa186, 0x0000, 0x0110, 0x0804, 0x39d0, 0x781b, 0x0083, 0x0005, + 0x6820, 0xc095, 0x6822, 0x82ff, 0x1118, 0x080c, 0x39ff, 0x0030, + 0x8211, 0x0110, 0x080c, 0x252b, 0x080c, 0x3a0e, 0x781b, 0x0082, + 0x0005, 0x080c, 0x3c0c, 0x7830, 0xa084, 0x00c0, 0x1170, 0x0016, + 0x3208, 0xa18c, 0x0800, 0x001e, 0x0118, 0x0104, 0x3065, 0x0010, + 0x0304, 0x3065, 0x791a, 0xa006, 0x0005, 0xa085, 0x0001, 0x0005, + 0xa684, 0x0060, 0x1130, 0x682f, 0x0000, 0x6833, 0x0000, 0x0804, + 0x30cf, 0xd6dc, 0x1198, 0x68b4, 0xd0dc, 0x1180, 0x6998, 0x6a94, + 0x692e, 0x6a32, 0x7044, 0xa005, 0x1130, 0x2200, 0xa105, 0x0904, + 0x3ed9, 0x7047, 0x0015, 0x0804, 0x3ed9, 0x0005, 0xd6ac, 0x01f0, + 0xd6f4, 0x0130, 0x682f, 0x0000, 0x6833, 0x0000, 0x0804, 0x3ed9, + 0x68b4, 0xa084, 0x4000, 0xa635, 0xd6f4, 0x1da0, 0x7044, 0xa005, + 0x1110, 0x7047, 0x0015, 0xd6dc, 0x1128, 0x68b4, 0xd0dc, 0x0110, + 0x6ca8, 0x6da4, 0x6c2e, 0x6d32, 0x0804, 0x3ed9, 0xd6f4, 0x0130, + 0x682f, 0x0000, 0x6833, 0x0000, 0x0804, 0x3ed9, 0x68b4, 0xa084, + 0x4800, 0xa635, 0xd6f4, 0x1da0, 0x7044, 0xa005, 0x1110, 0x7047, + 0x0015, 0x2408, 0x2510, 0x2700, 0x8007, 0xa084, 0x007f, 0xa108, + 0xa291, 0x0000, 0x692e, 0x6a32, 0x2100, 0xa205, 0x1110, 0x0804, + 0x3ed9, 0x7000, 0xa086, 0x0006, 0x0110, 0x0804, 0x3ed9, 0x0005, + 0x6946, 0x6008, 0xc0cd, 0xd3cc, 0x0108, 0xc08d, 0x600a, 0x6818, + 0x683a, 0x681b, 0x0006, 0x688f, 0x0000, 0x6893, 0x0000, 0x6a30, + 0x692c, 0x6a3e, 0x6942, 0x682f, 0x0003, 0x6833, 0x0000, 0x6837, + 0x0020, 0x6897, 0x0000, 0x689b, 0x0020, 0x7000, 0x0002, 0x257f, + 0x30ff, 0x30f9, 0x30f7, 0x30f7, 0x30f7, 0x30f7, 0x30f7, 0x080c, + 0x252b, 0x6820, 0xd084, 0x1118, 0x080c, 0x376c, 0x0030, 0x7058, + 0x2c50, 0x2060, 0x6800, 0x6002, 0x2a60, 0x3208, 0xa18c, 0x0600, + 0x0118, 0x2021, 0x4557, 0x0010, 0x2021, 0x4597, 0x2404, 0xa005, + 0x0110, 0x2020, 0x0cd8, 0x2d22, 0x206b, 0x0000, 0x0005, 0x080c, + 0x3772, 0x080c, 0x3786, 0x6008, 0xc0cc, 0x600a, 0x682b, 0x0000, + 0x789b, 0x000e, 0x6f14, 0x6938, 0x691a, 0x6944, 0x6916, 0x3208, + 0xa18c, 0x0600, 0x0118, 0x2009, 0x0000, 0x0010, 0x2009, 0x0001, + 0x080c, 0x428b, 0xd6dc, 0x01c8, 0x691c, 0xc1ed, 0x691e, 0x6828, + 0xa082, 0x000e, 0x0290, 0x6848, 0xa084, 0x000f, 0xa086, 0x000b, + 0x1160, 0x685c, 0xa086, 0x0047, 0x1140, 0x2001, 0x4501, 0x2004, + 0xd0ac, 0x1118, 0x2700, 0x080c, 0x2454, 0x6818, 0xd0fc, 0x0140, + 0x681b, 0x0000, 0x7868, 0xa08c, 0x00ff, 0x0110, 0x681b, 0x001e, + 0xb284, 0x0600, 0x1118, 0x2021, 0x4597, 0x0010, 0x2021, 0x4557, + 0x6800, 0x2022, 0x6a3c, 0x6940, 0x6a32, 0x692e, 0x68c0, 0x2060, + 0x6000, 0xd0a4, 0x0580, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, + 0x0020, 0x00d6, 0x00f6, 0x0156, 0x0146, 0x2079, 0x4500, 0x080c, + 0x1b77, 0x014e, 0x015e, 0x00fe, 0x70c8, 0x2010, 0x2009, 0x0101, + 0x0026, 0x2204, 0xa06d, 0x0140, 0x6814, 0xa706, 0x0110, 0x6800, + 0x0cc8, 0x6820, 0xc0d5, 0x6822, 0x002e, 0x8210, 0x8109, 0x1d80, + 0x00de, 0x7063, 0x0003, 0x707b, 0x0000, 0x7772, 0x707f, 0x000f, + 0x71d0, 0xc1c4, 0x71d2, 0x6818, 0xa086, 0x0002, 0x1138, 0x6817, + 0x0000, 0x682b, 0x0000, 0x681c, 0xc0ec, 0x681e, 0x080c, 0x1d89, + 0x0804, 0x257f, 0x7cd8, 0x7ddc, 0x7fd0, 0x080c, 0x3068, 0x682b, + 0x0000, 0x789b, 0x000e, 0x6f14, 0x080c, 0x3c10, 0xa08c, 0x00ff, + 0x6916, 0x6818, 0xd0fc, 0x0110, 0x7044, 0x681a, 0xa68c, 0xdf00, + 0x691e, 0x7063, 0x0000, 0x0804, 0x257f, 0x7000, 0xa005, 0x1110, + 0x0804, 0x257f, 0xa006, 0x080c, 0x3ed9, 0x6920, 0xd1ac, 0x1110, + 0x681b, 0x0014, 0xa68c, 0xdf00, 0x691e, 0x682b, 0x0000, 0x6820, + 0xa084, 0x00ff, 0x6822, 0x7000, 0x0002, 0x257f, 0x31e7, 0x31e7, + 0x31ea, 0x31ea, 0x31ea, 0x31e5, 0x31e5, 0x080c, 0x252b, 0x6818, + 0x0804, 0x2ea4, 0x6008, 0xc0a4, 0x600a, 0x6817, 0x0000, 0x0804, + 0x373a, 0x2300, 0x0002, 0x31f6, 0x31f8, 0x3241, 0x080c, 0x252b, + 0xd6fc, 0x1904, 0x2cdf, 0x7000, 0xa00d, 0x0002, 0x257f, 0x3208, + 0x3208, 0x3231, 0x3208, 0x323e, 0x3206, 0x3206, 0x080c, 0x252b, + 0xa684, 0x0060, 0x0530, 0xa086, 0x0060, 0x1508, 0xc6ac, 0xc6f4, + 0xc6ed, 0x7e5a, 0x681c, 0xc0ac, 0x681e, 0xa186, 0x0002, 0x0148, + 0x080c, 0x3ed9, 0x69ac, 0x68b0, 0xa115, 0x0118, 0x080c, 0x41ad, + 0x0010, 0x080c, 0x4180, 0x781b, 0x0083, 0x71d0, 0xd1b4, 0x1904, + 0x257c, 0x70a0, 0xa086, 0x0001, 0x1904, 0x25c0, 0x0005, 0xd6ec, + 0x09f8, 0x6818, 0xd0fc, 0x0150, 0xd6f4, 0x1130, 0x681b, 0x0015, + 0x781b, 0x0083, 0x0804, 0x257c, 0x681b, 0x0007, 0x080c, 0x3bb7, + 0x0005, 0x080c, 0x252b, 0x2300, 0x0002, 0x324a, 0x326c, 0x32c3, + 0x080c, 0x252b, 0x7000, 0x0002, 0x3254, 0x3256, 0x325d, 0x3254, + 0x3254, 0x3254, 0x3254, 0x3254, 0x080c, 0x252b, 0x69ac, 0x68b0, + 0xa115, 0x0118, 0x080c, 0x41ad, 0x0010, 0x080c, 0x4180, 0x681c, + 0xc0b4, 0x681e, 0x70d0, 0xd0b4, 0x1904, 0x257c, 0x70a0, 0xa086, + 0x0001, 0x1904, 0x25c0, 0x0005, 0xd6fc, 0x1904, 0x32b3, 0x7000, + 0xa00d, 0x0002, 0x257f, 0x3282, 0x327c, 0x32ab, 0x3282, 0x32b0, + 0x327a, 0x327a, 0x080c, 0x252b, 0x6894, 0x78d6, 0x78de, 0x6898, + 0x78d2, 0x78da, 0xa684, 0x0060, 0x0530, 0xa086, 0x0060, 0x1508, + 0xa6b4, 0xbfbf, 0xc6ed, 0x7e5a, 0xa186, 0x0002, 0x0148, 0x080c, + 0x3ed9, 0x69ac, 0x68b0, 0xa115, 0x0118, 0x080c, 0x41ad, 0x0010, + 0x080c, 0x4180, 0x781b, 0x0083, 0x681c, 0xc0b4, 0x681e, 0x71d0, + 0xd1b4, 0x1904, 0x257c, 0x70a0, 0xa086, 0x0001, 0x1904, 0x25c0, + 0x0005, 0xd6ec, 0x09f8, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x0007, + 0x781b, 0x00fb, 0x0005, 0xc6fc, 0x7e5a, 0x7adc, 0x79d8, 0x6b98, + 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x79d2, + 0x781b, 0x0083, 0x0005, 0xd6dc, 0x0130, 0x782b, 0x3009, 0x781b, + 0x0083, 0x0804, 0x257c, 0x7884, 0xc0ac, 0x7886, 0x78e4, 0xa084, + 0x0008, 0x1150, 0xa484, 0x0200, 0x0108, 0xc6f5, 0xc6dd, 0x7e5a, + 0x781b, 0x0083, 0x0804, 0x257c, 0x6820, 0xc095, 0x6822, 0x080c, + 0x3ba2, 0xc6dd, 0x080c, 0x39ff, 0x781b, 0x0082, 0x0804, 0x257c, + 0x2300, 0x0002, 0x32ed, 0x32ef, 0x32f1, 0x080c, 0x252b, 0x0804, + 0x39f9, 0x7d98, 0xd6d4, 0x11f8, 0x79e4, 0xd1ac, 0x0130, 0x78ec, + 0xa084, 0x0003, 0x0110, 0x782b, 0x3009, 0x789b, 0x0060, 0x78ab, + 0x0000, 0xa684, 0xfffb, 0x785a, 0x7d9a, 0x79e4, 0xd1ac, 0x0120, + 0x78ec, 0xa084, 0x0003, 0x1120, 0x2001, 0x0014, 0x0804, 0x2ea4, + 0xa184, 0x0007, 0x04c2, 0x7a90, 0xa294, 0x0007, 0x789b, 0x0060, + 0x79a8, 0x81ff, 0x0568, 0x789b, 0x0080, 0x7ba8, 0xa384, 0x0001, + 0x11d0, 0x7ba8, 0x7ba8, 0xa386, 0x0004, 0x1118, 0x2009, 0xffdf, + 0x0058, 0xa386, 0x0001, 0x1118, 0x2009, 0xfff7, 0x0028, 0xa386, + 0x0003, 0x1148, 0x2009, 0xffef, 0x00c6, 0x7054, 0x2060, 0x6004, + 0xa104, 0x6006, 0x00ce, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, + 0xfffb, 0x785a, 0x782b, 0x3009, 0x6920, 0xa18c, 0xecff, 0x6922, + 0x7d9a, 0x0804, 0x3bab, 0x2b90, 0x2b99, 0x3355, 0x335b, 0x3353, + 0x3353, 0x3bab, 0x3bab, 0x080c, 0x252b, 0x6920, 0xa18c, 0xfcff, + 0x6922, 0x0804, 0x3bb1, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0804, + 0x3bab, 0x79e4, 0xa184, 0x0030, 0x0120, 0x78ec, 0xa084, 0x0003, + 0x1570, 0x7000, 0xa086, 0x0004, 0x1190, 0x7060, 0xa086, 0x0002, + 0x1130, 0x2011, 0x0002, 0x2019, 0x0000, 0x0804, 0x2a4d, 0x7060, + 0xa086, 0x0006, 0x0db0, 0x7060, 0xa086, 0x0004, 0x0d90, 0x7000, + 0xa086, 0x0000, 0x0904, 0x257c, 0x6920, 0xa184, 0x0420, 0x0128, + 0xc1d4, 0x6922, 0x6818, 0x0804, 0x2ea4, 0x6818, 0xa08e, 0x0002, + 0x0120, 0xc0fd, 0x681a, 0x2001, 0x0014, 0x0804, 0x2ea4, 0xa184, + 0x0007, 0x0002, 0x3bab, 0x3bab, 0x33a2, 0x3bab, 0x3bef, 0x3bef, + 0x3bab, 0x3bab, 0xd6bc, 0x0570, 0x7180, 0x81ff, 0x0558, 0xa182, + 0x000d, 0x1318, 0x7083, 0x0000, 0x0028, 0xa182, 0x000c, 0x7082, + 0x2009, 0x000c, 0x789b, 0x0061, 0x79aa, 0x0156, 0x0136, 0x0146, + 0x7084, 0x8114, 0xa210, 0x7286, 0xa080, 0x000b, 0xad00, 0x2098, + 0xb284, 0x0600, 0x0118, 0x20a1, 0x022b, 0x0010, 0x20a1, 0x012b, + 0x789b, 0x0000, 0x8108, 0x81ac, 0x53a6, 0x014e, 0x013e, 0x015e, + 0x0804, 0x3bb1, 0xd6d4, 0x1904, 0x3415, 0x6820, 0xd084, 0x0904, + 0x3bb1, 0xa68c, 0x0060, 0xa684, 0x0060, 0x0120, 0xa086, 0x0060, + 0x1108, 0xc1f5, 0xc194, 0x795a, 0x69b6, 0x789b, 0x0060, 0x78ab, + 0x0000, 0x789b, 0x0061, 0x6818, 0xc0fd, 0x681a, 0x78aa, 0x8008, + 0x810c, 0x0904, 0x379b, 0xa18c, 0x00f8, 0x1904, 0x379b, 0x0156, + 0x0136, 0x0146, 0x0016, 0x20a1, 0x012b, 0x3208, 0xa18c, 0x0600, + 0x0110, 0x20a1, 0x022b, 0x001e, 0x789b, 0x0000, 0x8000, 0x80ac, + 0xad80, 0x000b, 0x2098, 0x53a6, 0x014e, 0x013e, 0x015e, 0x6814, + 0xc0fc, 0x8007, 0x7882, 0x0804, 0x3bb1, 0x6818, 0xd0fc, 0x0110, + 0x681b, 0x0008, 0x080c, 0x39ff, 0x781b, 0x00ed, 0x0005, 0x2300, + 0x0002, 0x3426, 0x34e8, 0x3424, 0x080c, 0x252b, 0x7cd8, 0x7ddc, + 0x7fd0, 0x82ff, 0x1528, 0x7200, 0xa286, 0x0003, 0x0904, 0x2e72, + 0x71d0, 0xd1bc, 0x11f8, 0xd1b4, 0x01e8, 0x2001, 0x4501, 0x2004, + 0xd0c4, 0x11c0, 0x00d6, 0x783b, 0x8800, 0x781b, 0x0059, 0x70b8, + 0xa06d, 0x68b4, 0xc0a5, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, + 0x78d2, 0x78da, 0xc1b4, 0x71d2, 0x7003, 0x0030, 0x00de, 0x0030, + 0x7200, 0x0020, 0x783b, 0x1800, 0x781b, 0x0057, 0xa284, 0x000f, + 0x0002, 0x34d3, 0x3490, 0x3463, 0x2ea1, 0x3461, 0x34d3, 0x3461, + 0x3461, 0x080c, 0x252b, 0x681c, 0xd0ec, 0x0118, 0x6008, 0xc08d, + 0x600a, 0x6920, 0xc185, 0x6922, 0x6800, 0x6006, 0xa005, 0x1108, + 0x6002, 0x6008, 0xc0d4, 0x600a, 0x681c, 0xa084, 0x000e, 0x1148, + 0xb284, 0x0600, 0x0118, 0x2009, 0x8bc0, 0x0040, 0x2009, 0x8cd0, + 0x0028, 0x7030, 0x68ba, 0x713c, 0x70c8, 0xa108, 0x2104, 0x6802, + 0x2d0a, 0x715a, 0xd6dc, 0x1120, 0xc6fc, 0x6eb6, 0x0804, 0x34d3, + 0x6eb6, 0xa684, 0x0060, 0x1120, 0xa684, 0x7fff, 0x68b6, 0x04d8, 0xd6dc, 0x1150, 0xa684, 0x7fff, 0x68b6, 0x6894, 0x68a6, 0x6898, - 0x68aa, 0x080c, 0x3d52, 0x0478, 0xd6ac, 0x0140, 0xa006, 0x080c, - 0x3d52, 0x2408, 0x2510, 0x69aa, 0x6aa6, 0x0068, 0x2408, 0x2510, + 0x68aa, 0x080c, 0x3ed9, 0x0478, 0xd6ac, 0x0140, 0xa006, 0x080c, + 0x3ed9, 0x2408, 0x2510, 0x69aa, 0x6aa6, 0x0068, 0x2408, 0x2510, 0x2700, 0x8007, 0xa084, 0x007f, 0xa108, 0xa291, 0x0000, 0x69aa, - 0x6aa6, 0x080c, 0x3d52, 0xd6fc, 0x01b0, 0xa684, 0x7fff, 0x68b6, + 0x6aa6, 0x080c, 0x3ed9, 0xd6fc, 0x01b0, 0xa684, 0x7fff, 0x68b6, 0x2510, 0x2408, 0xd6ac, 0x1138, 0x2700, 0x8007, 0xa084, 0x007f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, - 0x2200, 0xa303, 0x68ae, 0x7000, 0xa086, 0x0030, 0x1904, 0x248f, - 0x7003, 0x0002, 0x70bc, 0xa06d, 0x68bc, 0x7042, 0x70b8, 0xa065, - 0x68c0, 0x705a, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x0005, + 0x2200, 0xa303, 0x68ae, 0x7000, 0xa086, 0x0030, 0x1904, 0x257f, + 0x7003, 0x0002, 0x70b8, 0xa06d, 0x68bc, 0x703e, 0x70b4, 0xa065, + 0x68c0, 0x7056, 0x2d00, 0x704a, 0xad80, 0x0009, 0x7042, 0x0005, 0xa586, 0x8800, 0x1148, 0x7003, 0x0000, 0x6018, 0x8001, 0x601a, - 0x6008, 0xa084, 0xfbef, 0x600a, 0x0804, 0x3831, 0x7047, 0x0000, - 0xa282, 0x0006, 0x0310, 0x080c, 0x243b, 0x2300, 0x0002, 0x33b2, - 0x33e4, 0x340f, 0x2200, 0x0002, 0x33ba, 0x3831, 0x33bc, 0x33ba, - 0x343f, 0x349d, 0x080c, 0x243b, 0x7003, 0x0005, 0xb284, 0x0600, - 0x0118, 0x2001, 0x8ae0, 0x0010, 0x2001, 0x8b12, 0x2068, 0x704e, - 0x0156, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x1f04, 0x33cb, + 0x6008, 0xa084, 0xfbef, 0x600a, 0x0804, 0x39f9, 0x7043, 0x0000, + 0xa282, 0x0006, 0x0310, 0x080c, 0x252b, 0x2300, 0x0002, 0x3502, + 0x3534, 0x355f, 0x2200, 0x0002, 0x350a, 0x39f9, 0x350c, 0x350a, + 0x358f, 0x35f9, 0x080c, 0x252b, 0x7003, 0x0005, 0xb284, 0x0600, + 0x0118, 0x2001, 0x8ce0, 0x0010, 0x2001, 0x8d12, 0x2068, 0x704a, + 0x0156, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x1f04, 0x351b, 0x015e, 0xb284, 0x0600, 0x0118, 0x6817, 0x0000, 0x0010, 0x6817, - 0x8000, 0xad80, 0x0009, 0x7046, 0x68b7, 0x0700, 0x6823, 0x0800, - 0x6827, 0x0003, 0x0804, 0x3809, 0x7000, 0xa086, 0x0002, 0x1150, - 0x080c, 0x35c5, 0x0010, 0x080c, 0x3d52, 0x6008, 0xa084, 0xfbef, + 0x8000, 0xad80, 0x0009, 0x7042, 0x68b7, 0x0700, 0x6823, 0x0800, + 0x6827, 0x0003, 0x0804, 0x39d0, 0x7000, 0xa086, 0x0002, 0x1150, + 0x080c, 0x3786, 0x0010, 0x080c, 0x3ed9, 0x6008, 0xa084, 0xfbef, 0x600a, 0x0020, 0x7000, 0xa086, 0x0003, 0x0da8, 0x7003, 0x0005, - 0xb284, 0x0600, 0x0118, 0x2001, 0x8ae0, 0x0010, 0x2001, 0x8b12, - 0x2068, 0x704e, 0xad80, 0x0009, 0x7046, 0x2200, 0x0002, 0x3831, - 0x340d, 0x340d, 0x343f, 0x340d, 0x3831, 0x080c, 0x243b, 0x7000, - 0xa086, 0x0002, 0x1150, 0x080c, 0x35c5, 0x0010, 0x080c, 0x3d52, + 0xb284, 0x0600, 0x0118, 0x2001, 0x8ce0, 0x0010, 0x2001, 0x8d12, + 0x2068, 0x704a, 0xad80, 0x0009, 0x7042, 0x2200, 0x0002, 0x39f9, + 0x355d, 0x355d, 0x358f, 0x355d, 0x39f9, 0x080c, 0x252b, 0x7000, + 0xa086, 0x0002, 0x1150, 0x080c, 0x3786, 0x0010, 0x080c, 0x3ed9, 0x6008, 0xa084, 0xfbef, 0x600a, 0x0020, 0x7000, 0xa086, 0x0003, - 0x0da8, 0x7003, 0x0005, 0xb284, 0x0600, 0x0118, 0x2001, 0x8ae0, - 0x0010, 0x2001, 0x8b12, 0x2068, 0x704e, 0xad80, 0x0009, 0x7046, - 0x2200, 0x0002, 0x343a, 0x3438, 0x3438, 0x343a, 0x3438, 0x343a, - 0x080c, 0x243b, 0x080c, 0x3846, 0x781b, 0x0082, 0x0005, 0x7000, - 0xa086, 0x0002, 0x1158, 0x70d4, 0xc0b5, 0x70d6, 0x2c00, 0x70ba, - 0x2d00, 0x70be, 0x0038, 0x080c, 0x3d52, 0x0020, 0x7000, 0xa086, + 0x0da8, 0x7003, 0x0005, 0xb284, 0x0600, 0x0118, 0x2001, 0x8ce0, + 0x0010, 0x2001, 0x8d12, 0x2068, 0x704a, 0xad80, 0x0009, 0x7042, + 0x2200, 0x0002, 0x358a, 0x3588, 0x3588, 0x358a, 0x3588, 0x358a, + 0x080c, 0x252b, 0x080c, 0x3a0e, 0x781b, 0x0082, 0x0005, 0x7000, + 0xa086, 0x0002, 0x1158, 0x70d0, 0xc0b5, 0x70d2, 0x2c00, 0x70b6, + 0x2d00, 0x70ba, 0x0038, 0x080c, 0x3ed9, 0x0020, 0x7000, 0xa086, 0x0003, 0x0dc8, 0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00, 0x789b, - 0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215, 0x2069, 0x89c0, 0xb284, - 0x0600, 0x1118, 0xc2fd, 0x2069, 0x8ad0, 0x2d04, 0x2d08, 0x715e, + 0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215, 0x2069, 0x8bc0, 0xb284, + 0x0600, 0x1118, 0xc2fd, 0x2069, 0x8cd0, 0x2d04, 0x2d08, 0x715a, 0xa06d, 0x0128, 0x6814, 0xa206, 0x0500, 0x6800, 0x0cb8, 0x7003, - 0x0005, 0xd2fc, 0x1118, 0x2001, 0x8ae0, 0x0010, 0x2001, 0x8b12, - 0x2068, 0x704e, 0x0156, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, - 0x1f04, 0x347d, 0x015e, 0xad80, 0x0009, 0x7046, 0x6a16, 0x68b7, + 0x0005, 0xd2fc, 0x1118, 0x2001, 0x8ce0, 0x0010, 0x2001, 0x8d12, + 0x2068, 0x704a, 0x0156, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, + 0x1f04, 0x35cd, 0x015e, 0xad80, 0x0009, 0x7042, 0x6a16, 0x68b7, 0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x6eb4, 0x7e5a, 0x6920, - 0xa184, 0x0c00, 0x0904, 0x3507, 0x681b, 0x0005, 0xc1ad, 0xc1d4, - 0x6922, 0x080c, 0x383d, 0x0804, 0x3507, 0x7200, 0xa286, 0x0002, - 0x1158, 0x70d4, 0xc0b5, 0x70d6, 0x2c00, 0x70ba, 0x2d00, 0x70be, - 0x0030, 0x080c, 0x3d52, 0x0018, 0xa286, 0x0003, 0x0dd0, 0x7003, - 0x0001, 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, - 0x001f, 0xa215, 0xb284, 0x0600, 0x1108, 0xc2fd, 0x79a8, 0x79a8, - 0xa18c, 0x00ff, 0x70cc, 0xa168, 0x2d04, 0x2d08, 0x715e, 0xa06d, - 0x0128, 0x6814, 0xa206, 0x0538, 0x6800, 0x0cb8, 0x7003, 0x0005, - 0xb284, 0x0600, 0x0118, 0x2001, 0x8ae0, 0x0010, 0x2001, 0x8b12, - 0x2068, 0x704e, 0x0156, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, - 0x1f04, 0x34dd, 0x015e, 0xb284, 0x0600, 0x0110, 0xc2fc, 0x0008, - 0xc2fd, 0x6a16, 0xad80, 0x0009, 0x7046, 0x68b7, 0x0700, 0x6823, - 0x0800, 0x6827, 0x0003, 0x6eb4, 0x6920, 0xa184, 0x0c00, 0x0178, - 0xd0dc, 0x0118, 0x080c, 0x3843, 0x0050, 0x681b, 0x0005, 0xc1ad, - 0xc1d4, 0x6922, 0x080c, 0x383d, 0x707f, 0x0000, 0x0000, 0xa6ac, - 0x0060, 0x05c8, 0x6b98, 0x6c94, 0x69ac, 0x68b0, 0xa105, 0x11c0, - 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0xa6b4, 0xb7ff, 0xa586, 0x0060, - 0x0550, 0xc6ed, 0x7e5a, 0x2009, 0x0083, 0xd69c, 0x0128, 0x2009, - 0x0082, 0x2019, 0x0000, 0x2320, 0x791a, 0x080c, 0x3fb8, 0x0418, - 0x68b0, 0xa31a, 0x2100, 0xa423, 0x2400, 0xa305, 0x01a0, 0x7bd2, - 0x7bda, 0x7cd6, 0x7cde, 0x68b0, 0xc6f4, 0x7e5a, 0x2011, 0x0083, - 0xd69c, 0x0128, 0x2011, 0x0082, 0x2019, 0x0000, 0x2320, 0x7a1a, - 0x080c, 0x3fe5, 0x0040, 0x7e5a, 0x2009, 0x0083, 0xd69c, 0x0110, - 0x2009, 0x0082, 0x791a, 0x68c0, 0x705a, 0x2d00, 0x704e, 0x68c4, - 0x2060, 0x71d4, 0xd1b4, 0x1904, 0x248c, 0x2300, 0xa405, 0x0904, - 0x248c, 0x70a4, 0xa086, 0x0001, 0x1904, 0x24ce, 0x0005, 0x6020, + 0xa184, 0x0c00, 0x0904, 0x3670, 0x7060, 0xa086, 0x0006, 0x1128, + 0x7070, 0xa206, 0x1110, 0x7062, 0x707a, 0x681b, 0x0005, 0xc1ad, + 0x681b, 0x0005, 0xc1ad, 0xc1d4, 0x6922, 0x080c, 0x3a05, 0x0804, + 0x3670, 0x7200, 0xa286, 0x0002, 0x1158, 0x70d0, 0xc0b5, 0x70d2, + 0x2c00, 0x70b6, 0x2d00, 0x70ba, 0x0030, 0x080c, 0x3ed9, 0x0018, + 0xa286, 0x0003, 0x0dd0, 0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00, + 0x789b, 0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215, 0xb284, 0x0600, + 0x1108, 0xc2fd, 0x79a8, 0x79a8, 0xa18c, 0x00ff, 0x2118, 0x70c8, + 0xa168, 0x2d04, 0x2d08, 0x715a, 0xa06d, 0x0128, 0x6814, 0xa206, + 0x0538, 0x6800, 0x0cb8, 0x7003, 0x0005, 0xb284, 0x0600, 0x0118, + 0x2001, 0x8ce0, 0x0010, 0x2001, 0x8d12, 0x2068, 0x704a, 0x0156, + 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x1f04, 0x363a, 0x015e, + 0xb284, 0x0600, 0x0110, 0xc2fc, 0x0008, 0xc2fd, 0x6a16, 0xad80, + 0x0009, 0x7042, 0x68b7, 0x0700, 0x6823, 0x0800, 0x6827, 0x0003, + 0x6eb4, 0x6920, 0xa184, 0x0c00, 0x01d8, 0xd0dc, 0x0178, 0x7060, + 0xa086, 0x0004, 0x1140, 0x7070, 0xa206, 0x1128, 0x7074, 0xa306, + 0x1110, 0x7062, 0x707a, 0x080c, 0x3a0b, 0x0050, 0x681b, 0x0005, + 0xc1ad, 0xc1d4, 0x6922, 0x080c, 0x3a05, 0x707b, 0x0000, 0x0000, + 0xc6ec, 0xa6ac, 0x0060, 0x0904, 0x36b7, 0x6b98, 0x6c94, 0x69ac, + 0x68b0, 0xa105, 0x11e0, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0xa586, + 0x0060, 0x05c8, 0xd6f4, 0x1108, 0xc6ed, 0xa6b4, 0xb7ff, 0x7e5a, + 0x2009, 0x0083, 0xd69c, 0x0128, 0x2009, 0x0082, 0x2019, 0x0000, + 0x2320, 0x791a, 0xd6ec, 0x0588, 0x080c, 0x4180, 0x0470, 0x68b0, + 0xa31a, 0x2100, 0xa423, 0x2400, 0xa305, 0x01f8, 0x7bd2, 0x7bda, + 0x7cd6, 0x7cde, 0x68b0, 0xd6f4, 0x1108, 0xc6ed, 0xc6f4, 0x7e5a, + 0x2011, 0x0083, 0xd69c, 0x0128, 0x2011, 0x0082, 0x2019, 0x0000, + 0x2320, 0x7a1a, 0xd6ec, 0x0188, 0x080c, 0x41ad, 0x0070, 0x2019, + 0x0000, 0x2320, 0x0010, 0xa6b4, 0xb7ff, 0x7e5a, 0x2009, 0x0083, + 0xd69c, 0x0110, 0x2009, 0x0082, 0x791a, 0x68c0, 0x7056, 0x2d00, + 0x704a, 0x68c4, 0x2060, 0x71d0, 0x2001, 0x4501, 0x2004, 0xd0c4, + 0x15c8, 0x70d4, 0xa02d, 0x01b8, 0xd1bc, 0x0548, 0x7a80, 0xa294, + 0x0f00, 0x70d8, 0xa206, 0x0118, 0x78e0, 0xa504, 0x1558, 0x70d6, + 0xc1bc, 0x71d2, 0x0438, 0x2031, 0x0001, 0x852c, 0x0218, 0x8633, + 0x8210, 0x0cd8, 0x0005, 0x7de0, 0xa594, 0xff00, 0x0130, 0x2011, + 0x0008, 0x852f, 0x0c81, 0x8637, 0x0008, 0x0c69, 0x8217, 0x7880, + 0xa084, 0x0f00, 0xa206, 0x0170, 0x72da, 0x76d6, 0x0058, 0x7a80, + 0xa294, 0x0f00, 0x70d8, 0xa236, 0x0dc0, 0x78e0, 0xa534, 0x0da8, + 0xc1bd, 0x71d2, 0xd1b4, 0x1904, 0x257c, 0x2300, 0xa405, 0x0904, + 0x257c, 0x70a0, 0xa086, 0x0001, 0x1904, 0x25c0, 0x0005, 0x6020, 0xa005, 0x0150, 0x8001, 0x6022, 0x6008, 0xa085, 0x0008, 0x600a, - 0x700f, 0x0100, 0x702c, 0x6026, 0x0005, 0xa006, 0x080c, 0x3d52, + 0x700f, 0x0100, 0x702c, 0x6026, 0x0005, 0xa006, 0x080c, 0x3ed9, + 0x7000, 0xa086, 0x0002, 0x0120, 0x7060, 0xa086, 0x0005, 0x1150, 0x682b, 0x0000, 0x6817, 0x0000, 0x681b, 0x0001, 0x6823, 0x0040, - 0x681f, 0x0100, 0x7000, 0xa084, 0x000f, 0x0002, 0x248f, 0x358b, - 0x3588, 0x35a7, 0x3594, 0x248f, 0x3586, 0x3586, 0x080c, 0x243b, - 0x0441, 0x0409, 0x0028, 0x0429, 0x705c, 0x2060, 0x6800, 0x6002, - 0x080c, 0x1d3d, 0x0804, 0x248f, 0x7064, 0x7067, 0x0000, 0x7083, - 0x0000, 0x0002, 0x35a3, 0x35a3, 0x35a2, 0x35a2, 0x35a2, 0x35a3, - 0x35a2, 0x35a3, 0x2971, 0x7067, 0x0000, 0x0804, 0x248f, 0x681b, - 0x0000, 0x0804, 0x3012, 0x6800, 0xa005, 0x1108, 0x6002, 0x6006, - 0x0005, 0x6410, 0x84ff, 0x0168, 0x2009, 0x4302, 0x2104, 0x8001, - 0x200a, 0x8421, 0x6412, 0x1128, 0x2021, 0x4304, 0x2404, 0xc0a5, - 0x2022, 0x6008, 0xc0a4, 0x600a, 0x0005, 0x6018, 0xa005, 0x0110, - 0x8001, 0x601a, 0x0005, 0x080c, 0x3aa0, 0x681b, 0x0018, 0x04a0, - 0x080c, 0x3aa0, 0x681b, 0x0019, 0x0478, 0x080c, 0x3aa0, 0x681b, - 0x001a, 0x0450, 0x080c, 0x3aa0, 0x681b, 0x0003, 0x0428, 0x7774, - 0x080c, 0x396d, 0x7178, 0xa18c, 0x00ff, 0x3210, 0xa294, 0x0600, - 0x0118, 0xa1e8, 0x88c0, 0x0010, 0xa1e8, 0x89d0, 0x2d04, 0x2d08, - 0x2068, 0xa005, 0x1118, 0x707e, 0x0804, 0x248f, 0x6814, 0xc0fc, - 0x7274, 0xc2fc, 0xa206, 0x0110, 0x6800, 0x0c88, 0x6800, 0x200a, - 0x681b, 0x0005, 0x707f, 0x0000, 0x080c, 0x35b1, 0x6820, 0xd084, - 0x1110, 0x080c, 0x35ab, 0x080c, 0x35c5, 0x681f, 0x0000, 0x6823, - 0x0020, 0x080c, 0x1d3d, 0x0804, 0x248f, 0xa282, 0x0003, 0x1904, - 0x380d, 0x7da8, 0xa5ac, 0x00ff, 0x7ea8, 0xa6b4, 0x00ff, 0x6920, - 0xc1bd, 0x6922, 0xd1c4, 0x0590, 0xc1c4, 0x6922, 0xa6b4, 0x00ff, - 0x0510, 0xa682, 0x001c, 0x0218, 0x0110, 0x2031, 0x001c, 0x852b, - 0x852b, 0x2041, 0x0000, 0x080c, 0x38c6, 0x0118, 0x080c, 0x36f6, - 0x00a0, 0x080c, 0x3892, 0x080c, 0x36f3, 0x6920, 0xc1c5, 0x6922, + 0x681f, 0x0100, 0x7000, 0xa084, 0x000f, 0x0002, 0x257f, 0x374b, + 0x3748, 0x3768, 0x3754, 0x257f, 0x3746, 0x3746, 0x080c, 0x252b, + 0x0449, 0x0411, 0x0028, 0x0431, 0x7058, 0x2060, 0x6800, 0x6002, + 0x080c, 0x1d89, 0x0804, 0x257f, 0x7060, 0x7063, 0x0000, 0x707f, + 0x0000, 0x0002, 0x3764, 0x3764, 0x3762, 0x3762, 0x3762, 0x3764, + 0x3762, 0x3764, 0x0804, 0x2a62, 0x7063, 0x0000, 0x0804, 0x257f, + 0x681b, 0x0000, 0x0804, 0x3117, 0x6800, 0xa005, 0x1108, 0x6002, + 0x6006, 0x0005, 0x6410, 0x84ff, 0x0168, 0x2009, 0x4502, 0x2104, + 0x8001, 0x200a, 0x8421, 0x6412, 0x1128, 0x2021, 0x4504, 0x2404, + 0xc0a5, 0x2022, 0x6008, 0xc0a4, 0x600a, 0x0005, 0x6018, 0xa005, + 0x0110, 0x8001, 0x601a, 0x0005, 0x080c, 0x3c0c, 0x681b, 0x0018, + 0x0490, 0x080c, 0x3c0c, 0x681b, 0x0019, 0x0468, 0x080c, 0x3c0c, + 0x681b, 0x001a, 0x0440, 0x080c, 0x3c0c, 0x681b, 0x0003, 0x0418, + 0x7770, 0x080c, 0x3b35, 0x7174, 0xa18c, 0x00ff, 0x3210, 0xa294, + 0x0600, 0x0118, 0xa1e8, 0x8ac0, 0x0010, 0xa1e8, 0x8bd0, 0x2d04, + 0x2d08, 0x2068, 0xa005, 0x1118, 0x707a, 0x0804, 0x257f, 0x6814, + 0x7270, 0xa206, 0x0110, 0x6800, 0x0c98, 0x6800, 0x200a, 0x681b, + 0x0005, 0x707b, 0x0000, 0x080c, 0x3772, 0x6820, 0xd084, 0x1110, + 0x080c, 0x376c, 0x080c, 0x3786, 0x681f, 0x0000, 0x6823, 0x0020, + 0x080c, 0x1d89, 0x0804, 0x257f, 0xa282, 0x0003, 0x1904, 0x39d5, + 0x7da8, 0xa5ac, 0x00ff, 0x7ea8, 0xa6b4, 0x00ff, 0x6920, 0xc1bd, + 0x6922, 0xd1c4, 0x05b0, 0xc1c4, 0x6922, 0xa6b4, 0x00ff, 0x0530, + 0xa682, 0x001c, 0x0218, 0x0110, 0x2031, 0x001c, 0xa686, 0x0010, + 0x1108, 0x8630, 0x852b, 0x852b, 0x2041, 0x0000, 0x080c, 0x3a8e, + 0x0118, 0x080c, 0x38bd, 0x00a0, 0x080c, 0x3a5a, 0x080c, 0x38ba, + 0x6920, 0xc1c5, 0x6922, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x1118, + 0x781b, 0x006e, 0x0005, 0x781b, 0x0082, 0x0005, 0x080c, 0x38ba, + 0x7e58, 0xd6d4, 0x1118, 0x781b, 0x0071, 0x0005, 0x781b, 0x0083, + 0x0005, 0x00c6, 0x7054, 0x2060, 0x6100, 0xd1e4, 0x0598, 0x6208, + 0x8217, 0xa294, 0x00ff, 0xa282, 0x001c, 0x0218, 0x0110, 0x2011, + 0x001c, 0x2600, 0xa202, 0x1208, 0x2230, 0xa686, 0x0010, 0x1108, + 0x8630, 0x6208, 0xa294, 0x00ff, 0x78ec, 0xd0e4, 0x0130, 0xa282, + 0x000a, 0x1240, 0x2011, 0x000a, 0x0028, 0xa282, 0x000c, 0x1210, + 0x2011, 0x000c, 0x2200, 0xa502, 0x1208, 0x2228, 0x080c, 0x3a5e, + 0x852b, 0x852b, 0x2041, 0x0000, 0x080c, 0x3a8e, 0x0118, 0x080c, + 0x38bd, 0x0020, 0x080c, 0x3a5a, 0x080c, 0x38ba, 0x7858, 0xc095, + 0x785a, 0x00ce, 0x781b, 0x0082, 0x0005, 0x00c6, 0x2960, 0x6000, + 0xd0e4, 0x1178, 0x6010, 0xa084, 0x000f, 0x1130, 0x6104, 0xa18c, + 0xfff5, 0x6106, 0x00ce, 0x0005, 0x2011, 0x0032, 0x2019, 0x0000, + 0x00f0, 0x68a0, 0xd0cc, 0x1dc0, 0x6208, 0xa294, 0x00ff, 0x78ec, + 0xd0e4, 0x0130, 0xa282, 0x000b, 0x1218, 0x2011, 0x000a, 0x0028, + 0xa282, 0x000c, 0x1210, 0x2011, 0x000c, 0x6308, 0x831f, 0xa39c, + 0x00ff, 0xa382, 0x001c, 0x0218, 0x0110, 0x2019, 0x001c, 0x78ab, + 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, + 0x0005, 0x6820, 0xc0c5, 0x6822, 0x080c, 0x3a18, 0x00ce, 0x0005, + 0x00c6, 0x2960, 0x6104, 0xa18c, 0xfff5, 0x6106, 0x2011, 0x0032, + 0x2019, 0x0000, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, + 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xc0c5, 0x6822, + 0x00ce, 0x0005, 0xa006, 0x2030, 0x2010, 0x00c6, 0x7154, 0x2160, + 0x2018, 0x2008, 0xa084, 0xffe0, 0xa635, 0x7e86, 0x6018, 0x789a, + 0x7eae, 0x6612, 0x78a4, 0xa084, 0x7770, 0xa18c, 0x000f, 0xa105, + 0x2029, 0x4505, 0x252c, 0xd5cc, 0x0140, 0xd3a4, 0x0110, 0xa085, + 0x0800, 0xd3fc, 0x0110, 0xa085, 0x8080, 0x78a6, 0x6016, 0x788a, + 0xa6b4, 0x001f, 0x8637, 0x8204, 0x8004, 0xa605, 0x600e, 0x6004, + 0xa084, 0xffd5, 0x6006, 0x00ce, 0x0005, 0xa282, 0x0002, 0x1904, + 0x39de, 0x7aa8, 0x6920, 0xc1bd, 0x6922, 0xd1cc, 0x0568, 0xc1cc, + 0x6922, 0xa294, 0x00ff, 0xa282, 0x0002, 0x1a04, 0x39d0, 0x080c, + 0x3963, 0x080c, 0x38ba, 0xa980, 0x0001, 0x200c, 0x080c, 0x3b31, + 0x080c, 0x385d, 0x88ff, 0x0178, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x1118, 0x781b, 0x006e, 0x0005, - 0x781b, 0x0082, 0x0005, 0x080c, 0x36f3, 0x7e58, 0xd6d4, 0x1118, - 0x781b, 0x0071, 0x0005, 0x781b, 0x0083, 0x0005, 0x00c6, 0x7058, - 0x2060, 0x6100, 0xd1e4, 0x0578, 0x6208, 0x8217, 0xa294, 0x00ff, - 0xa282, 0x001c, 0x0218, 0x0110, 0x2011, 0x001c, 0x2600, 0xa202, - 0x1208, 0x2230, 0x6208, 0xa294, 0x00ff, 0x78ec, 0xd0e4, 0x0130, - 0xa282, 0x000a, 0x1240, 0x2011, 0x000a, 0x0028, 0xa282, 0x000c, - 0x1210, 0x2011, 0x000c, 0x2200, 0xa502, 0x1208, 0x2228, 0x080c, - 0x3896, 0x852b, 0x852b, 0x2041, 0x0000, 0x080c, 0x38c6, 0x0118, - 0x080c, 0x36f6, 0x0020, 0x080c, 0x3892, 0x080c, 0x36f3, 0x7858, - 0xc095, 0x785a, 0x00ce, 0x781b, 0x0082, 0x0005, 0x00c6, 0x2960, - 0x6000, 0xd0e4, 0x1178, 0x6010, 0xa084, 0x000f, 0x1130, 0x6104, - 0xa18c, 0xfff5, 0x6106, 0x00ce, 0x0005, 0x2011, 0x0032, 0x2019, - 0x0000, 0x00f0, 0x68a0, 0xd0cc, 0x1dc0, 0x6208, 0xa294, 0x00ff, - 0x78ec, 0xd0e4, 0x0130, 0xa282, 0x000b, 0x1218, 0x2011, 0x000a, - 0x0028, 0xa282, 0x000c, 0x1210, 0x2011, 0x000c, 0x6308, 0x831f, - 0xa39c, 0x00ff, 0xa382, 0x001c, 0x0218, 0x0110, 0x2019, 0x001c, - 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa, - 0xa8c0, 0x0005, 0x6820, 0xc0c5, 0x6822, 0x080c, 0x3850, 0x00ce, - 0x0005, 0x00c6, 0x2960, 0x6104, 0xa18c, 0xfff5, 0x6106, 0x2011, - 0x0032, 0x2019, 0x0000, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0003, - 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xc0c5, - 0x6822, 0x00ce, 0x0005, 0xa006, 0x2030, 0x2010, 0x00c6, 0x7158, - 0x2160, 0x2018, 0x2008, 0xa084, 0xffe0, 0xa635, 0x7e86, 0x6018, - 0x789a, 0x7eae, 0x6612, 0x78a4, 0xa084, 0x7770, 0xa18c, 0x000f, - 0xa105, 0x2029, 0x4305, 0x252c, 0xd5cc, 0x0140, 0xd3a4, 0x0110, - 0xa085, 0x0800, 0xd3fc, 0x0110, 0xa085, 0x8080, 0x78a6, 0x6016, - 0x788a, 0xa6b4, 0x001f, 0x8637, 0x8204, 0x8004, 0xa605, 0x600e, - 0x6004, 0xa084, 0xffd5, 0x6006, 0x00ce, 0x0005, 0xa282, 0x0002, - 0x1904, 0x3816, 0x7aa8, 0x6920, 0xc1bd, 0x6922, 0xd1cc, 0x0568, - 0xc1cc, 0x6922, 0xa294, 0x00ff, 0xa282, 0x0002, 0x1a04, 0x3809, - 0x080c, 0x379c, 0x080c, 0x36f3, 0xa980, 0x0001, 0x200c, 0x080c, - 0x3969, 0x080c, 0x3696, 0x88ff, 0x0178, 0x789b, 0x0060, 0x2800, - 0x78aa, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x1118, 0x781b, 0x006e, - 0x0005, 0x781b, 0x0082, 0x0005, 0x7e58, 0xd6d4, 0x1118, 0x781b, - 0x0071, 0x0005, 0x781b, 0x0083, 0x0005, 0xa282, 0x0002, 0x1218, - 0xa284, 0x0001, 0x0140, 0x7158, 0xa188, 0x0000, 0x210c, 0xd1ec, - 0x1110, 0x2011, 0x0000, 0x080c, 0x3883, 0x0471, 0x080c, 0x36f3, - 0x7858, 0xc095, 0x785a, 0x781b, 0x0082, 0x0005, 0x00c6, 0x0026, - 0x2960, 0x6000, 0x2011, 0x0001, 0xd0ec, 0x1150, 0x6014, 0xa084, - 0x0040, 0x1120, 0xc1a4, 0x6106, 0xa006, 0x0088, 0x2011, 0x0000, - 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0xa8c0, - 0x0004, 0x080c, 0x3850, 0x6820, 0xa085, 0x0200, 0x6822, 0x002e, - 0x00ce, 0x0005, 0x8807, 0xa715, 0x00c6, 0x2009, 0x0000, 0x7058, - 0x2060, 0x82ff, 0x0110, 0x2009, 0x0040, 0x6018, 0xa080, 0x0002, - 0x789a, 0x78a4, 0xa084, 0xff9f, 0xa105, 0xc0ec, 0xd0b4, 0x1108, - 0xc0ed, 0x6100, 0xd1f4, 0x0110, 0xa085, 0x0020, 0x78a6, 0x6016, - 0x788a, 0x6004, 0xa084, 0xffef, 0x6006, 0x00ce, 0x0005, 0x0006, - 0x7000, 0xa086, 0x0003, 0x0110, 0x000e, 0x0010, 0x000e, 0x0488, - 0xd6ac, 0x0578, 0x7888, 0xa084, 0x0040, 0x0558, 0x7bb8, 0x8307, - 0xa084, 0x007f, 0x1508, 0x8207, 0xa084, 0x00ff, 0xa09e, 0x0001, - 0x1904, 0x382d, 0xd6f4, 0x11d0, 0x79d8, 0x7adc, 0xa108, 0xa291, - 0x0000, 0x79d2, 0x79da, 0x7ad6, 0x7ade, 0x080c, 0x4083, 0x781b, - 0x0080, 0xb284, 0x0600, 0x0118, 0x2001, 0x0000, 0x0010, 0x2001, - 0x0001, 0x080c, 0x3f50, 0x0005, 0x080c, 0x243b, 0x781b, 0x0080, - 0x0005, 0x781b, 0x0083, 0x0005, 0x2039, 0x0000, 0x2041, 0x0000, - 0x2031, 0x0000, 0xa006, 0x2010, 0x080c, 0x36f6, 0x080c, 0x379a, - 0x7e58, 0x04f9, 0x781b, 0x0082, 0x0005, 0x0cd9, 0x6820, 0xc0c4, - 0x6822, 0x00c6, 0x7058, 0x2060, 0x0804, 0x3720, 0x0c91, 0x6820, - 0xc0cc, 0x6822, 0x00c6, 0x7058, 0x2060, 0x0804, 0x37b9, 0x0c49, - 0x6820, 0xa084, 0xecff, 0x6822, 0x00c6, 0x7058, 0x2060, 0x6004, + 0x781b, 0x0082, 0x0005, 0x7e58, 0xd6d4, 0x1118, 0x781b, 0x0071, + 0x0005, 0x781b, 0x0083, 0x0005, 0xa282, 0x0002, 0x1218, 0xa284, + 0x0001, 0x0140, 0x7154, 0xa188, 0x0000, 0x210c, 0xd1ec, 0x1110, + 0x2011, 0x0000, 0x080c, 0x3a4b, 0x0471, 0x080c, 0x38ba, 0x7858, + 0xc095, 0x785a, 0x781b, 0x0082, 0x0005, 0x00c6, 0x0026, 0x2960, + 0x6000, 0x2011, 0x0001, 0xd0ec, 0x1150, 0x6014, 0xa084, 0x0040, + 0x1120, 0xc1a4, 0x6106, 0xa006, 0x0088, 0x2011, 0x0000, 0x78ab, + 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0xa8c0, 0x0004, + 0x080c, 0x3a18, 0x6820, 0xa085, 0x0200, 0x6822, 0x002e, 0x00ce, + 0x0005, 0x8807, 0xa715, 0x00c6, 0x2009, 0x0000, 0x7054, 0x2060, + 0x82ff, 0x0110, 0x2009, 0x0040, 0x6018, 0xa080, 0x0002, 0x789a, + 0x78a4, 0xa084, 0xff9f, 0xa105, 0xc0ec, 0xd0b4, 0x1108, 0xc0ed, + 0x6100, 0xd1f4, 0x0110, 0xa085, 0x0020, 0x78a6, 0x6016, 0x788a, + 0x6004, 0xa084, 0xffef, 0x6006, 0x00ce, 0x0005, 0x0006, 0x7000, + 0xa086, 0x0003, 0x0110, 0x000e, 0x0010, 0x000e, 0x0488, 0xd6ac, + 0x0578, 0x7888, 0xa084, 0x0040, 0x0558, 0x7bb8, 0x8307, 0xa084, + 0x007f, 0x1508, 0x8207, 0xa084, 0x00ff, 0xa09e, 0x0001, 0x1904, + 0x39f5, 0xd6f4, 0x11d0, 0x79d8, 0x7adc, 0xa108, 0xa291, 0x0000, + 0x79d2, 0x79da, 0x7ad6, 0x7ade, 0x080c, 0x425d, 0x781b, 0x0080, + 0xb284, 0x0600, 0x0118, 0x2001, 0x0000, 0x0010, 0x2001, 0x0001, + 0x080c, 0x4118, 0x0005, 0x080c, 0x252b, 0x781b, 0x0080, 0x0005, + 0x781b, 0x0083, 0x0005, 0x2039, 0x0000, 0x2041, 0x0000, 0x2031, + 0x0000, 0xa006, 0x2010, 0x080c, 0x38bd, 0x080c, 0x3961, 0x7e58, + 0x080c, 0x3a11, 0x781b, 0x0082, 0x0005, 0x0cd1, 0x6820, 0xc0c4, + 0x6822, 0x00c6, 0x7054, 0x2060, 0x0804, 0x38e7, 0x0c89, 0x6820, + 0xc0cc, 0x6822, 0x00c6, 0x7054, 0x2060, 0x0804, 0x3980, 0x0c41, + 0x6820, 0xa084, 0xecff, 0x6822, 0x00c6, 0x7054, 0x2060, 0x6004, 0xa084, 0xffc5, 0x6006, 0x00ce, 0x0005, 0x0049, 0x781b, 0x0082, 0x0005, 0x6827, 0x0002, 0x0049, 0x781b, 0x0082, 0x0005, 0x2001, 0x0005, 0x0088, 0x2001, 0x000c, 0x0070, 0x6820, 0xc0d5, 0x6822, 0x2001, 0x0006, 0x0040, 0x2001, 0x000d, 0x0028, 0x2001, 0x0009, 0x0010, 0x2001, 0x0007, 0x789b, 0x007e, 0x78aa, 0xc69d, 0x7e5a, - 0x70d4, 0xd0b4, 0x0168, 0xc0b4, 0x70d6, 0x00c6, 0x70b8, 0xa065, + 0x70d0, 0xd0b4, 0x0168, 0xc0b4, 0x70d2, 0x00c6, 0x70b4, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x00ce, 0x0005, 0x0076, 0x873f, 0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703, - 0xb28c, 0x0600, 0x0118, 0xa0e0, 0x47c0, 0x0010, 0xa0e0, 0x4840, + 0xb28c, 0x0600, 0x0118, 0xa0e0, 0x49c0, 0x0010, 0xa0e0, 0x4a40, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184, 0x7fe0, 0x78ae, 0x6012, 0x79a4, 0xa184, 0x773f, 0x78a6, 0x6016, 0x6004, 0xa085, 0x0038, 0x6006, 0x007e, 0x0005, 0x789b, 0x0080, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060, 0x78ab, 0x0004, - 0x0804, 0x3850, 0x2031, 0x0000, 0x2029, 0x0032, 0x789b, 0x0080, + 0x0804, 0x3a18, 0x2031, 0x0000, 0x2029, 0x0032, 0x789b, 0x0080, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa, 0x7eaa, - 0x789b, 0x0060, 0x78ab, 0x0005, 0x0804, 0x3850, 0x0156, 0x8007, + 0x789b, 0x0060, 0x78ab, 0x0005, 0x0804, 0x3a18, 0x0156, 0x8007, 0xa084, 0x00ff, 0x8003, 0x8003, 0xa080, 0x0020, 0x789a, 0x79a4, - 0xa18c, 0xffe0, 0x2021, 0x3952, 0x2019, 0x0011, 0x20a9, 0x000e, + 0xa18c, 0xffe0, 0x2021, 0x3b1a, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011, 0x0032, 0x2404, 0xa084, 0xffe0, 0xa106, 0x0128, 0x8420, - 0x2300, 0xa210, 0x1f04, 0x38ba, 0x015e, 0x0005, 0x0156, 0x0804, - 0x3908, 0x2021, 0x3960, 0x20a9, 0x0009, 0x2011, 0x0029, 0xa582, + 0x2300, 0xa210, 0x1f04, 0x3a82, 0x015e, 0x0005, 0x0156, 0x0804, + 0x3ad0, 0x2021, 0x3b28, 0x20a9, 0x0009, 0x2011, 0x0029, 0xa582, 0x0028, 0x0550, 0x8420, 0x95a9, 0x2011, 0x0033, 0xa582, 0x0033, 0x0618, 0x8420, 0x95a9, 0x2019, 0x000a, 0x2011, 0x0065, 0x2200, - 0xa502, 0x02d0, 0x8420, 0x2300, 0xa210, 0x1f04, 0x38df, 0x015e, - 0x0088, 0x2021, 0x3952, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011, + 0xa502, 0x02d0, 0x8420, 0x2300, 0xa210, 0x1f04, 0x3aa7, 0x015e, + 0x0088, 0x2021, 0x3b1a, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011, 0x0033, 0x2200, 0xa502, 0x0240, 0x8420, 0x2300, 0xa210, 0x1f04, - 0x38f1, 0x015e, 0xa006, 0x0005, 0x8211, 0x015e, 0xa582, 0x0064, + 0x3ab9, 0x015e, 0xa006, 0x0005, 0x8211, 0x015e, 0xa582, 0x0064, 0x1220, 0x7808, 0xa085, 0x0070, 0x780a, 0x2404, 0xa005, 0x0005, - 0xa886, 0x0002, 0x01e8, 0x2021, 0x393e, 0x20a9, 0x000d, 0x2011, + 0xa886, 0x0002, 0x01e8, 0x2021, 0x3b06, 0x20a9, 0x000d, 0x2011, 0x0028, 0xa582, 0x0028, 0x0d48, 0x8420, 0x2019, 0x0019, 0x2011, 0x0033, 0x2200, 0xa502, 0x0e00, 0x8420, 0x2300, 0xa210, 0x1f04, - 0x3919, 0x015e, 0x2011, 0x0184, 0xa582, 0x0185, 0x0ab0, 0x0890, - 0x2021, 0x394d, 0x20a9, 0x0003, 0x2011, 0x0024, 0xa586, 0x0024, + 0x3ae1, 0x015e, 0x2011, 0x0184, 0xa582, 0x0185, 0x0ab0, 0x0890, + 0x2021, 0x3b15, 0x20a9, 0x0003, 0x2011, 0x0024, 0xa586, 0x0024, 0x0960, 0x8420, 0x2011, 0x0028, 0xa586, 0x0028, 0x0930, 0x8420, - 0x2019, 0x0019, 0x2011, 0x0033, 0x0804, 0x38f1, 0x1021, 0x2202, + 0x2019, 0x0019, 0x2011, 0x0033, 0x0804, 0x3ab9, 0x1021, 0x2202, 0x3403, 0x4604, 0x5805, 0x6a06, 0x7c07, 0x4610, 0x4612, 0x5812, 0x5a12, 0x6a14, 0x6c14, 0x6e14, 0x7e17, 0x9021, 0xb002, 0xe204, 0xe210, 0xe210, 0x1209, 0x3002, 0x3202, 0x4203, 0x4403, 0x5404, @@ -1391,314 +1485,319 @@ 0x10e1, 0x330a, 0x5805, 0x5a05, 0x6a06, 0x6c06, 0x7c07, 0x7e07, 0x0e00, 0x789b, 0x0080, 0xa046, 0x0005, 0xa784, 0x0f00, 0x800b, 0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xd7fc, - 0x0118, 0xa0e0, 0x68c0, 0x0010, 0xa0e0, 0x48c0, 0x0005, 0x00e6, - 0x00f6, 0xd084, 0x0138, 0x2079, 0x0100, 0x2009, 0x4380, 0x2071, - 0x4380, 0x0030, 0x2009, 0x4340, 0x2079, 0x0200, 0x2071, 0x4340, - 0x2091, 0x8000, 0x2104, 0xa084, 0x000f, 0x0002, 0x39c5, 0x39a0, - 0x39a0, 0x39a0, 0x39a0, 0x39a0, 0x399e, 0x399e, 0x080c, 0x243b, - 0x784b, 0x0004, 0x7848, 0xa084, 0x0004, 0x1de0, 0x784b, 0x0008, - 0x7848, 0xa084, 0x0008, 0x1de0, 0x68b4, 0xc0f5, 0x68b6, 0x7858, - 0xc0f5, 0x785a, 0x7830, 0xd0bc, 0x1180, 0xb284, 0x0800, 0x0118, - 0x0104, 0x39c5, 0x0010, 0x0304, 0x39c5, 0x681c, 0xd0ac, 0x1118, - 0x080c, 0x3a4b, 0x0010, 0x781b, 0x00fb, 0x2091, 0x8001, 0x00fe, - 0x00ee, 0x0005, 0x00c6, 0x2001, 0x4301, 0x2004, 0xd0ac, 0x1904, - 0x3a3d, 0x6814, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, - 0xb28c, 0x0600, 0x0118, 0xa0e0, 0x47c0, 0x0010, 0xa0e0, 0x4840, - 0x6004, 0xa084, 0x000a, 0x1904, 0x3a3d, 0x6108, 0xa194, 0xff00, - 0x0904, 0x3a3d, 0xa18c, 0x00ff, 0x601c, 0xa084, 0xff00, 0x0180, - 0x2001, 0x0009, 0xa102, 0x16b8, 0x2001, 0x000a, 0xa102, 0x16b0, - 0x2001, 0x000c, 0xa102, 0x16a8, 0x601c, 0xa084, 0x00ff, 0x601e, - 0x2001, 0x000a, 0xa106, 0x01a8, 0x2001, 0x000c, 0xa106, 0x01a0, - 0x2001, 0x0012, 0xa106, 0x0198, 0x2001, 0x0014, 0xa106, 0x0190, - 0x2001, 0x0019, 0xa106, 0x0188, 0x2001, 0x0032, 0xa106, 0x0180, - 0x00d8, 0x2009, 0x000c, 0x00d0, 0x2009, 0x0012, 0x00b8, 0x2009, - 0x0014, 0x00a0, 0x2009, 0x0019, 0x0088, 0x2009, 0x0020, 0x0070, - 0x2009, 0x003f, 0x0058, 0x2009, 0x000a, 0x0040, 0x2009, 0x000c, - 0x0028, 0x2009, 0x0019, 0x0010, 0x2011, 0x0000, 0x2100, 0xa205, - 0x600a, 0x6004, 0xa085, 0x0002, 0x6006, 0x00ce, 0x0005, 0x781b, - 0x0083, 0x0005, 0x781b, 0x0082, 0x0005, 0x781b, 0x0071, 0x0005, - 0x781b, 0x006e, 0x0005, 0x2009, 0x4319, 0x210c, 0xa186, 0x0000, - 0x0150, 0xa186, 0x0001, 0x0150, 0x701f, 0x000b, 0x7067, 0x0001, - 0x781b, 0x0054, 0x0005, 0x781b, 0x00f3, 0x0005, 0x701f, 0x000a, - 0x0005, 0x2009, 0x4319, 0x210c, 0xa186, 0x0000, 0x0168, 0xa186, - 0x0001, 0x0138, 0x701f, 0x000b, 0x7067, 0x0001, 0x781b, 0x0054, - 0x0005, 0x701f, 0x000a, 0x0005, 0x781b, 0x00f2, 0x0005, 0x781b, - 0x00fb, 0x0005, 0x781b, 0x00fa, 0x0005, 0x781b, 0x00cc, 0x0005, - 0x781b, 0x00cb, 0x0005, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d, - 0x7067, 0x0001, 0x781b, 0x0054, 0x0005, 0x7830, 0xa084, 0x00c0, - 0x1170, 0x7808, 0xc08c, 0x780a, 0xe000, 0xe000, 0xe000, 0xe000, - 0x78ec, 0xa084, 0x0021, 0x0118, 0x7808, 0xc08d, 0x780a, 0x0005, - 0x7808, 0xc08d, 0x780a, 0x0005, 0x7830, 0xa084, 0x0040, 0x1de0, - 0xb284, 0x0800, 0x0118, 0x1104, 0x3ab2, 0x0010, 0x1304, 0x3ab2, - 0x78ac, 0x0005, 0x7808, 0xa084, 0xfffd, 0x780a, 0xe000, 0xe000, - 0xe000, 0xe000, 0x78ec, 0xa084, 0x0021, 0x0140, 0xb284, 0x0800, - 0x0118, 0x1104, 0x3ac1, 0x0010, 0x1304, 0x3ac4, 0x78ac, 0x0006, - 0x7808, 0xa085, 0x0002, 0x780a, 0x000e, 0x0005, 0xa784, 0x0001, - 0x1904, 0x30a0, 0xa784, 0x0070, 0x0140, 0x00c6, 0x2d60, 0x2f68, - 0x080c, 0x23e1, 0x2d78, 0x2c68, 0x00ce, 0xa784, 0x0008, 0x0148, - 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0904, 0x248f, 0x0804, - 0x3a3f, 0xa784, 0x0004, 0x01c8, 0x78b8, 0xa084, 0x8000, 0x01a8, - 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0904, 0x248f, 0x78e4, - 0xa084, 0x0007, 0xa086, 0x0001, 0x1140, 0x78c0, 0xa685, 0x4800, - 0x2030, 0x7e5a, 0x781b, 0x00fb, 0x0005, 0xa784, 0x0080, 0x0140, - 0x7884, 0xd0fc, 0x0128, 0x080c, 0x382d, 0x681b, 0x0022, 0x0005, - 0x681b, 0x0003, 0x7858, 0xa084, 0x3f00, 0x681e, 0x682f, 0x0000, - 0x6833, 0x0000, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0904, - 0x2a7a, 0xb284, 0x0800, 0x0110, 0x0104, 0x248c, 0x0304, 0x248c, - 0x6b14, 0x8307, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xd3fc, - 0x0118, 0xa080, 0x4840, 0x0010, 0xa080, 0x47c0, 0x2060, 0x2048, - 0x705a, 0x2a60, 0x0005, 0x00c6, 0x2960, 0x6000, 0xd0ac, 0x0904, - 0x3b81, 0xd1ac, 0x05e0, 0x6108, 0x8117, 0xa18c, 0x00ff, 0x631c, - 0x832f, 0x68a0, 0xd0cc, 0x11c8, 0xa584, 0x00ff, 0x0138, 0x78ec, - 0xd0e4, 0x0110, 0x8213, 0x00b8, 0x2029, 0x0000, 0xa182, 0x000c, - 0x1290, 0x78ec, 0xd0e4, 0x1118, 0x2009, 0x000c, 0x0060, 0xa182, - 0x000b, 0x1248, 0x2009, 0x000a, 0x0030, 0x2009, 0x0032, 0x2011, - 0x0000, 0x2029, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0006, 0x78ab, - 0x0004, 0x79aa, 0x78ab, 0x0000, 0x7aaa, 0x7baa, 0x7daa, 0xa8c0, - 0x0008, 0x6820, 0xa085, 0x1000, 0x6822, 0x080c, 0x3850, 0xa085, - 0x0001, 0x00ce, 0x0005, 0xa282, 0x0006, 0x1904, 0x381f, 0x7da8, - 0x7eac, 0x8637, 0xa5ac, 0x00ff, 0xa6b4, 0x00ff, 0x7fac, 0x8747, - 0xa7bc, 0x00ff, 0xa8c4, 0x00ff, 0x6920, 0xc1bd, 0x6922, 0xd1e4, - 0x05c8, 0xa18c, 0xecff, 0x6922, 0xa782, 0x0002, 0x1a04, 0x37fc, - 0xa6b4, 0x00ff, 0x0560, 0xa682, 0x0039, 0x1a04, 0x37fc, 0xa582, - 0x0009, 0x0a04, 0x37fc, 0xa882, 0x0003, 0x1a04, 0x37fc, 0xa886, - 0x0002, 0x0128, 0xa886, 0x0000, 0x0138, 0x0804, 0x37fc, 0xa786, - 0x0000, 0x0904, 0x37fc, 0x8634, 0x852b, 0x852b, 0x080c, 0x38c6, - 0x0904, 0x37fc, 0x080c, 0x36f6, 0x080c, 0x379a, 0x7e58, 0xd6d4, - 0x1118, 0x781b, 0x0071, 0x0005, 0x781b, 0x0083, 0x0005, 0x080c, - 0x36f3, 0x0c90, 0xa886, 0x0002, 0x1108, 0x8634, 0x7158, 0xa188, - 0x0000, 0x210c, 0xd1ac, 0x0904, 0x37fc, 0xd1ec, 0x1120, 0x2039, - 0x0000, 0x2041, 0x0000, 0xd1e4, 0x1120, 0x2031, 0x0000, 0x2041, - 0x0000, 0xa782, 0x0002, 0x12c8, 0x621c, 0xa284, 0x00ff, 0xa706, - 0x0110, 0x2039, 0x0000, 0xa605, 0x0190, 0x6108, 0x811f, 0xa39c, - 0x00ff, 0x0168, 0xa302, 0x1208, 0x2330, 0x8807, 0xa705, 0xa086, - 0x0201, 0x0160, 0xa886, 0x0000, 0x0168, 0x2039, 0x0000, 0x2041, - 0x0000, 0x2031, 0x0000, 0xa006, 0x2010, 0x0070, 0xa284, 0xff00, - 0x1108, 0x2040, 0xa184, 0x00ff, 0xa502, 0x0108, 0x2128, 0x852b, - 0x852b, 0x080c, 0x38c6, 0x0d58, 0x080c, 0x36f6, 0x080c, 0x379a, - 0x789b, 0x0080, 0x78ab, 0x0001, 0x78ab, 0x0006, 0x78ab, 0x0004, - 0x78ab, 0x0000, 0x7daa, 0x7eaa, 0x7faa, 0x2800, 0x78aa, 0x789b, - 0x0060, 0x78ab, 0x0005, 0x080c, 0x3850, 0x7858, 0xc095, 0x785a, - 0x781b, 0x0082, 0x0005, 0x0020, 0x0020, 0x0000, 0x0020, 0x0000, - 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, - 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, - 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, - 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0062, 0x0009, 0x0014, - 0x0014, 0x9855, 0x984d, 0x0014, 0x9911, 0x98ff, 0x0014, 0x0014, - 0x0090, 0x00e7, 0x0100, 0x0402, 0x2008, 0xf880, 0x0018, 0x0017, - 0x840f, 0xd8c1, 0x0014, 0x0016, 0xa20a, 0x0014, 0x300b, 0xa20c, - 0x0014, 0x2500, 0x0013, 0x2500, 0x0010, 0x0010, 0x0010, 0x0010, + 0x0118, 0xa0e0, 0x6ac0, 0x0010, 0xa0e0, 0x4ac0, 0x0005, 0x00e6, + 0x00f6, 0xd084, 0x0138, 0x2079, 0x0100, 0x2009, 0x4580, 0x2071, + 0x4580, 0x0030, 0x2009, 0x4540, 0x2079, 0x0200, 0x2071, 0x4540, + 0x2091, 0x8000, 0x2104, 0xa084, 0x000f, 0x0002, 0x3b68, 0x3b68, + 0x3b68, 0x3b68, 0x3b68, 0x3b68, 0x3b66, 0x3b66, 0x080c, 0x252b, + 0x69b4, 0xc1f5, 0xa18c, 0xff9f, 0x69b6, 0xa005, 0x0580, 0x7858, + 0xa084, 0xff9f, 0xa085, 0x6000, 0x785a, 0x7828, 0xa086, 0x1814, + 0x1530, 0x784b, 0x0004, 0x7848, 0xa084, 0x0004, 0x1de0, 0x784b, + 0x0008, 0x7848, 0xa084, 0x0008, 0x1de0, 0x7830, 0xd0bc, 0x11b8, + 0xb284, 0x0800, 0x0118, 0x0104, 0x3b9f, 0x0010, 0x0304, 0x3b9f, + 0x79e4, 0xa184, 0x0030, 0x0158, 0x78ec, 0xa084, 0x0003, 0x0138, + 0x681c, 0xd0ac, 0x1110, 0x00d9, 0x0010, 0x781b, 0x00fb, 0x00fe, + 0x00ee, 0x0005, 0x2001, 0x4501, 0x2004, 0xd0ac, 0x1118, 0x6814, + 0x080c, 0x2454, 0x0005, 0x781b, 0x0083, 0x0005, 0x781b, 0x0082, + 0x0005, 0x781b, 0x0071, 0x0005, 0x781b, 0x006e, 0x0005, 0x2009, + 0x4519, 0x210c, 0xa186, 0x0000, 0x0150, 0xa186, 0x0001, 0x0150, + 0x701f, 0x000b, 0x7063, 0x0001, 0x781b, 0x0054, 0x0005, 0x781b, + 0x00f3, 0x0005, 0x701f, 0x000a, 0x0005, 0x2009, 0x4519, 0x210c, + 0xa186, 0x0000, 0x0168, 0xa186, 0x0001, 0x0138, 0x701f, 0x000b, + 0x7063, 0x0001, 0x781b, 0x0054, 0x0005, 0x701f, 0x000a, 0x0005, + 0x781b, 0x00f2, 0x0005, 0x781b, 0x00fb, 0x0005, 0x781b, 0x00fa, + 0x0005, 0x781b, 0x00cc, 0x0005, 0x781b, 0x00cb, 0x0005, 0x6818, + 0xd0fc, 0x0110, 0x681b, 0x001d, 0x7063, 0x0001, 0x781b, 0x0054, + 0x0005, 0x7830, 0xa084, 0x00c0, 0x1170, 0x7808, 0xc08c, 0x780a, + 0xe000, 0xe000, 0xe000, 0xe000, 0x78ec, 0xa084, 0x0021, 0x0118, + 0x7808, 0xc08d, 0x780a, 0x0005, 0x7808, 0xc08d, 0x780a, 0x0005, + 0x7830, 0xa084, 0x0040, 0x1de0, 0xb284, 0x0800, 0x0118, 0x1104, + 0x3c1e, 0x0010, 0x1304, 0x3c1e, 0x78ac, 0x0005, 0x7808, 0xa084, + 0xfffd, 0x780a, 0xe000, 0xe000, 0xe000, 0xe000, 0x78ec, 0xa084, + 0x0021, 0x0140, 0xb284, 0x0800, 0x0118, 0x1104, 0x3c2d, 0x0010, + 0x1304, 0x3c30, 0x78ac, 0x0006, 0x7808, 0xa085, 0x0002, 0x780a, + 0x000e, 0x0005, 0xa784, 0x0001, 0x1904, 0x31c5, 0xa784, 0x0070, + 0x0140, 0x00c6, 0x2d60, 0x2f68, 0x080c, 0x2446, 0x2d78, 0x2c68, + 0x00ce, 0xa784, 0x0008, 0x0148, 0x784b, 0x0008, 0x78ec, 0xa084, + 0x0003, 0x0904, 0x31c5, 0x0804, 0x3bab, 0xa784, 0x0004, 0x01c8, + 0x78b8, 0xa084, 0x8000, 0x01a8, 0x784b, 0x0008, 0x78ec, 0xa084, + 0x0003, 0x0904, 0x31c5, 0x78e4, 0xa084, 0x0007, 0xa086, 0x0001, + 0x1140, 0x78c0, 0xa685, 0x4800, 0x2030, 0x7e5a, 0x781b, 0x00fb, + 0x0005, 0xa784, 0x0080, 0x0140, 0x7884, 0xd0fc, 0x0128, 0x080c, + 0x39f5, 0x681b, 0x0022, 0x0005, 0x681b, 0x0003, 0x7858, 0xa084, + 0x5f00, 0x681e, 0x682f, 0x0000, 0x6833, 0x0000, 0x784b, 0x0008, + 0x78ec, 0xa084, 0x0003, 0x0904, 0x2b6b, 0xb284, 0x0800, 0x0110, + 0x0104, 0x257c, 0x0304, 0x257c, 0x6b14, 0x8307, 0xa084, 0x000f, + 0x8003, 0x8003, 0x8003, 0xd3fc, 0x0118, 0xa080, 0x4a40, 0x0010, + 0xa080, 0x49c0, 0x2060, 0x2048, 0x7056, 0x2a60, 0x0005, 0x00c6, + 0x2960, 0x6000, 0xd0ac, 0x0904, 0x3ced, 0xd1ac, 0x05e0, 0x6108, + 0x8117, 0xa18c, 0x00ff, 0x631c, 0x832f, 0x68a0, 0xd0cc, 0x11c8, + 0xa584, 0x00ff, 0x0138, 0x78ec, 0xd0e4, 0x0110, 0x8213, 0x00b8, + 0x2029, 0x0000, 0xa182, 0x000c, 0x1290, 0x78ec, 0xd0e4, 0x1118, + 0x2009, 0x000c, 0x0060, 0xa182, 0x000b, 0x1248, 0x2009, 0x000a, + 0x0030, 0x2009, 0x0032, 0x2011, 0x0000, 0x2029, 0x0000, 0x78ab, + 0x0001, 0x78ab, 0x0006, 0x78ab, 0x0004, 0x79aa, 0x78ab, 0x0000, + 0x7aaa, 0x7baa, 0x7daa, 0xa8c0, 0x0008, 0x6820, 0xa085, 0x1000, + 0x6822, 0x080c, 0x3a18, 0xa085, 0x0001, 0x00ce, 0x0005, 0xa282, + 0x0006, 0x1904, 0x39e7, 0x7da8, 0x7eac, 0x8637, 0xa5ac, 0x00ff, + 0xa6b4, 0x00ff, 0x7fac, 0x8747, 0xa7bc, 0x00ff, 0xa8c4, 0x00ff, + 0x6920, 0xc1bd, 0x6922, 0xd1e4, 0x0904, 0x3d59, 0xa18c, 0xecff, + 0x6922, 0xa782, 0x0002, 0x1a04, 0x39c3, 0xa6b4, 0x00ff, 0x0904, + 0x3d56, 0xa682, 0x0039, 0x1a04, 0x39c3, 0xa582, 0x0009, 0x0a04, + 0x39c3, 0xa882, 0x0003, 0x1a04, 0x39c3, 0xa886, 0x0002, 0x01d0, + 0xa886, 0x0000, 0x1904, 0x39c3, 0x2001, 0x000c, 0x79ec, 0xd1e4, + 0x0110, 0x2001, 0x000a, 0xa502, 0x1290, 0x080c, 0x39c3, 0x00c6, + 0x2960, 0x6004, 0xa085, 0x001a, 0x6006, 0x6000, 0xc0ac, 0x6002, + 0x00ce, 0x0005, 0xa786, 0x0000, 0x0904, 0x39c3, 0x8634, 0xa686, + 0x0010, 0x1108, 0x8630, 0x852b, 0x852b, 0x080c, 0x3a8e, 0x0904, + 0x39c3, 0x080c, 0x38bd, 0x080c, 0x3961, 0x7e58, 0xd6d4, 0x1118, + 0x781b, 0x0071, 0x0005, 0x781b, 0x0083, 0x0005, 0x080c, 0x38ba, + 0x0c90, 0xa886, 0x0002, 0x1108, 0x8634, 0x7154, 0xa188, 0x0000, + 0x210c, 0xd1ac, 0x0904, 0x39c3, 0xd1ec, 0x1120, 0x2039, 0x0000, + 0x2041, 0x0000, 0xd1e4, 0x1120, 0x2031, 0x0000, 0x2041, 0x0000, + 0xa782, 0x0002, 0x12c8, 0x621c, 0xa284, 0x00ff, 0xa706, 0x0110, + 0x2039, 0x0000, 0xa605, 0x0190, 0x6108, 0x811f, 0xa39c, 0x00ff, + 0x0168, 0xa302, 0x1208, 0x2330, 0x8807, 0xa705, 0xa086, 0x0201, + 0x0160, 0xa886, 0x0000, 0x0168, 0x2039, 0x0000, 0x2041, 0x0000, + 0x2031, 0x0000, 0xa006, 0x2010, 0x0070, 0xa284, 0xff00, 0x1108, + 0x2040, 0xa184, 0x00ff, 0xa502, 0x0108, 0x2128, 0x852b, 0x852b, + 0x080c, 0x3a8e, 0x0d58, 0x080c, 0x38bd, 0x080c, 0x3961, 0x789b, + 0x0080, 0x78ab, 0x0001, 0x78ab, 0x0006, 0x78ab, 0x0004, 0x78ab, + 0x0000, 0x7daa, 0x7eaa, 0x7faa, 0x2800, 0x78aa, 0x789b, 0x0060, + 0x78ab, 0x0005, 0x080c, 0x3a18, 0x7858, 0xc095, 0x785a, 0x781b, + 0x0082, 0x0005, 0x0020, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, + 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, + 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, + 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, + 0x0000, 0x0020, 0x0000, 0x0020, 0x0062, 0x0009, 0x0014, 0x0014, + 0x9855, 0x984d, 0x0014, 0x9911, 0x98ff, 0x0014, 0x0014, 0x0090, + 0x00e7, 0x0100, 0x0402, 0x2008, 0xf880, 0x0018, 0x0017, 0x840f, + 0xd8c1, 0x0014, 0x0016, 0xa20a, 0x0014, 0x300b, 0xa20c, 0x0014, + 0x2500, 0x0013, 0x2500, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, - 0x0010, 0x0010, 0xa200, 0x3806, 0x8839, 0x20c4, 0x0864, 0xa84f, - 0x3008, 0x28c1, 0x9d18, 0xa201, 0x300c, 0x2847, 0x8161, 0x846a, - 0x8000, 0x84a4, 0x1856, 0x883a, 0xa808, 0x28e2, 0x9cce, 0xa8f3, - 0x0864, 0xa83d, 0x300c, 0xa801, 0x3008, 0x28e1, 0x9cce, 0x2021, - 0xa818, 0xa205, 0x870c, 0xd8de, 0x64a0, 0x6de0, 0x6fc0, 0x67a4, - 0x6c80, 0x0212, 0xa205, 0x883d, 0x882b, 0x1814, 0x883b, 0x7027, - 0x85f2, 0xa737, 0xa532, 0xf003, 0x8576, 0x8677, 0xa814, 0x883e, - 0xa812, 0x280a, 0xa204, 0x64c0, 0x6de0, 0x67a0, 0x6fc0, 0x1814, - 0x883b, 0x7027, 0x8576, 0x8677, 0xa806, 0x796d, 0xa8da, 0x796b, - 0xa8f1, 0x7861, 0x883e, 0x206b, 0x28c1, 0x9d18, 0x2044, 0x2103, - 0x20b4, 0x2095, 0xa8ca, 0xa207, 0x2901, 0xa80a, 0x0014, 0xa203, + 0x0010, 0xa200, 0x3806, 0x8839, 0x20c4, 0x0864, 0xa850, 0x3008, + 0x28c1, 0x9d18, 0xa201, 0x300c, 0x2847, 0x8161, 0x846a, 0x8000, + 0x84a4, 0x1856, 0x883a, 0xa808, 0x28e2, 0x9cce, 0xa8f3, 0x0864, + 0xa83e, 0x300c, 0xa801, 0x3008, 0x28e1, 0x9cce, 0x28a1, 0x7162, + 0x2021, 0xa818, 0xa205, 0x870c, 0xd8de, 0x64a0, 0x6de0, 0x6fc0, + 0x67a4, 0x6c80, 0x0212, 0xa205, 0x883d, 0x882b, 0x1814, 0x883b, + 0x7027, 0x85f2, 0xa737, 0xa532, 0xf003, 0x8576, 0x8677, 0xa812, + 0x883e, 0xa810, 0x2881, 0x7161, 0x280a, 0xa204, 0x64c0, 0x6de0, + 0x67a0, 0x6fc0, 0x1814, 0x883b, 0x7023, 0x8576, 0x8677, 0xa802, + 0x7861, 0x883e, 0x206c, 0x28c1, 0x9d18, 0x2044, 0x2103, 0x20a2, + 0x2081, 0xa8ca, 0x2902, 0xa20e, 0xa80b, 0xa207, 0x0014, 0xa203, 0x8000, 0x85a4, 0x1872, 0x879a, 0x883c, 0x1fe2, 0xf601, 0xa208, - 0x856e, 0x866f, 0x7121, 0x0014, 0x0704, 0x3008, 0x9cce, 0x0014, - 0xa202, 0x8000, 0x85a4, 0x3009, 0x84a8, 0x19e2, 0xf844, 0x856e, - 0x883f, 0x08e6, 0xa8f5, 0xf861, 0xa8ea, 0xf801, 0x0014, 0xf881, - 0x0016, 0x85b2, 0x80f0, 0x9532, 0xfaa2, 0x1de2, 0x0014, 0x8532, - 0xf221, 0x0014, 0x1de2, 0x84a8, 0xd6e0, 0x1fe6, 0x0014, 0x3008, - 0x8000, 0x2849, 0x1011, 0xa8fc, 0x3008, 0x8000, 0xa000, 0x2081, - 0x2802, 0x1011, 0xa8fc, 0xa889, 0x3008, 0x20a1, 0x283c, 0x1011, - 0xa8fc, 0xa209, 0x0017, 0x300c, 0x8000, 0x85a4, 0x1de2, 0xdac1, - 0x0014, 0x0210, 0xa801, 0x0014, 0x26e0, 0x873a, 0xfaa3, 0x19f2, - 0x26e0, 0x18f2, 0x0014, 0xa20b, 0x0014, 0xa20d, 0x3806, 0x0210, - 0x9d22, 0x0704, 0xa206, 0x6865, 0x817e, 0x842a, 0x1dc1, 0x8823, - 0x0016, 0x6042, 0x8008, 0xa8fa, 0x8160, 0x842a, 0x8180, 0xf021, - 0x3008, 0x84a8, 0x11d7, 0x7042, 0x20dd, 0x0011, 0x20d5, 0x8822, - 0x0016, 0x0000, 0x0126, 0x70d4, 0xa084, 0x4c00, 0x8004, 0x2090, - 0x7204, 0x7008, 0xc09c, 0xa205, 0x1178, 0x720c, 0x82ff, 0x0128, - 0x8aff, 0x1150, 0x7200, 0xd284, 0x1138, 0x7007, 0x0004, 0x7003, - 0x0008, 0x012e, 0x2000, 0x0005, 0x7000, 0xa084, 0x0003, 0x7002, - 0xc69c, 0xd084, 0x05b8, 0x2001, 0x4301, 0x2004, 0xd0b4, 0x0904, - 0x3dcf, 0x7108, 0xe000, 0x7008, 0xa106, 0x1dd8, 0xa184, 0x0003, - 0x0904, 0x3dcf, 0xa184, 0x01e0, 0x1904, 0x3dcf, 0xd1f4, 0x1d88, - 0xa184, 0x3000, 0xa086, 0x1000, 0x0d60, 0x2011, 0x0180, 0x710c, - 0x8211, 0x0130, 0x7008, 0xd0f4, 0x1d20, 0x700c, 0xa106, 0x0dc0, - 0x7007, 0x0012, 0x7108, 0xe000, 0x7008, 0xa106, 0x1dd8, 0xa184, - 0x0003, 0x0568, 0xd194, 0x0db0, 0xd1f4, 0x0548, 0x7007, 0x0002, - 0x0880, 0x0428, 0x7108, 0xd1fc, 0x0130, 0x080c, 0x3e9e, 0x8aff, - 0x0904, 0x3d58, 0x0cb8, 0x700c, 0xa08c, 0x07ff, 0x01e8, 0x7004, - 0xd084, 0x0178, 0x7014, 0xa005, 0x1148, 0x7010, 0x7310, 0xa306, - 0x1de0, 0x2300, 0xa005, 0x0128, 0xa102, 0x1e20, 0x7007, 0x0010, - 0x0030, 0x8aff, 0x0148, 0x080c, 0x4046, 0x1de8, 0x09d8, 0x080c, - 0x3e58, 0x012e, 0x2000, 0x0005, 0x7204, 0x7108, 0xc19c, 0x8103, - 0x1218, 0x080c, 0x3e9e, 0x0cc0, 0xa205, 0x1d88, 0x7007, 0x0004, - 0x7003, 0x0008, 0x012e, 0x2000, 0x0005, 0x6428, 0x84ff, 0x0508, - 0x2c70, 0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x3e19, 0x273c, 0x87fb, - 0x1148, 0x0210, 0x080c, 0x243b, 0x609c, 0xa075, 0x0190, 0x0c88, - 0x2039, 0x3e0e, 0x2704, 0xae68, 0x6808, 0xa630, 0x680c, 0xa529, - 0x8421, 0x0138, 0x8738, 0x2704, 0xa005, 0x1da8, 0x709c, 0xa075, - 0x1d00, 0x0005, 0x0000, 0x0005, 0x0009, 0x000d, 0x0011, 0x0015, - 0x0019, 0x001d, 0x0000, 0x0003, 0x0009, 0x000f, 0x0015, 0x001b, - 0x0000, 0x0000, 0x3e0e, 0x3e0b, 0x0000, 0x0000, 0x8000, 0x0000, - 0x3e0e, 0x0000, 0x3e16, 0x3e13, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3e16, 0x0000, 0x3e11, 0x3e11, 0x0000, 0x0000, 0x8000, 0x0000, - 0x3e11, 0x0000, 0x3e17, 0x3e17, 0x0000, 0x0000, 0x0000, 0x0000, - 0x3e17, 0x2079, 0x4300, 0x2071, 0x0010, 0x7007, 0x000a, 0x7007, - 0x0002, 0x7003, 0x0001, 0x2009, 0x0002, 0x2071, 0x0050, 0x7007, - 0x000a, 0x7007, 0x0002, 0x7003, 0x0000, 0x2001, 0x01ff, 0x2004, - 0xd0fc, 0x1128, 0x8109, 0x0118, 0x2071, 0x0020, 0x0c80, 0x0005, - 0x7004, 0x8004, 0x1690, 0x7007, 0x0012, 0x2019, 0x0000, 0x7108, - 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0, 0x0110, 0x080c, 0x243b, - 0xa19c, 0x300c, 0xa386, 0x2004, 0x0130, 0xa386, 0x0008, 0x0160, - 0xa386, 0x200c, 0x1d60, 0x7200, 0x8204, 0x0230, 0x730c, 0xa384, - 0x07ff, 0x0110, 0x080c, 0x243b, 0x7007, 0x0012, 0x7000, 0xd084, - 0x1160, 0x7008, 0xa084, 0x01e0, 0x1140, 0x7310, 0x7014, 0xa305, - 0x0120, 0x710c, 0xa184, 0x07ff, 0x1958, 0x7007, 0x0012, 0x7007, - 0x0008, 0x7004, 0xd09c, 0x1de8, 0x7007, 0x0012, 0x7108, 0x8103, - 0x0ed8, 0x7003, 0x0008, 0x0005, 0x7108, 0x0000, 0xa184, 0x01e0, - 0x1550, 0x7108, 0xa184, 0x01e0, 0x1530, 0xa184, 0x0007, 0x0002, - 0x3eb2, 0x3ec0, 0x3eb0, 0x3ec0, 0x3eb0, 0x3f06, 0x3eb0, 0x3f05, - 0x080c, 0x243b, 0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x8aff, - 0x1118, 0x2049, 0x0000, 0x0005, 0x080c, 0x4046, 0x1de8, 0x0005, - 0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x8aff, 0x0118, 0x080c, - 0x4046, 0x1de8, 0x0005, 0x7007, 0x0012, 0x7108, 0x1d04, 0x3ece, - 0x2091, 0x6000, 0x1d04, 0x3ed2, 0x2091, 0x6000, 0x7007, 0x0012, + 0x856e, 0x7121, 0x0014, 0x0704, 0x3008, 0x9cce, 0x0014, 0xa202, + 0x8000, 0x85a4, 0x3009, 0x84a8, 0x19e2, 0xf844, 0x856e, 0x883f, + 0x08e6, 0xa8f5, 0xf861, 0xa8eb, 0xf801, 0x0014, 0xf881, 0x0016, + 0x85b2, 0x80f0, 0x9532, 0xfaa2, 0x1de2, 0x0014, 0x8532, 0xf221, + 0x0014, 0x1de2, 0x84a8, 0xd6e0, 0x1fe6, 0x0014, 0x3008, 0x8000, + 0x2849, 0x1011, 0xa8fc, 0x3008, 0x8000, 0xa000, 0x2081, 0x2802, + 0x1011, 0xa8fc, 0xa889, 0x3008, 0x20a1, 0x283c, 0x1011, 0xa8fc, + 0xa209, 0x0017, 0x300c, 0x8000, 0x85a4, 0x1de2, 0xdac1, 0x0014, + 0x0210, 0xa801, 0x0014, 0x26e0, 0x873a, 0xfaa3, 0x19f2, 0x26e0, + 0x18f2, 0x0014, 0xa20b, 0x0014, 0xa20d, 0x3806, 0x0210, 0x9d22, + 0x0704, 0xa206, 0x6865, 0x817e, 0x842a, 0x1dc1, 0x8823, 0x0016, + 0x6042, 0x8008, 0xa8fa, 0x8160, 0x842a, 0x8180, 0xf021, 0x3008, + 0x84a8, 0x11d7, 0x7042, 0x20dd, 0x0011, 0x20d5, 0x8822, 0x0016, + 0x0000, 0x0126, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x7204, + 0x7008, 0xc09c, 0xa205, 0x1178, 0x720c, 0x82ff, 0x0128, 0x8aff, + 0x1150, 0x7200, 0xd284, 0x1138, 0x7007, 0x0004, 0x7003, 0x0008, + 0x012e, 0x2000, 0x0005, 0x7000, 0xa084, 0x0003, 0x7002, 0xc69c, + 0xd084, 0x0588, 0x7108, 0xe000, 0x7008, 0xa106, 0x1dd8, 0xa184, + 0x0003, 0x0904, 0x3f50, 0xa184, 0x01e0, 0x1904, 0x3f50, 0xd1f4, + 0x1d88, 0xa184, 0x3000, 0xa086, 0x1000, 0x0d60, 0x2011, 0x0180, + 0x710c, 0x8211, 0x0130, 0x7008, 0xd0f4, 0x1d20, 0x700c, 0xa106, + 0x0dc0, 0x7007, 0x0012, 0x7108, 0xe000, 0x7008, 0xa106, 0x1dd8, + 0xa184, 0x0003, 0x0568, 0xd194, 0x0db0, 0xd1f4, 0x0548, 0x7007, + 0x0002, 0x0880, 0x0428, 0x7108, 0xd1fc, 0x0130, 0x080c, 0x4053, + 0x8aff, 0x0904, 0x3edf, 0x0cb8, 0x700c, 0xa08c, 0x07ff, 0x01e8, + 0x7004, 0xd084, 0x0178, 0x7014, 0xa005, 0x1148, 0x7010, 0x7310, + 0xa306, 0x1de0, 0x2300, 0xa005, 0x0128, 0xa102, 0x1e20, 0x7007, + 0x0010, 0x0030, 0x8aff, 0x0148, 0x080c, 0x4212, 0x1de8, 0x09d8, + 0x080c, 0x3fd9, 0x012e, 0x2000, 0x0005, 0x7204, 0x7108, 0xc19c, + 0x8103, 0x1218, 0x7007, 0x0002, 0x0cc0, 0xa205, 0x1d88, 0x7007, + 0x0004, 0x7003, 0x0008, 0x012e, 0x2000, 0x0005, 0x6428, 0x84ff, + 0x0508, 0x2c70, 0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x3f9a, 0x273c, + 0x87fb, 0x1148, 0x0210, 0x080c, 0x252b, 0x609c, 0xa075, 0x0190, + 0x0c88, 0x2039, 0x3f8f, 0x2704, 0xae68, 0x6808, 0xa630, 0x680c, + 0xa529, 0x8421, 0x0138, 0x8738, 0x2704, 0xa005, 0x1da8, 0x709c, + 0xa075, 0x1d00, 0x0005, 0x0000, 0x0005, 0x0009, 0x000d, 0x0011, + 0x0015, 0x0019, 0x001d, 0x0000, 0x0003, 0x0009, 0x000f, 0x0015, + 0x001b, 0x0000, 0x0000, 0x3f8f, 0x3f8c, 0x0000, 0x0000, 0x8000, + 0x0000, 0x3f8f, 0x0000, 0x3f97, 0x3f94, 0x0000, 0x0000, 0x0000, + 0x0000, 0x3f97, 0x0000, 0x3f92, 0x3f92, 0x0000, 0x0000, 0x8000, + 0x0000, 0x3f92, 0x0000, 0x3f98, 0x3f98, 0x0000, 0x0000, 0x0000, + 0x0000, 0x3f98, 0x2079, 0x4500, 0x2071, 0x0010, 0x7007, 0x000a, + 0x7007, 0x0002, 0x7003, 0x0001, 0x2009, 0x0002, 0x2071, 0x0050, + 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0000, 0x2001, 0x01ff, + 0x2004, 0xd0fc, 0x1128, 0x8109, 0x0118, 0x2071, 0x0020, 0x0c80, + 0x0005, 0x7004, 0x8004, 0x1a04, 0x402f, 0x7108, 0x7008, 0xa106, + 0x1de0, 0xa184, 0x01e0, 0x0120, 0x080c, 0x408b, 0x0804, 0x404f, + 0x7007, 0x0012, 0x2019, 0x0000, 0x7108, 0x7008, 0xa106, 0x1de0, + 0xa184, 0x01e0, 0x0120, 0x080c, 0x408b, 0x0804, 0x404f, 0xa19c, + 0x300c, 0xa386, 0x2004, 0x0190, 0xa386, 0x0008, 0x01c0, 0x7004, + 0xd084, 0x1148, 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x0003, + 0x0110, 0x0804, 0x408b, 0xa386, 0x200c, 0x19f0, 0x7200, 0x8204, + 0x0230, 0x730c, 0xa384, 0x07ff, 0x0110, 0x080c, 0x252b, 0x7108, + 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0, 0x0118, 0x080c, 0x408b, + 0x0470, 0x7007, 0x0012, 0x7000, 0xd084, 0x1148, 0x7310, 0x7014, + 0xa305, 0x0128, 0x710c, 0xa184, 0x07ff, 0x1904, 0x3fd9, 0x7108, + 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0, 0x0118, 0x080c, 0x408b, + 0x00b0, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xd09c, 0x1de8, + 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0, 0x0118, 0x080c, + 0x408b, 0x0028, 0x7007, 0x0012, 0x7108, 0x8103, 0x0e88, 0x7003, + 0x0008, 0x0005, 0x7108, 0xa184, 0x01e0, 0x15a8, 0x7108, 0xa184, + 0x01e0, 0x1588, 0xa184, 0x0007, 0x0002, 0x4067, 0x4075, 0x4065, + 0x4075, 0x4065, 0x40c5, 0x4065, 0x40c3, 0x080c, 0x252b, 0x7004, + 0xa084, 0x0010, 0xc08d, 0x7006, 0x8aff, 0x1118, 0x2049, 0x0000, + 0x0005, 0x080c, 0x4212, 0x1de8, 0x0005, 0x7004, 0xa084, 0x0010, + 0xc08d, 0x7006, 0x7004, 0xd084, 0x1140, 0x7108, 0x7008, 0xa106, + 0x1de0, 0xa184, 0x0003, 0x0108, 0x0030, 0x8aff, 0x0118, 0x080c, + 0x4212, 0x1de8, 0x0005, 0x7007, 0x0012, 0x7108, 0x1d04, 0x408e, + 0x2091, 0x6000, 0x1d04, 0x4092, 0x2091, 0x6000, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xd09c, 0x1de8, 0x7007, 0x0012, 0x7108, 0xd1fc, 0x1dd8, 0x7003, 0x0000, 0x7000, 0xa005, 0x1130, 0x7004, 0xa005, 0x1118, 0x700c, 0xa005, 0x0108, 0x0c40, 0x2049, 0x0000, 0xb284, 0x0200, 0x0118, 0x2001, 0x0000, 0x0010, 0x2001, 0x0001, - 0x080c, 0x397f, 0x6818, 0xa084, 0x8000, 0x0110, 0x681b, 0x0002, - 0x0005, 0x080c, 0x243b, 0x080c, 0x243b, 0x04b9, 0x7210, 0x7114, - 0x700c, 0xa09c, 0x07ff, 0x2800, 0xa300, 0xa211, 0xa189, 0x0000, - 0x0461, 0x2704, 0x2c58, 0xac60, 0x6308, 0x2200, 0xa322, 0x630c, - 0x2100, 0xa31b, 0x2400, 0xa305, 0x0140, 0x1238, 0x8412, 0x8210, - 0x830a, 0xa189, 0x0000, 0x2b60, 0x0c58, 0x2b60, 0x8a07, 0x0006, - 0x6004, 0xa084, 0x0008, 0x0118, 0xa7ba, 0x3e13, 0x0010, 0xa7ba, - 0x3e0b, 0x000e, 0xa73d, 0x2c00, 0x6886, 0x6f8a, 0x6c92, 0x6b8e, - 0x7007, 0x0012, 0x080c, 0x3e58, 0x0005, 0x8a50, 0x8739, 0x2704, + 0x080c, 0x3b47, 0x681b, 0x0002, 0x2051, 0x0000, 0x0005, 0x080c, + 0x252b, 0x080c, 0x252b, 0x080c, 0x4105, 0x7210, 0x7114, 0x700c, + 0xa09c, 0x07ff, 0x2800, 0xa300, 0xa211, 0xa189, 0x0000, 0x04a9, + 0x2704, 0x2c58, 0xac60, 0x6308, 0x2200, 0xa322, 0x630c, 0x2100, + 0xa31b, 0x2400, 0xa305, 0x0140, 0x1238, 0x8412, 0x8210, 0x830a, + 0xa189, 0x0000, 0x2b60, 0x0c58, 0x2b60, 0x8a07, 0x0006, 0x6004, + 0xa084, 0x0008, 0x0118, 0xa7ba, 0x3f94, 0x0010, 0xa7ba, 0x3f8c, + 0x000e, 0xa73d, 0x2c00, 0x6886, 0x6f8a, 0x6c92, 0x6b8e, 0x7108, + 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0, 0x0110, 0x080c, 0x408b, + 0x7007, 0x0012, 0x080c, 0x3fd9, 0x0005, 0x8a50, 0x8739, 0x2704, 0xa004, 0x1168, 0x6000, 0xa064, 0x1108, 0x2d60, 0x6004, 0xa084, - 0x000f, 0xa080, 0x3e29, 0x203c, 0x87fb, 0x090c, 0x243b, 0x0005, - 0x0126, 0x00d6, 0x70d4, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de, + 0x000f, 0xa080, 0x3faa, 0x203c, 0x87fb, 0x090c, 0x252b, 0x0005, + 0x0126, 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de, 0x6884, 0x2060, 0x6888, 0x6b8c, 0x6c90, 0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff, 0x0006, 0x6804, 0xa084, 0x0008, 0x000e, 0x0118, - 0xa0b8, 0x3e13, 0x0010, 0xa0b8, 0x3e0b, 0xb284, 0x0200, 0x0110, + 0xa0b8, 0x3f94, 0x0010, 0xa0b8, 0x3f8c, 0xb284, 0x0200, 0x0110, 0x7e20, 0x0008, 0x7e24, 0xa6b5, 0x000c, 0x681c, 0xd0b4, 0x0108, 0xc685, 0x2400, 0xa305, 0x0520, 0x2c58, 0x2704, 0x6104, 0xac60, 0x6000, 0xa400, 0x701a, 0x6004, 0xa301, 0x701e, 0xa184, 0x0008, 0x0140, 0x6010, 0xa081, 0x0000, 0x7022, 0x6014, 0xa081, 0x0000, 0x7026, 0x6208, 0x2400, 0xa202, 0x7012, 0x620c, 0x2300, 0xa203, - 0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x080c, 0x4067, 0x0010, - 0x080c, 0x4046, 0x1de8, 0x012e, 0x2000, 0x0005, 0x0126, 0x00d6, - 0x70d4, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de, 0x7007, 0x0004, + 0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x080c, 0x423a, 0x0010, + 0x080c, 0x4212, 0x1de8, 0x012e, 0x2000, 0x0005, 0x0126, 0x00d6, + 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de, 0x7007, 0x0004, 0x7004, 0xd094, 0x1de8, 0x7003, 0x0008, 0x012e, 0x2000, 0x0005, - 0x0126, 0x00d6, 0x70d4, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de, + 0x0126, 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de, 0x7e20, 0xb284, 0x0200, 0x1108, 0x7e24, 0xa6b5, 0x000c, 0x681c, 0xd0ac, 0x1118, 0xc685, 0x7003, 0x0000, 0x6828, 0x2050, 0x2d60, - 0x6004, 0xa0bc, 0x000f, 0xa7b8, 0x3e19, 0x273c, 0x87fb, 0x1138, - 0x0210, 0x080c, 0x243b, 0x689c, 0xa065, 0x0120, 0x0c88, 0x080c, - 0x4046, 0x1de8, 0x012e, 0x2000, 0x0005, 0x0126, 0x0006, 0x0016, - 0x00d6, 0x70d4, 0xa084, 0x4c00, 0x8004, 0x2090, 0x7e20, 0xb284, + 0x6004, 0xa0bc, 0x000f, 0xa7b8, 0x3f9a, 0x273c, 0x87fb, 0x1138, + 0x0210, 0x080c, 0x252b, 0x689c, 0xa065, 0x0120, 0x0c88, 0x080c, + 0x4212, 0x1de8, 0x012e, 0x2000, 0x0005, 0x0126, 0x0006, 0x0016, + 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x7e20, 0xb284, 0x0200, 0x1108, 0x7e24, 0x00de, 0x003e, 0x004e, 0xa6b5, 0x000c, 0x681c, 0xd0b4, 0x0128, 0xc685, 0x7003, 0x0000, 0x7007, 0x0004, - 0x2049, 0x3fe5, 0x6828, 0xa055, 0x05f0, 0x2d70, 0x2e60, 0x7004, - 0xa0bc, 0x000f, 0xa7b8, 0x3e19, 0x273c, 0x87fb, 0x1140, 0x0210, - 0x080c, 0x243b, 0x709c, 0xa075, 0x2060, 0x0568, 0x0c80, 0x2704, - 0xae68, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0268, 0x8a51, 0x1110, - 0x080c, 0x243b, 0x8738, 0x2704, 0xa005, 0x1d90, 0x709c, 0xa075, - 0x2060, 0x01c8, 0x08e0, 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, - 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, 0x1210, 0x080c, - 0x243b, 0xb284, 0x0200, 0x0118, 0x2071, 0x0050, 0x0010, 0x2071, - 0x0020, 0x0804, 0x3f79, 0x012e, 0x2000, 0x0005, 0x7008, 0xa084, - 0x0003, 0xa086, 0x0003, 0x1108, 0x0005, 0x2704, 0xac78, 0x7800, - 0x701a, 0x7804, 0x701e, 0x7808, 0x7012, 0x780c, 0x7016, 0x6004, - 0xa084, 0x0008, 0x0120, 0x7810, 0x7022, 0x7814, 0x7026, 0x7602, - 0x7004, 0xa084, 0x0010, 0xc085, 0x7006, 0x2079, 0x4300, 0x8a51, - 0x01b0, 0x8738, 0x2704, 0xa005, 0x1168, 0x609c, 0xa005, 0x0180, - 0x2060, 0x6004, 0xa084, 0x000f, 0xa080, 0x3e19, 0x203c, 0x87fb, - 0x090c, 0x243b, 0x7008, 0xa084, 0x0003, 0xa086, 0x0003, 0x0005, - 0x2051, 0x0000, 0x0005, 0x0126, 0x0006, 0x00d6, 0x70d4, 0xa084, - 0x4c00, 0x8004, 0x2090, 0x00de, 0x008e, 0x7108, 0xa184, 0x0003, - 0x1128, 0x6828, 0xa005, 0x0178, 0x0804, 0x3d6c, 0x7108, 0xd1fc, - 0x0118, 0x080c, 0x3e9e, 0x0c88, 0x7007, 0x0010, 0x7108, 0xd1fc, - 0x0de8, 0x080c, 0x3e9e, 0x7008, 0xa086, 0x0008, 0x1d30, 0x7000, - 0xa005, 0x1d18, 0x7003, 0x0000, 0x2049, 0x0000, 0x012e, 0x2000, - 0x0005, 0x0126, 0x0146, 0x0136, 0x0156, 0x00c6, 0x00d6, 0x70d4, - 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de, 0x2049, 0x40b1, 0xad80, - 0x0011, 0x20a0, 0xb284, 0x0200, 0x0118, 0x2099, 0x0032, 0x0010, - 0x2099, 0x0031, 0x700c, 0xa084, 0x07ff, 0x682a, 0x7007, 0x0008, - 0x7007, 0x0002, 0x7003, 0x0001, 0x0118, 0x8000, 0x80ac, 0x53a5, - 0x700c, 0xa084, 0x07ff, 0x0130, 0x7007, 0x0004, 0x7004, 0xa084, - 0x0004, 0x1de0, 0x00ce, 0x2049, 0x0000, 0x7003, 0x0000, 0x015e, - 0x013e, 0x014e, 0x012e, 0x2000, 0x0005, 0x2091, 0x8000, 0x2091, - 0x6000, 0x78ac, 0xa005, 0x1168, 0x7974, 0x70d0, 0xa106, 0x1148, - 0x781c, 0xa005, 0x0130, 0x781f, 0x0000, 0x0e04, 0x4101, 0x2091, - 0x4080, 0x7830, 0x8001, 0x7832, 0x1904, 0x416b, 0x7834, 0x7832, - 0x2061, 0x68c0, 0x2069, 0x4380, 0xc7fd, 0x68d0, 0xa005, 0x0128, - 0x8001, 0x68d2, 0x1110, 0x080c, 0x42c4, 0x6800, 0xa084, 0x000f, - 0x0168, 0xa086, 0x0001, 0x0150, 0x6844, 0xa00d, 0x0138, 0x2104, - 0xa005, 0x0120, 0x8001, 0x200a, 0x0904, 0x425f, 0x6814, 0xa005, - 0x01a8, 0x8001, 0x6816, 0x1190, 0x68a7, 0x0001, 0x00f6, 0xd7fc, - 0x1118, 0x2079, 0x0200, 0x0010, 0x2079, 0x0100, 0x080c, 0x3aa0, - 0x00fe, 0x6864, 0xa005, 0x0110, 0x080c, 0x2233, 0x6880, 0xa005, - 0x0140, 0x8001, 0x6882, 0x1128, 0x6867, 0x0000, 0x68d4, 0xc0c5, - 0x68d6, 0x68d4, 0xd0fc, 0x01b0, 0xc0fc, 0x68d6, 0x20a9, 0x0200, - 0x6034, 0xa005, 0x0158, 0x8001, 0x6036, 0x68d4, 0xc0fd, 0x68d6, - 0x1128, 0x6010, 0xa005, 0x0110, 0x080c, 0x2233, 0xace0, 0x0010, - 0x1f04, 0x4150, 0xd7fc, 0x0138, 0x2061, 0x48c0, 0x2069, 0x4340, - 0xc7fc, 0x0804, 0x410d, 0x0459, 0x7838, 0x8001, 0x783a, 0x11a0, - 0x783c, 0x783a, 0x2061, 0x48c0, 0x2069, 0x4340, 0xc7fc, 0x680c, - 0xa005, 0x0110, 0x080c, 0x41c9, 0xd7fc, 0x1130, 0x2061, 0x68c0, - 0x2069, 0x4380, 0xc7fd, 0x0c98, 0x7810, 0xd0cc, 0x0168, 0xd0ac, - 0x1120, 0xd0a4, 0x0148, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0e04, - 0x4193, 0x080c, 0x1ffe, 0x0005, 0x2091, 0x8001, 0x0005, 0x7840, - 0x8001, 0x7842, 0x1568, 0x7844, 0x7842, 0x2091, 0x8000, 0x2061, - 0x48c0, 0x2069, 0x4340, 0xc7fc, 0x6810, 0xa005, 0x1110, 0x2001, - 0x0101, 0x8001, 0x6812, 0xd7fc, 0x0118, 0xa080, 0x89d0, 0x0010, - 0xa080, 0x88c0, 0x2040, 0x2004, 0xa065, 0x0150, 0x6024, 0xa005, - 0x0120, 0x8001, 0x6026, 0x0904, 0x4207, 0x6000, 0x2c40, 0x0ca0, - 0xd7fc, 0x1130, 0x2061, 0x68c0, 0x2069, 0x4380, 0xc7fd, 0x08e0, - 0x0005, 0x2009, 0x0000, 0x20a9, 0x0200, 0x6008, 0xd09c, 0x0540, - 0x6024, 0xa005, 0x0118, 0x8001, 0x6026, 0x0400, 0x6008, 0xc09c, - 0xd084, 0x1110, 0xd0ac, 0x01a8, 0x600a, 0x6004, 0xa06d, 0x01c0, - 0x00c6, 0x0016, 0x6010, 0x8001, 0x6012, 0x080c, 0x35ab, 0x2d00, - 0x2c68, 0x2060, 0x080c, 0x1b85, 0x080c, 0x1d30, 0x001e, 0x00ce, - 0x0038, 0xc0bd, 0x600a, 0xa18d, 0x0001, 0x0010, 0xa18d, 0x0100, - 0xace0, 0x0010, 0x1f04, 0x41cd, 0xa184, 0x0001, 0x0130, 0xa18c, - 0xfffe, 0x690e, 0x080c, 0x2233, 0x0008, 0x690e, 0x0005, 0x6800, - 0xa005, 0x0120, 0x684c, 0xac06, 0x0904, 0x425f, 0x6864, 0xa005, - 0x0120, 0x6027, 0x0001, 0x0804, 0x425c, 0x2c00, 0x687e, 0x6714, - 0x6f76, 0x6017, 0x0000, 0x602b, 0x0000, 0x601b, 0x0006, 0x60b4, - 0xa084, 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085, 0x0060, - 0x6022, 0x6000, 0x2042, 0x080c, 0x1b1d, 0x6818, 0xa005, 0x0110, - 0x8001, 0x681a, 0x6808, 0xc0a4, 0x680a, 0x6810, 0x7908, 0x8109, - 0x790a, 0x8001, 0x1310, 0x080c, 0x243b, 0x6812, 0x1118, 0x7910, - 0xc1a5, 0x7912, 0x602f, 0x0000, 0x6033, 0x0000, 0x2c68, 0x080c, - 0x1d3d, 0xd7fc, 0x1118, 0x2069, 0x4340, 0x0010, 0x2069, 0x4380, - 0x6910, 0xa184, 0x0100, 0x2001, 0x0006, 0x1118, 0x697a, 0x2001, - 0x0004, 0x2708, 0x080c, 0x2228, 0x2091, 0x8001, 0x0005, 0x00d6, - 0x694c, 0x2160, 0xd7fc, 0x1118, 0x2069, 0x0200, 0x0010, 0x2069, - 0x0100, 0x080c, 0x23e1, 0x601b, 0x0006, 0x6858, 0xa084, 0x3f00, - 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085, 0x0048, 0x6022, 0x602f, - 0x0000, 0x6033, 0x0000, 0x6830, 0xd0b4, 0x01b0, 0x684b, 0x0004, - 0x20a9, 0x0014, 0x6848, 0xd094, 0x0110, 0x1f04, 0x4282, 0x684b, - 0x0009, 0x20a9, 0x0014, 0x6848, 0xd084, 0x0110, 0x1f04, 0x428b, - 0x20a9, 0x00fa, 0x1f04, 0x4292, 0x6808, 0xa084, 0xfffd, 0x680a, - 0x681b, 0x0054, 0x00de, 0x6867, 0x0007, 0x2091, 0x8001, 0x0005, - 0x2079, 0x4300, 0x00e1, 0x0089, 0x00a9, 0x2009, 0x0002, 0x2069, - 0x4380, 0x680f, 0x0000, 0x6813, 0x0000, 0x6817, 0x0000, 0x8109, - 0x0118, 0x2069, 0x4340, 0x0ca8, 0x0005, 0x2019, 0x00a3, 0x7b3a, - 0x7b3e, 0x0005, 0x2019, 0x0033, 0x7b42, 0x7b46, 0x0005, 0x2019, - 0x32dd, 0x7b32, 0x7b36, 0x0005, 0x6950, 0xa185, 0x0000, 0x0178, - 0x00c6, 0x6ac0, 0x2264, 0x602b, 0x0000, 0x602f, 0x0000, 0x6008, - 0xc0b5, 0x600a, 0x8210, 0x8109, 0x1da8, 0x6952, 0x00ce, 0x0005, - 0x70ec, 0xd0dc, 0x1118, 0xd0d4, 0x0180, 0x0088, 0xae8e, 0x0100, - 0x0130, 0x7814, 0xc0f5, 0x7816, 0xd0d4, 0x1170, 0x0050, 0x7814, - 0xc0fd, 0x7816, 0xd0d4, 0x1140, 0x0020, 0xd0e4, 0x0138, 0x70a0, - 0x70a2, 0x7804, 0xd08c, 0x0110, 0x681f, 0x000c, 0x0005, 0xaf67 + 0x2049, 0x41ad, 0x6828, 0xa055, 0x00d6, 0x0904, 0x420e, 0x2d70, + 0x2e60, 0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x3f9a, 0x273c, 0x87fb, + 0x1140, 0x0210, 0x080c, 0x252b, 0x709c, 0xa075, 0x2060, 0x0570, + 0x0c80, 0x2704, 0xae68, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0268, + 0x8a51, 0x1110, 0x080c, 0x252b, 0x8738, 0x2704, 0xa005, 0x1d90, + 0x709c, 0xa075, 0x2060, 0x01d0, 0x08e0, 0x8422, 0x8420, 0x831a, + 0xa399, 0x0000, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, + 0x1210, 0x080c, 0x252b, 0xb284, 0x0200, 0x0118, 0x2071, 0x0050, + 0x0010, 0x2071, 0x0020, 0x00de, 0x0804, 0x4141, 0x00de, 0x012e, + 0x2000, 0x0005, 0x7008, 0x0006, 0xa084, 0x01e0, 0x000e, 0x0110, + 0xa006, 0x0005, 0xa084, 0x0003, 0xa086, 0x0003, 0x1108, 0x0005, + 0x2704, 0xac78, 0x7800, 0x701a, 0x7804, 0x701e, 0x7808, 0x7012, + 0x780c, 0x7016, 0x6004, 0xa084, 0x0008, 0x0120, 0x7810, 0x7022, + 0x7814, 0x7026, 0x7602, 0x7004, 0xa084, 0x0010, 0xc085, 0x7006, + 0x2079, 0x4500, 0x8a51, 0x01e8, 0x8738, 0x2704, 0xa005, 0x1168, + 0x609c, 0xa005, 0x01b8, 0x2060, 0x6004, 0xa084, 0x000f, 0xa080, + 0x3f9a, 0x203c, 0x87fb, 0x090c, 0x252b, 0x7008, 0x0006, 0xa084, + 0x01e0, 0x000e, 0x0110, 0xa006, 0x0028, 0xa084, 0x0003, 0xa086, + 0x0003, 0x0005, 0x2051, 0x0000, 0x0005, 0x0126, 0x0006, 0x00d6, + 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de, 0x008e, 0x7108, + 0xa184, 0x0003, 0x1128, 0x6828, 0xa005, 0x0178, 0x0804, 0x3ef3, + 0x7108, 0xd1fc, 0x0118, 0x080c, 0x4053, 0x0c88, 0x7007, 0x0010, + 0x7108, 0xd1fc, 0x0de8, 0x080c, 0x4053, 0x7008, 0xa086, 0x0008, + 0x1d30, 0x7000, 0xa005, 0x1d18, 0x7003, 0x0000, 0x2049, 0x0000, + 0x012e, 0x2000, 0x0005, 0x0126, 0x0146, 0x0136, 0x0156, 0x00c6, + 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de, 0x2049, + 0x428b, 0xad80, 0x0011, 0x20a0, 0xb284, 0x0200, 0x0118, 0x2099, + 0x0032, 0x0010, 0x2099, 0x0031, 0x700c, 0xa084, 0x07ff, 0x682a, + 0x7007, 0x0008, 0x7007, 0x0002, 0x7003, 0x0001, 0x0118, 0x8000, + 0x80ac, 0x53a5, 0x700c, 0xa084, 0x07ff, 0x0130, 0x7007, 0x0004, + 0x7004, 0xa084, 0x0004, 0x1de0, 0x00ce, 0x2049, 0x0000, 0x7003, + 0x0000, 0x015e, 0x013e, 0x014e, 0x012e, 0x2000, 0x0005, 0x2091, + 0x8000, 0x2091, 0x6000, 0x78ac, 0xa005, 0x1168, 0x7974, 0x70d0, + 0xa106, 0x1148, 0x781c, 0xa005, 0x0130, 0x781f, 0x0000, 0x0e04, + 0x42db, 0x2091, 0x4080, 0x7830, 0x8001, 0x7832, 0x1904, 0x4345, + 0x7834, 0x7832, 0x2061, 0x6ac0, 0x2069, 0x4580, 0xc7fd, 0x68cc, + 0xa005, 0x0128, 0x8001, 0x68ce, 0x1110, 0x080c, 0x44ad, 0x6800, + 0xa084, 0x000f, 0x0168, 0xa086, 0x0001, 0x0150, 0x6840, 0xa00d, + 0x0138, 0x2104, 0xa005, 0x0120, 0x8001, 0x200a, 0x0904, 0x444a, + 0x6814, 0xa005, 0x01a8, 0x8001, 0x6816, 0x1190, 0x68a3, 0x0001, + 0x00f6, 0xd7fc, 0x1118, 0x2079, 0x0200, 0x0010, 0x2079, 0x0100, + 0x080c, 0x3c0c, 0x00fe, 0x6860, 0xa005, 0x0110, 0x080c, 0x2296, + 0x687c, 0xa005, 0x0140, 0x8001, 0x687e, 0x1128, 0x6863, 0x0000, + 0x68d0, 0xc0c5, 0x68d2, 0x68d0, 0xd0fc, 0x01b0, 0xc0fc, 0x68d2, + 0x20a9, 0x0200, 0x6034, 0xa005, 0x0158, 0x8001, 0x6036, 0x68d0, + 0xc0fd, 0x68d2, 0x1128, 0x6010, 0xa005, 0x0110, 0x080c, 0x2296, + 0xace0, 0x0010, 0x1f04, 0x432a, 0xd7fc, 0x0138, 0x2061, 0x4ac0, + 0x2069, 0x4540, 0xc7fc, 0x0804, 0x42e7, 0x0459, 0x7838, 0x8001, + 0x783a, 0x11a0, 0x783c, 0x783a, 0x2061, 0x4ac0, 0x2069, 0x4540, + 0xc7fc, 0x680c, 0xa005, 0x0110, 0x080c, 0x43c1, 0xd7fc, 0x1130, + 0x2061, 0x6ac0, 0x2069, 0x4580, 0xc7fd, 0x0c98, 0x7810, 0xd0cc, + 0x0168, 0xd0ac, 0x1120, 0xd0a4, 0x0148, 0xc0ad, 0x7812, 0x2091, + 0x8001, 0x0e04, 0x436d, 0x080c, 0x2061, 0x0005, 0x2091, 0x8001, + 0x0005, 0x7840, 0x8001, 0x7842, 0x1904, 0x43c0, 0x7844, 0x7842, + 0x2069, 0x4540, 0xc7fc, 0x2079, 0x0200, 0x68d4, 0xa005, 0x0138, + 0x7de0, 0xa504, 0x1120, 0x68d6, 0x68d0, 0xc0bc, 0x68d2, 0x2079, + 0x4500, 0x6810, 0xa005, 0x1110, 0x2001, 0x0101, 0x8001, 0x6812, + 0xd7fc, 0x0118, 0xa080, 0x8bd0, 0x0010, 0xa080, 0x8ac0, 0x2040, + 0x2004, 0xa065, 0x01e0, 0x6024, 0xa005, 0x01b0, 0x8001, 0x6026, + 0x1198, 0x6800, 0xa005, 0x0130, 0x6848, 0xac06, 0x1118, 0x080c, + 0x444a, 0x0068, 0x6860, 0xa005, 0x0118, 0x6027, 0x0001, 0x0020, + 0x080c, 0x4402, 0x2804, 0x0c28, 0x6000, 0x2c40, 0x0c10, 0xd7fc, + 0x1138, 0x2069, 0x4580, 0xc7fd, 0x2079, 0x0100, 0x0804, 0x437d, + 0x0005, 0x2009, 0x0000, 0x20a9, 0x0200, 0x6008, 0xd09c, 0x0558, + 0x6024, 0xa005, 0x0118, 0x8001, 0x6026, 0x0418, 0x6008, 0xc09c, + 0xd084, 0x1110, 0xd0ac, 0x01c0, 0x600a, 0x6004, 0xa005, 0x01d8, + 0x00d6, 0x00c6, 0x0016, 0x2068, 0x6010, 0x8001, 0x6012, 0x080c, + 0x376c, 0x2d00, 0x2c68, 0x2060, 0x080c, 0x1bc7, 0x080c, 0x1d7c, + 0x001e, 0x00ce, 0x00de, 0x0038, 0xc0bd, 0x600a, 0xa18d, 0x0001, + 0x0010, 0xa18d, 0x0100, 0xace0, 0x0010, 0x1f04, 0x43c5, 0xa184, + 0x0001, 0x0130, 0xa18c, 0xfffe, 0x690e, 0x080c, 0x2296, 0x0008, + 0x690e, 0x0005, 0x2c00, 0x687a, 0x6714, 0x6f72, 0x6017, 0x0000, + 0x602b, 0x0000, 0x601b, 0x0006, 0x60b4, 0xa084, 0x5f00, 0x601e, + 0x6020, 0xa084, 0x00ff, 0xa085, 0x0060, 0x6022, 0x6000, 0x2042, + 0x080c, 0x1b5f, 0x6818, 0xa005, 0x0110, 0x8001, 0x681a, 0x6808, + 0xc0a4, 0x680a, 0x6810, 0x7908, 0x8109, 0x790a, 0x8001, 0x1310, + 0x080c, 0x252b, 0x6812, 0x1118, 0x7910, 0xc1a5, 0x7912, 0x602f, + 0x0000, 0x6033, 0x0000, 0x2c68, 0x080c, 0x1d89, 0xd7fc, 0x1118, + 0x2069, 0x4540, 0x0010, 0x2069, 0x4580, 0x6910, 0xa184, 0x0100, + 0x2001, 0x0006, 0x1118, 0x6976, 0x2001, 0x0004, 0x2708, 0x080c, + 0x228b, 0x0005, 0x00d6, 0x6948, 0x2160, 0xd7fc, 0x1118, 0x2069, + 0x0200, 0x0010, 0x2069, 0x0100, 0x080c, 0x2446, 0x601b, 0x0006, + 0x6858, 0xa084, 0x5f00, 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085, + 0x0048, 0x6022, 0x602f, 0x0000, 0x6033, 0x0000, 0x6808, 0xa084, + 0xfffd, 0x680a, 0x6830, 0xd0b4, 0x01b0, 0x684b, 0x0004, 0x20a9, + 0x0014, 0x6848, 0xd094, 0x0110, 0x1f04, 0x4471, 0x684b, 0x0009, + 0x20a9, 0x0014, 0x6848, 0xd084, 0x0110, 0x1f04, 0x447a, 0x20a9, + 0x00fa, 0x1f04, 0x4481, 0x681b, 0x0054, 0x00de, 0x6863, 0x0007, + 0x0005, 0x2079, 0x4500, 0x00e1, 0x0089, 0x00a9, 0x2009, 0x0002, + 0x2069, 0x4580, 0x680f, 0x0000, 0x6813, 0x0000, 0x6817, 0x0000, + 0x8109, 0x0118, 0x2069, 0x4540, 0x0ca8, 0x0005, 0x2019, 0x00a3, + 0x7b3a, 0x7b3e, 0x0005, 0x2019, 0x0033, 0x7b42, 0x7b46, 0x0005, + 0x2019, 0x32dd, 0x7b32, 0x7b36, 0x0005, 0x694c, 0xa185, 0x0000, + 0x0158, 0x00c6, 0x6abc, 0x2264, 0x6008, 0xc0b5, 0x600a, 0x8210, + 0x8109, 0x1dc8, 0x694e, 0x00ce, 0x0005, 0x70ec, 0xd0dc, 0x1118, + 0xd0d4, 0x0190, 0x0098, 0xae8e, 0x0100, 0x0138, 0x7814, 0xc0f5, + 0xc0c5, 0x7816, 0xd0d4, 0x11a8, 0x0088, 0x7814, 0xc0fd, 0xc0c5, + 0x7816, 0xd0d4, 0x1170, 0x0050, 0xd0e4, 0x0168, 0x70e4, 0xa084, + 0x01ff, 0xa086, 0x01ff, 0x0d38, 0x70a0, 0x70a2, 0x7804, 0xd08c, + 0x0110, 0x681f, 0x000c, 0x0005, 0x69ca }; #ifdef UNIQUE_FW_NAME -unsigned short fw12160i_length01 = 0x32f8; +unsigned short fw12160i_length01 = 0x34e5; #else -unsigned short risc_code_length01 = 0x32f8; +unsigned short risc_code_length01 = 0x34e5; #endif diff -urN linux-2.4.0-test10/drivers/scsi/ql1280_fw.h linux-2.4.0-test10-lia/drivers/scsi/ql1280_fw.h --- linux-2.4.0-test10/drivers/scsi/ql1280_fw.h Mon Feb 7 19:45:28 2000 +++ linux-2.4.0-test10-lia/drivers/scsi/ql1280_fw.h Mon Oct 30 22:17:11 2000 @@ -1,59 +1,117 @@ /************************************************************************ + * * + * --- ISP1240/1080/1280 Initiator Firmware --- * + * 32 LUN Support * + * * + ************************************************************************ - * Copyright (C) 1999,2000 Qlogic, Corporation. + + * * + + * Copyright (C) 1999,2000 Qlogic, Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted provided + * that the following conditions are met: + * 1. Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. - * 2. The name of the author may not be used to endorse or promote products + + * 2. Redistribution in binary form must reproduce the above copyright + + * notice, this list of conditions and the following disclaimer in the + + * documentation and/or other materials provided with the distribution. + + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * * + ************************************************************************ + */ /* - * Firmware Version 8.09.00 (18:29 Apr 16, 1999) + * Firmware Version 8.13.08 (10:53 Jan 14, 2000) */ -unsigned short fw1280ei_version = 8*1024+9; +#ifdef UNIQUE_FW_NAME +unsigned short fw1280ei_version = 8*1024+13; +#else +unsigned short risc_code_version = 8*1024+13; +#endif + +#ifdef UNIQUE_FW_NAME +unsigned char fw1280ei_version_str[] = {8,13,8}; +#else +unsigned char firmware_version[] = {8,13,8}; +#endif -unsigned char fw1280ei_version_str[] = {8,9,0}; +#ifdef UNIQUE_FW_NAME +#define fw1280ei_VERSION_STRING "8.13.8" +#else +#define FW_VERSION_STRING "8.13.8" +#endif +#ifdef UNIQUE_FW_NAME unsigned short fw1280ei_addr01 = 0x1000 ; +#else +unsigned short risc_code_addr01 = 0x1000 ; +#endif +#ifdef UNIQUE_FW_NAME unsigned short fw1280ei_code01[] = { - 0x0078, 0x1041, 0x0000, 0x39e3, 0x0000, 0x2043, 0x4f50, 0x5952, +#else +unsigned short risc_code01[] = { +#endif + 0x0078, 0x1041, 0x0000, 0x3c71, 0x0000, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932, 0x2c31, 0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749, 0x4320, 0x434f, 0x5250, 0x4f52, 0x4154, 0x494f, 0x4e00, 0x2049, 0x5350, 0x3132, 0x3430, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, 0x2056, - 0x6572, 0x7369, 0x6f6e, 0x2030, 0x382e, 0x3039, 0x2020, 0x2043, + 0x6572, 0x7369, 0x6f6e, 0x2030, 0x382e, 0x3133, 0x2020, 0x2043, 0x7573, 0x746f, 0x6d65, 0x7220, 0x4e6f, 0x2e20, 0x3030, 0x2050, 0x726f, 0x6475, 0x6374, 0x204e, 0x6f2e, 0x2020, 0x3030, 0x2020, - 0x2400, 0x20c9, 0x93ff, 0x2001, 0x04fc, 0x2004, 0xa086, 0x1080, + 0x2400, 0x20c9, 0x96ff, 0x2001, 0x04fc, 0x2004, 0xa086, 0x1080, 0x00c0, 0x1054, 0x2071, 0x0100, 0x70a0, 0x70a2, 0x20c1, 0x0010, - 0x2089, 0x136a, 0x0078, 0x106d, 0x2001, 0x04fc, 0x2004, 0xa086, + 0x2089, 0x1374, 0x0078, 0x106d, 0x2001, 0x04fc, 0x2004, 0xa086, 0x1280, 0x00c0, 0x1069, 0x2071, 0x0200, 0x70a0, 0x70a2, 0x2071, - 0x0100, 0x70a0, 0x70a2, 0x20c1, 0x0010, 0x2089, 0x13ea, 0x0078, - 0x106d, 0x20c1, 0x0020, 0x2089, 0x1312, 0x2071, 0x0010, 0x70c3, + 0x0100, 0x70a0, 0x70a2, 0x20c1, 0x0010, 0x2089, 0x13f8, 0x0078, + 0x106d, 0x20c1, 0x0020, 0x2089, 0x131c, 0x2071, 0x0010, 0x70c3, 0x0004, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, 0x0008, 0x2001, 0x04fe, 0x70d6, 0x20c1, 0x0021, 0x2019, 0x0000, 0x2009, 0xfeff, 0x2100, 0x200b, 0xa5a5, 0xa1ec, 0x7fff, 0x2d64, @@ -61,1838 +119,1924 @@ 0xa286, 0xa5a5, 0x0040, 0x10a4, 0xa386, 0x000f, 0x0040, 0x10a0, 0x2c6a, 0x2a5a, 0x20c1, 0x0020, 0x2019, 0x000f, 0x0078, 0x1080, 0x2c6a, 0x2a5a, 0x0078, 0x10a2, 0x2c6a, 0x2a5a, 0x2130, 0x2128, - 0xa1a2, 0x4a00, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, - 0xa192, 0x9400, 0x2009, 0x0000, 0x2001, 0x0032, 0x1078, 0x2078, - 0x2218, 0x2079, 0x4a00, 0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9, - 0x0040, 0x42a4, 0x8109, 0x00c0, 0x10bf, 0x2001, 0x04fc, 0x2004, - 0xa086, 0x1080, 0x00c0, 0x10db, 0x2071, 0x0100, 0x0d7e, 0x2069, - 0x4a40, 0x1078, 0x49ae, 0x0d7f, 0x7810, 0xc0ed, 0x7812, 0x781b, - 0x0064, 0x0078, 0x1100, 0x2001, 0x04fc, 0x2004, 0xa086, 0x1280, - 0x00c0, 0x10fb, 0x7814, 0xc0ed, 0xc0d5, 0x7816, 0x781b, 0x0064, - 0x2071, 0x0200, 0x0d7e, 0x2069, 0x4a40, 0x1078, 0x49ae, 0x2069, - 0x4a80, 0x2071, 0x0100, 0x1078, 0x49ae, 0x7814, 0xc0d4, 0x7816, - 0x0d7f, 0x0078, 0x1100, 0x7814, 0xc0e5, 0x7816, 0x781b, 0x003c, - 0x7eca, 0x7cc2, 0x7bc6, 0x7867, 0x0000, 0x7800, 0xc08d, 0x7802, - 0x2031, 0x0030, 0x78af, 0x0101, 0x7823, 0x0002, 0x7827, 0x0002, - 0x2009, 0x0002, 0x2069, 0x4a40, 0x681b, 0x0003, 0x6823, 0x0007, - 0x6827, 0x00fa, 0x682b, 0x0008, 0x682f, 0x0028, 0x6837, 0x0000, - 0x683b, 0x0006, 0x6833, 0x0008, 0x683f, 0x0000, 0x8109, 0x0040, - 0x1154, 0x68d3, 0x000a, 0x68c3, 0x4ac0, 0x2079, 0x4a00, 0x7814, - 0xd0e4, 0x00c0, 0x113a, 0xd0ec, 0x00c0, 0x113e, 0x68d7, 0x7329, - 0x0078, 0x1140, 0x68d7, 0x730d, 0x0078, 0x1140, 0x68d7, 0x7329, - 0x68c7, 0x4fc0, 0x68cb, 0x4ec0, 0x68cf, 0x8fc0, 0x68ab, 0x9244, - 0x68af, 0x9249, 0x68b3, 0x9244, 0x68b7, 0x9244, 0x68a7, 0x0001, - 0x2069, 0x4a80, 0x0078, 0x1114, 0x68d3, 0x000a, 0x68c3, 0x4cc0, - 0x7814, 0xd0e4, 0x00c0, 0x1160, 0x68d7, 0x7439, 0x0078, 0x1162, - 0x68d7, 0x7419, 0x68c7, 0x6fc0, 0x68cb, 0x4f40, 0x68cf, 0x90d0, - 0x68ab, 0x9249, 0x68af, 0x924e, 0x68b3, 0x9249, 0x68b7, 0x9249, - 0x68a7, 0x0001, 0x7810, 0xd0ec, 0x00c0, 0x11b8, 0x7814, 0xd0e4, - 0x00c0, 0x11aa, 0x0e7e, 0x2069, 0x4ec0, 0x2071, 0x0200, 0x70ec, - 0xd0e4, 0x00c0, 0x118b, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x1078, - 0x2007, 0x0078, 0x1191, 0x2019, 0x0c0a, 0x2021, 0x000a, 0x1078, - 0x2007, 0x2069, 0x4f40, 0x2071, 0x0100, 0x70ec, 0xd0e4, 0x00c0, - 0x11a1, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x1078, 0x2007, 0x0078, - 0x11a7, 0x2019, 0x0c0a, 0x2021, 0x000a, 0x1078, 0x2007, 0x0e7f, - 0x0078, 0x11d1, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x2069, 0x4ec0, - 0x1078, 0x2007, 0x2069, 0x4f40, 0x1078, 0x2007, 0x0078, 0x11d1, - 0x2069, 0x4ec0, 0x0e7e, 0x2071, 0x0100, 0x70ec, 0xd0e4, 0x00c0, - 0x11ca, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x1078, 0x2007, 0x0e7f, - 0x0078, 0x11d1, 0x2019, 0x0c0a, 0x2021, 0x000a, 0x1078, 0x2007, - 0x0e7f, 0x2011, 0x0002, 0x2069, 0x4fc0, 0x2009, 0x0002, 0x20a9, - 0x0100, 0x683f, 0x0000, 0x680b, 0x0040, 0x7bc8, 0xa386, 0xfeff, - 0x00c0, 0x11e8, 0x6817, 0x0100, 0x681f, 0x0064, 0x0078, 0x11ec, - 0x6817, 0x0064, 0x681f, 0x0002, 0xade8, 0x0010, 0x00f0, 0x11d9, - 0x8109, 0x00c0, 0x11d7, 0x8211, 0x0040, 0x11fa, 0x2069, 0x6fc0, - 0x0078, 0x11d5, 0x1078, 0x2611, 0x1078, 0x441d, 0x1078, 0x1df2, - 0x1078, 0x4957, 0x2091, 0x2100, 0x2079, 0x4a00, 0x7810, 0xd0ec, - 0x0040, 0x120e, 0x2071, 0x0020, 0x0078, 0x1210, 0x2071, 0x0050, - 0x2091, 0x2200, 0x2079, 0x4a00, 0x2071, 0x0020, 0x2091, 0x2300, - 0x2079, 0x4a00, 0x7810, 0xd0ec, 0x0040, 0x1222, 0x2079, 0x0100, - 0x0078, 0x1224, 0x2079, 0x0200, 0x2071, 0x4a40, 0x2091, 0x2400, - 0x2079, 0x0100, 0x2071, 0x4a80, 0x2091, 0x2000, 0x2079, 0x4a00, - 0x2071, 0x0010, 0x3200, 0xa085, 0x303d, 0x2090, 0x2071, 0x0010, - 0x70c3, 0x0000, 0x0090, 0x1243, 0x70c0, 0xa086, 0x0002, 0x00c0, - 0x1243, 0x1078, 0x159d, 0x2039, 0x0000, 0x7810, 0xd0ec, 0x00c0, - 0x12c5, 0x1078, 0x1472, 0x78ac, 0xa005, 0x00c0, 0x1261, 0x0068, - 0x1257, 0x786c, 0xa065, 0x0040, 0x1257, 0x1078, 0x2368, 0x1078, - 0x209f, 0x0068, 0x126e, 0x786c, 0xa065, 0x0040, 0x1261, 0x1078, - 0x2368, 0x0068, 0x126e, 0x2009, 0x4a47, 0x2011, 0x4a87, 0x2104, - 0x220c, 0xa105, 0x0040, 0x126e, 0x1078, 0x1f1e, 0x2071, 0x4a40, - 0x70a4, 0xa005, 0x0040, 0x1293, 0x7450, 0xa485, 0x0000, 0x0040, - 0x1293, 0x2079, 0x0200, 0x2091, 0x8000, 0x72d4, 0xa28c, 0x303d, - 0x2190, 0x1078, 0x2a9c, 0x2091, 0x8000, 0x2091, 0x303d, 0x0068, - 0x1293, 0x2079, 0x4a00, 0x786c, 0xa065, 0x0040, 0x1293, 0x2071, - 0x0010, 0x1078, 0x2368, 0x00e0, 0x129b, 0x2079, 0x4a00, 0x2071, - 0x0010, 0x1078, 0x4765, 0x2071, 0x4a80, 0x70a4, 0xa005, 0x0040, - 0x12b3, 0x7050, 0xa025, 0x0040, 0x12b3, 0x2079, 0x0100, 0x2091, - 0x8000, 0x72d4, 0xa28c, 0x303d, 0x2190, 0x1078, 0x2a9c, 0x2091, - 0x8000, 0x2091, 0x303d, 0x2079, 0x4a00, 0x2071, 0x0010, 0x0068, - 0x12bf, 0x786c, 0xa065, 0x0040, 0x12bf, 0x1078, 0x2368, 0x00e0, - 0x1249, 0x1078, 0x4765, 0x0078, 0x1249, 0x1078, 0x1472, 0x78ac, - 0xa005, 0x00c0, 0x12dd, 0x0068, 0x12d3, 0x786c, 0xa065, 0x0040, - 0x12d3, 0x1078, 0x2368, 0x1078, 0x209f, 0x0068, 0x12e7, 0x786c, - 0xa065, 0x0040, 0x12dd, 0x1078, 0x2368, 0x0068, 0x12e7, 0x2009, - 0x4a47, 0x2104, 0xa005, 0x0040, 0x12e7, 0x1078, 0x1f1e, 0x2071, - 0x4a40, 0x70a4, 0xa005, 0x0040, 0x1302, 0x7450, 0xa485, 0x0000, - 0x0040, 0x1302, 0x2079, 0x0100, 0x2091, 0x8000, 0x72d4, 0xa28c, - 0x303d, 0x2190, 0x1078, 0x2a9c, 0x2091, 0x8000, 0x2091, 0x303d, - 0x2079, 0x4a00, 0x2071, 0x0010, 0x0068, 0x130c, 0x786c, 0xa065, - 0x0040, 0x130c, 0x1078, 0x2368, 0x00e0, 0x12c5, 0x1078, 0x4765, - 0x0078, 0x12c5, 0x1332, 0x1332, 0x1334, 0x1334, 0x1341, 0x1341, - 0x1341, 0x1341, 0x134c, 0x134c, 0x1359, 0x1359, 0x1341, 0x1341, - 0x1341, 0x1341, 0x1332, 0x1332, 0x1334, 0x1334, 0x1341, 0x1341, - 0x1341, 0x1341, 0x134c, 0x134c, 0x1359, 0x1359, 0x1341, 0x1341, - 0x1341, 0x1341, 0x0078, 0x1332, 0x007e, 0x107e, 0x127e, 0x2091, - 0x2400, 0x1078, 0x290b, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, - 0x007c, 0x007e, 0x107e, 0x127e, 0x1078, 0x13ba, 0x127f, 0x107f, - 0x007f, 0x2091, 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x2091, - 0x2300, 0x1078, 0x290b, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, - 0x007c, 0x007e, 0x107e, 0x127e, 0x2091, 0x2300, 0x1078, 0x290b, - 0x2091, 0x2400, 0x1078, 0x290b, 0x127f, 0x107f, 0x007f, 0x2091, - 0x8001, 0x007c, 0x138a, 0x138a, 0x138c, 0x138c, 0x1399, 0x1399, - 0x1399, 0x1399, 0x13a4, 0x13a4, 0x138c, 0x138c, 0x1399, 0x1399, - 0x1399, 0x1399, 0x13a5, 0x13a5, 0x13a5, 0x13a5, 0x13a5, 0x13a5, - 0x13a5, 0x13a5, 0x13a5, 0x13a5, 0x13a5, 0x13a5, 0x13a5, 0x13a5, - 0x13a5, 0x13a5, 0x0078, 0x138a, 0x007e, 0x107e, 0x127e, 0x2091, - 0x2300, 0x1078, 0x290b, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, - 0x007c, 0x007e, 0x107e, 0x127e, 0x1078, 0x13c7, 0x127f, 0x107f, - 0x007f, 0x2091, 0x8001, 0x007c, 0x007c, 0x107e, 0x127e, 0x0d7e, - 0x0e7e, 0x0f7e, 0x007e, 0x2071, 0x0100, 0x2069, 0x4a40, 0x2079, - 0x4a00, 0x1078, 0x49ae, 0x007f, 0x0f7f, 0x0e7f, 0x0d7f, 0x127f, - 0x107f, 0x007c, 0x3c00, 0xa084, 0x0007, 0x0079, 0x13bf, 0x13d0, - 0x13d0, 0x13d2, 0x13d2, 0x13d7, 0x13d7, 0x13dc, 0x13dc, 0x3c00, - 0xa084, 0x0003, 0x0079, 0x13cc, 0x13d0, 0x13d0, 0x13e5, 0x13e5, - 0x1078, 0x28ec, 0x2091, 0x2200, 0x1078, 0x44b7, 0x007c, 0x2091, - 0x2100, 0x1078, 0x44b7, 0x007c, 0x2091, 0x2100, 0x1078, 0x44b7, - 0x2091, 0x2200, 0x1078, 0x44b7, 0x007c, 0x2091, 0x2100, 0x1078, - 0x44b7, 0x007c, 0x140a, 0x140a, 0x140c, 0x140c, 0x1419, 0x1419, - 0x1419, 0x1419, 0x1424, 0x1424, 0x1431, 0x1431, 0x1419, 0x1419, - 0x1419, 0x1419, 0x1442, 0x1442, 0x1442, 0x1442, 0x1442, 0x1442, - 0x1442, 0x1442, 0x1442, 0x1442, 0x1442, 0x1442, 0x1442, 0x1442, - 0x1442, 0x1442, 0x0078, 0x140a, 0x007e, 0x107e, 0x127e, 0x2091, - 0x2400, 0x1078, 0x290b, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, - 0x007c, 0x007e, 0x107e, 0x127e, 0x1078, 0x13ba, 0x127f, 0x107f, - 0x007f, 0x2091, 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x2091, - 0x2300, 0x1078, 0x290b, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, - 0x007c, 0x007e, 0x107e, 0x127e, 0x2091, 0x2300, 0x1078, 0x290b, - 0x2091, 0x2400, 0x1078, 0x290b, 0x127f, 0x107f, 0x007f, 0x2091, - 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x0d7e, 0x0e7e, 0x0f7e, - 0x2079, 0x4a00, 0x2071, 0x0200, 0x2069, 0x4a40, 0x3d00, 0xd08c, - 0x00c0, 0x1456, 0x2069, 0x4a80, 0x2071, 0x0100, 0x1078, 0x49ae, - 0x0f7f, 0x0e7f, 0x0d7f, 0x127f, 0x107f, 0x007f, 0x007c, 0x7008, - 0x800b, 0x00c8, 0x146d, 0x7007, 0x0002, 0xa08c, 0x01e0, 0x00c0, - 0x146e, 0xd09c, 0x0040, 0x146d, 0x087a, 0x097a, 0x70c3, 0x4002, - 0x0078, 0x15a0, 0x0068, 0x14f7, 0x2061, 0x0000, 0x6018, 0xd084, - 0x00c0, 0x14f7, 0x7828, 0xa005, 0x00c0, 0x1482, 0x0010, 0x14f8, - 0x0078, 0x14f7, 0x7910, 0xd1f4, 0x0040, 0x148a, 0x2001, 0x4007, - 0x0078, 0x159f, 0x7914, 0xd1ec, 0x0040, 0x14a5, 0xd0fc, 0x0040, - 0x149b, 0x007e, 0x1078, 0x1d82, 0x007f, 0x0040, 0x14a5, 0x2001, - 0x4007, 0x0078, 0x159f, 0x007e, 0x1078, 0x1d72, 0x007f, 0x0040, - 0x14a5, 0x2001, 0x4007, 0x0078, 0x159f, 0x7910, 0xd0fc, 0x00c0, - 0x14af, 0x2061, 0x4a40, 0xc19c, 0xc7fc, 0x0078, 0x14b3, 0x2061, - 0x4a80, 0xc19d, 0xc7fd, 0x6064, 0xa005, 0x00c0, 0x14f7, 0x7912, - 0x6083, 0x0000, 0x7828, 0xc0fc, 0xa086, 0x0018, 0x00c0, 0x14c4, - 0x0c7e, 0x1078, 0x1b13, 0x0c7f, 0x782b, 0x0000, 0x607c, 0xa065, - 0x0040, 0x14dd, 0x0c7e, 0x609c, 0x1078, 0x1e5d, 0x0c7f, 0x609f, - 0x0000, 0x1078, 0x1c3f, 0x2009, 0x0018, 0x6087, 0x0103, 0x1078, - 0x1d92, 0x00c0, 0x14f1, 0x1078, 0x1de4, 0x7810, 0xd09c, 0x00c0, - 0x14e5, 0x2061, 0x4a40, 0x0078, 0x14e9, 0x2061, 0x4a80, 0xc09c, - 0x7812, 0x607f, 0x0000, 0x60d4, 0xd0dc, 0x0040, 0x14f5, 0xc0dc, - 0x60d6, 0x2001, 0x4005, 0x0078, 0x159f, 0x0078, 0x159d, 0x007c, - 0x7810, 0xd0f4, 0x0040, 0x1500, 0x2001, 0x4007, 0x0078, 0x159f, - 0xa006, 0x70c2, 0x70c6, 0x70ca, 0x70ce, 0x70da, 0x70c0, 0xa08a, - 0x0040, 0x00c8, 0x150d, 0x0079, 0x1514, 0x2100, 0xa08a, 0x0040, - 0x00c8, 0x15ab, 0x0079, 0x1554, 0x159d, 0x15f3, 0x15bc, 0x162b, - 0x1663, 0x1663, 0x15b3, 0x1c57, 0x166e, 0x15ab, 0x15c0, 0x15c2, - 0x15c4, 0x15c6, 0x1c5c, 0x15ab, 0x167c, 0x16d4, 0x1b35, 0x1c51, - 0x15c8, 0x19a7, 0x19e9, 0x1a1f, 0x1a6b, 0x1962, 0x196f, 0x1983, - 0x1996, 0x17a4, 0x1cdc, 0x1706, 0x1713, 0x171f, 0x172b, 0x1741, - 0x174d, 0x1750, 0x175c, 0x1768, 0x1770, 0x178c, 0x1798, 0x15ab, - 0x15ab, 0x15ab, 0x15ab, 0x17b1, 0x17c3, 0x17df, 0x1815, 0x183d, - 0x184d, 0x1850, 0x1881, 0x18b2, 0x18c4, 0x1931, 0x1941, 0x1d32, - 0x15ab, 0x15ab, 0x15ab, 0x1951, 0x15ab, 0x15ab, 0x15ab, 0x15ab, - 0x15ab, 0x1c81, 0x1c87, 0x15ab, 0x15ab, 0x15ab, 0x1c8b, 0x1cd8, - 0x15ab, 0x15ab, 0x1ce8, 0x1cf7, 0x15ed, 0x165d, 0x1676, 0x16ce, - 0x1b2f, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x1d39, 0x1c73, 0x1c7d, - 0x15ab, 0x15ab, 0x1d02, 0x1d1b, 0x15ab, 0x15ab, 0x15ab, 0x15ab, - 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, - 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, - 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, - 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x72ca, 0x71c6, 0x2001, 0x4006, - 0x0078, 0x159f, 0x73ce, 0x72ca, 0x71c6, 0x2001, 0x4000, 0x70c2, - 0x0068, 0x15a0, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x5000, - 0x2091, 0x4080, 0x007c, 0x70c3, 0x4001, 0x0078, 0x15a0, 0x70c3, - 0x4006, 0x0078, 0x15a0, 0x2099, 0x0041, 0x20a1, 0x0041, 0x20a9, - 0x0005, 0x53a3, 0x0078, 0x159d, 0x70c4, 0x70c3, 0x0004, 0x007a, - 0x0078, 0x159d, 0x0078, 0x159d, 0x0078, 0x159d, 0x0078, 0x159d, - 0x2091, 0x8000, 0x70c3, 0x0004, 0x70c7, 0x4953, 0x70cb, 0x5020, - 0x70cf, 0x2020, 0x70d3, 0x0008, 0x2001, 0x0009, 0x70d6, 0x2079, - 0x0000, 0x781b, 0x0001, 0x2031, 0x0030, 0x2059, 0x1000, 0x2029, - 0x041a, 0x2051, 0x0445, 0x2061, 0x0447, 0x20c1, 0x0020, 0x2091, - 0x5000, 0x2091, 0x4080, 0x0078, 0x0418, 0x75d8, 0x74dc, 0x75da, - 0x74de, 0x0078, 0x15f6, 0x2029, 0x0000, 0x2520, 0x71d0, 0x72c8, - 0x73cc, 0x70c4, 0x20a0, 0x2099, 0x0030, 0x7003, 0x0001, 0x7007, - 0x0006, 0x731a, 0x721e, 0x7422, 0x7526, 0x2021, 0x0040, 0x81ff, - 0x0040, 0x159d, 0xa182, 0x0040, 0x00c8, 0x1610, 0x2120, 0xa006, - 0x2008, 0x8403, 0x7012, 0x7007, 0x0004, 0x7007, 0x0001, 0x7008, - 0xd0fc, 0x0040, 0x1617, 0x7007, 0x0002, 0xa084, 0x01e0, 0x0040, - 0x1625, 0x70c3, 0x4002, 0x0078, 0x15a0, 0x24a8, 0x53a5, 0x0078, - 0x1607, 0x0078, 0x159d, 0x2029, 0x0000, 0x2520, 0x71d0, 0x72c8, - 0x73cc, 0x70c4, 0x2098, 0x20a1, 0x0030, 0x7003, 0x0000, 0x7007, - 0x0006, 0x731a, 0x721e, 0x7422, 0x7526, 0x2021, 0x0040, 0x7007, - 0x0006, 0x81ff, 0x0040, 0x159d, 0xa182, 0x0040, 0x00c8, 0x164a, - 0x2120, 0xa006, 0x2008, 0x8403, 0x7012, 0x24a8, 0x53a6, 0x7007, - 0x0001, 0x7008, 0xd0fc, 0x0040, 0x1651, 0xa084, 0x01e0, 0x0040, - 0x163f, 0x70c3, 0x4002, 0x0078, 0x15a0, 0x75d8, 0x74dc, 0x75da, - 0x74de, 0x0078, 0x162e, 0x71c4, 0x70c8, 0x2114, 0xa79e, 0x0004, - 0x00c0, 0x166b, 0x200a, 0x72ca, 0x0078, 0x159c, 0x70c7, 0x0008, - 0x70cb, 0x0009, 0x70cf, 0x0000, 0x0078, 0x159d, 0x75d8, 0x76dc, - 0x75da, 0x76de, 0x0078, 0x167f, 0x2029, 0x0000, 0x2530, 0x70c4, - 0x72c8, 0x73cc, 0x74d0, 0x70c6, 0x72ca, 0x73ce, 0x74d2, 0xa005, - 0x0040, 0x16c9, 0x8001, 0x7872, 0xa084, 0xfc00, 0x0040, 0x1697, - 0x78ac, 0xc085, 0x78ae, 0x2001, 0x4005, 0x0078, 0x159f, 0x7b7e, - 0x7a7a, 0x7e86, 0x7d82, 0x7c76, 0xa48c, 0xff00, 0x0040, 0x16af, - 0x8407, 0x8004, 0x8004, 0x810c, 0x810c, 0x810f, 0xa118, 0xa291, - 0x0000, 0xa6b1, 0x0000, 0xa581, 0x0000, 0x0078, 0x16b9, 0x8407, - 0x8004, 0x8004, 0xa318, 0xa291, 0x0000, 0xa6b1, 0x0000, 0xa581, - 0x0000, 0x731a, 0x721e, 0x7622, 0x7026, 0xa605, 0x0040, 0x16c3, - 0x7a10, 0xc2c5, 0x7a12, 0x78ac, 0xa084, 0xfffc, 0x78ae, 0x0078, - 0x16cc, 0x78ac, 0xc085, 0x78ae, 0x0078, 0x159d, 0x75d8, 0x76dc, - 0x75da, 0x76de, 0x0078, 0x16d7, 0x2029, 0x0000, 0x2530, 0x70c4, - 0x72c8, 0x73cc, 0x74d4, 0x70c6, 0x72ca, 0x73ce, 0x74d6, 0xa005, - 0x0040, 0x1701, 0x8001, 0x7892, 0xa084, 0xfc00, 0x0040, 0x16ef, - 0x78ac, 0xc0c5, 0x78ae, 0x2001, 0x4005, 0x0078, 0x159f, 0x7a9a, - 0x7b9e, 0x7da2, 0x7ea6, 0x2600, 0xa505, 0x0040, 0x16fa, 0x7a10, - 0xc2c5, 0x7a12, 0x7c96, 0x78ac, 0xa084, 0xfcff, 0x78ae, 0x0078, - 0x1704, 0x78ac, 0xc0c5, 0x78ae, 0x0078, 0x159d, 0x2009, 0x0000, - 0x786c, 0xa065, 0x0040, 0x1710, 0x8108, 0x6000, 0x0078, 0x1709, - 0x7ac4, 0x0078, 0x159b, 0x2009, 0x4a48, 0x210c, 0x7810, 0xd0ec, - 0x00c0, 0x159c, 0x2011, 0x4a88, 0x2214, 0x0078, 0x159b, 0x2009, - 0x4a49, 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x159c, 0x2011, 0x4a89, - 0x2214, 0x0078, 0x159b, 0x2061, 0x4a40, 0x6128, 0x622c, 0x8214, - 0x8214, 0x8214, 0x7810, 0xd0ec, 0x00c0, 0x173f, 0x2061, 0x4a80, - 0x6328, 0x73da, 0x632c, 0x831c, 0x831c, 0x831c, 0x73de, 0x0078, - 0x159b, 0x2009, 0x4a4c, 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x159c, - 0x2011, 0x4a8c, 0x2214, 0x0078, 0x159b, 0x7918, 0x0078, 0x159c, - 0x2009, 0x4a4d, 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x159c, 0x2011, - 0x4a8d, 0x2214, 0x0078, 0x159b, 0x2009, 0x4a4e, 0x210c, 0x7810, - 0xd0ec, 0x00c0, 0x159c, 0x2011, 0x4a8e, 0x2214, 0x0078, 0x159b, - 0x7920, 0x7810, 0xd0ec, 0x00c0, 0x159c, 0x7a24, 0x0078, 0x159b, - 0x71c4, 0xd1fc, 0x00c0, 0x1778, 0x2011, 0x4ec0, 0x0078, 0x177a, - 0x2011, 0x4f40, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, - 0xa268, 0x6a00, 0x6804, 0xd09c, 0x0040, 0x1789, 0x6b08, 0x0078, - 0x178a, 0x6b0c, 0x0078, 0x159a, 0x77c4, 0x1078, 0x1e02, 0x2091, - 0x8000, 0x6b1c, 0x6a14, 0x2091, 0x8001, 0x2708, 0x0078, 0x159a, - 0x2061, 0x4a40, 0x6118, 0x7810, 0xd0ec, 0x00c0, 0x159c, 0x2061, - 0x4a80, 0x6218, 0x0078, 0x159b, 0x77c4, 0x1078, 0x1e02, 0x2091, - 0x8000, 0x6908, 0x6a18, 0x6b10, 0x77da, 0x2091, 0x8001, 0x0078, - 0x159a, 0x71c4, 0x2110, 0xa294, 0x000f, 0xa282, 0x0010, 0x00c8, - 0x1595, 0x1078, 0x2729, 0xa384, 0x4000, 0x0040, 0x17c1, 0xa295, - 0x0020, 0x0078, 0x159a, 0x71c4, 0x2100, 0xc0bc, 0xa082, 0x0010, - 0x00c8, 0x1595, 0xd1bc, 0x00c0, 0x17d2, 0x2011, 0x4a48, 0x2204, - 0x0078, 0x17d6, 0x2011, 0x4a88, 0x2204, 0xc0bd, 0x007e, 0x2100, - 0xc0bc, 0x2012, 0x1078, 0x2686, 0x017f, 0x0078, 0x159c, 0x71c4, - 0x2021, 0x4a49, 0x2404, 0x70c6, 0x2019, 0x0000, 0x0078, 0x17ee, - 0x71c8, 0x2021, 0x4a89, 0x2404, 0x70ca, 0xc3fd, 0x2011, 0x180d, - 0x20a9, 0x0008, 0x2204, 0xa106, 0x0040, 0x17fd, 0x8210, 0x00f0, - 0x17f2, 0x71c4, 0x72c8, 0x0078, 0x1594, 0xa292, 0x180d, 0x027e, - 0x2122, 0x017f, 0x1078, 0x26a7, 0x7810, 0xd0ec, 0x00c0, 0x180b, - 0xd3fc, 0x0040, 0x17e8, 0x0078, 0x159d, 0x03e8, 0x00fa, 0x01f4, - 0x02ee, 0x0064, 0x0019, 0x0032, 0x004b, 0x2061, 0x4a40, 0x6128, - 0x622c, 0x8214, 0x8214, 0x8214, 0x70c4, 0x602a, 0x70c8, 0x8003, - 0x8003, 0x8003, 0x602e, 0x7810, 0xd0ec, 0x00c0, 0x183b, 0x027e, - 0x017e, 0x2061, 0x4a80, 0x6128, 0x622c, 0x8214, 0x8214, 0x8214, - 0x70d8, 0x602a, 0x70dc, 0x8003, 0x8003, 0x8003, 0x602e, 0x71da, - 0x72de, 0x017f, 0x027f, 0x0078, 0x159b, 0x2061, 0x4a40, 0x6130, - 0x70c4, 0x6032, 0x7810, 0xd0ec, 0x00c0, 0x159c, 0x2061, 0x4a80, - 0x6230, 0x70c8, 0x6032, 0x0078, 0x159b, 0x7918, 0x0078, 0x159c, - 0x71c4, 0xa184, 0xffcf, 0x0040, 0x185c, 0x7810, 0xd0ec, 0x00c0, - 0x1595, 0x72c8, 0x0078, 0x1594, 0x2011, 0x4a4d, 0x2204, 0x2112, - 0x007e, 0x2019, 0x0000, 0x1078, 0x270e, 0x7810, 0xd0ec, 0x0040, - 0x186c, 0x017f, 0x0078, 0x159c, 0x71c8, 0xa184, 0xffcf, 0x0040, - 0x1875, 0x2110, 0x71c4, 0x0078, 0x1594, 0x2011, 0x4a8d, 0x2204, - 0x2112, 0x007e, 0xc3fd, 0x1078, 0x270e, 0x027f, 0x017f, 0x0078, - 0x159b, 0x71c4, 0xa182, 0x0010, 0x0048, 0x188d, 0x7810, 0xd0ec, - 0x00c0, 0x1595, 0x72c8, 0x0078, 0x1594, 0x2011, 0x4a4e, 0x2204, - 0x007e, 0x2112, 0x2019, 0x0000, 0x1078, 0x26ec, 0x7810, 0xd0ec, - 0x0040, 0x189d, 0x017f, 0x0078, 0x159c, 0x71c8, 0xa182, 0x0010, - 0x0048, 0x18a6, 0x2110, 0x71c4, 0x0078, 0x1594, 0x2011, 0x4a8e, - 0x2204, 0x007e, 0x2112, 0xc3fd, 0x1078, 0x26ec, 0x027f, 0x017f, - 0x0078, 0x159b, 0x71c4, 0x72c8, 0xa184, 0xfffd, 0x00c0, 0x1594, - 0xa284, 0xfffd, 0x00c0, 0x1594, 0x2100, 0x7920, 0x7822, 0x2200, - 0x7a24, 0x7826, 0x0078, 0x159b, 0x71c4, 0xd1fc, 0x00c0, 0x18cc, - 0x2011, 0x4ec0, 0x0078, 0x18ce, 0x2011, 0x4f40, 0x8107, 0xa084, - 0x000f, 0x8003, 0x8003, 0x8003, 0xa268, 0x2019, 0x0000, 0x72c8, - 0xa284, 0x0080, 0x0040, 0x18e2, 0x6c14, 0x84ff, 0x00c0, 0x18e2, - 0x6817, 0x0040, 0xa284, 0x0040, 0x0040, 0x18ec, 0x6c10, 0x84ff, - 0x00c0, 0x18ec, 0x6813, 0x0001, 0x6800, 0x007e, 0xa226, 0x0040, - 0x1909, 0x6a02, 0xd4ec, 0x0040, 0x18f6, 0xc3a5, 0xd4e4, 0x0040, - 0x18fa, 0xc39d, 0xd4f4, 0x0040, 0x1909, 0x810f, 0xd2f4, 0x0040, - 0x1905, 0x1078, 0x276b, 0x0078, 0x1909, 0x1078, 0x2749, 0x0078, - 0x1909, 0x72cc, 0x6808, 0xa206, 0x0040, 0x1929, 0xa2a4, 0x00ff, - 0x7814, 0xd0e4, 0x00c0, 0x191c, 0xa482, 0x0028, 0x0048, 0x1926, - 0x0040, 0x1926, 0x0078, 0x1920, 0xa482, 0x0043, 0x0048, 0x1926, - 0x71c4, 0x71c6, 0x027f, 0x72ca, 0x0078, 0x1596, 0x6a0a, 0xa39d, - 0x000a, 0x6804, 0xa305, 0x6806, 0x027f, 0x6b0c, 0x71c4, 0x0078, - 0x159a, 0x77c4, 0x1078, 0x1e02, 0x2091, 0x8000, 0x6a14, 0x6b1c, - 0x2091, 0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e, 0x2708, 0x0078, - 0x159a, 0x70c4, 0x2061, 0x4a40, 0x6118, 0x601a, 0x7810, 0xd0ec, - 0x00c0, 0x159c, 0x70c8, 0x2061, 0x4a80, 0x6218, 0x601a, 0x0078, - 0x159b, 0x71c4, 0x72c8, 0x73cc, 0xa182, 0x0010, 0x00c8, 0x1595, - 0x1078, 0x278d, 0xa384, 0x4000, 0x0040, 0x1960, 0xa295, 0x0020, - 0x0078, 0x159a, 0x77c4, 0x1078, 0x1e02, 0x2091, 0x8000, 0x6a08, - 0xc28d, 0x6a0a, 0x2091, 0x8001, 0x2708, 0x0078, 0x159b, 0x77c4, - 0x1078, 0x1e02, 0x2091, 0x8000, 0x6a08, 0xa294, 0xfff9, 0x6a0a, - 0x6804, 0xa005, 0x0040, 0x197e, 0x1078, 0x25de, 0x2091, 0x8001, - 0x2708, 0x0078, 0x159b, 0x77c4, 0x1078, 0x1e02, 0x2091, 0x8000, - 0x6a08, 0xc295, 0x6a0a, 0x6804, 0xa005, 0x0040, 0x1991, 0x1078, - 0x25de, 0x2091, 0x8001, 0x2708, 0x0078, 0x159b, 0x77c4, 0x2041, - 0x0001, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078, - 0x1e1d, 0x2091, 0x8001, 0x2708, 0x6a08, 0x0078, 0x159b, 0x77c4, - 0x7814, 0xd0e4, 0x00c0, 0x19bb, 0xd7fc, 0x0040, 0x19b5, 0x1078, - 0x1d82, 0x0040, 0x19bb, 0x0078, 0x159f, 0x1078, 0x1d72, 0x0040, - 0x19bb, 0x0078, 0x159f, 0x73c8, 0x72cc, 0x77c6, 0x73ca, 0x72ce, - 0x1078, 0x1e9a, 0x00c0, 0x19e5, 0x6818, 0xa005, 0x0040, 0x19df, - 0x2708, 0x077e, 0x1078, 0x27bd, 0x077f, 0x00c0, 0x19df, 0x2001, - 0x0015, 0xd7fc, 0x00c0, 0x19d8, 0x2061, 0x4a40, 0x0078, 0x19db, - 0xc0fd, 0x2061, 0x4a80, 0x782a, 0x2091, 0x8001, 0x007c, 0x2091, - 0x8001, 0x2001, 0x4005, 0x0078, 0x159f, 0x2091, 0x8001, 0x0078, - 0x159d, 0x77c4, 0x7814, 0xd0e4, 0x00c0, 0x19fd, 0xd7fc, 0x0040, - 0x19f7, 0x1078, 0x1d82, 0x0040, 0x19fd, 0x0078, 0x159f, 0x1078, - 0x1d72, 0x0040, 0x19fd, 0x0078, 0x159f, 0x77c6, 0x2041, 0x0021, - 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078, 0x1e1d, - 0x2009, 0x0016, 0xd7fc, 0x00c0, 0x1a11, 0x2061, 0x4a40, 0x0078, - 0x1a14, 0x2061, 0x4a80, 0xc1fd, 0x6067, 0x0003, 0x6776, 0x6083, - 0x000f, 0x792a, 0x1078, 0x25de, 0x2091, 0x8001, 0x007c, 0x77c8, - 0x77ca, 0x77c4, 0x77c6, 0x7814, 0xd0e4, 0x00c0, 0x1a36, 0xd7fc, - 0x0040, 0x1a30, 0x1078, 0x1d82, 0x0040, 0x1a36, 0x0078, 0x159f, - 0x1078, 0x1d72, 0x0040, 0x1a36, 0x0078, 0x159f, 0xa7bc, 0xff00, - 0x2091, 0x8000, 0x2009, 0x0017, 0xd7fc, 0x00c0, 0x1a43, 0x2061, - 0x4a40, 0x0078, 0x1a46, 0x2061, 0x4a80, 0xc1fd, 0x6067, 0x0002, - 0x6776, 0x6083, 0x000f, 0x792a, 0x1078, 0x25de, 0x2091, 0x8001, - 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0010, 0x2091, 0x8000, - 0x70c8, 0xa005, 0x0040, 0x1a5f, 0x60d4, 0xc0fd, 0x60d6, 0x1078, - 0x1e1d, 0x70c8, 0x683e, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1a5f, - 0x2091, 0x8001, 0x007c, 0x7814, 0xd0e4, 0x00c0, 0x1a7f, 0x72c8, - 0xd284, 0x0040, 0x1a79, 0x1078, 0x1d82, 0x0040, 0x1a7f, 0x0078, - 0x159f, 0x1078, 0x1d72, 0x0040, 0x1a7f, 0x0078, 0x159f, 0x72c8, - 0x72ca, 0x78ac, 0xa084, 0x0003, 0x00c0, 0x1aaa, 0x2039, 0x0000, - 0xd284, 0x0040, 0x1a8c, 0xc7fd, 0x2041, 0x0021, 0x2049, 0x0004, - 0x2051, 0x0008, 0x1078, 0x1e02, 0x2091, 0x8000, 0x6808, 0xc0d4, - 0xa80d, 0x690a, 0x2091, 0x8001, 0x8738, 0xa784, 0x001f, 0x00c0, - 0x1a92, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, - 0x00c0, 0x1a92, 0x2091, 0x8000, 0x72c8, 0xd284, 0x00c0, 0x1abc, - 0x7810, 0xd0ec, 0x0040, 0x1ab8, 0x2069, 0x0100, 0x0078, 0x1abe, - 0x2069, 0x0200, 0x0078, 0x1abe, 0x2069, 0x0100, 0x6830, 0xd0b4, - 0x0040, 0x1ada, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, 0xd094, - 0x0040, 0x1acc, 0x00f0, 0x1ac6, 0x684b, 0x0009, 0x20a9, 0x0014, - 0x6848, 0xd084, 0x0040, 0x1ad6, 0x00f0, 0x1ad0, 0x20a9, 0x00fa, - 0x00f0, 0x1ad8, 0x2079, 0x4a00, 0x2009, 0x0018, 0x72c8, 0xd284, - 0x00c0, 0x1ae6, 0x2061, 0x4a40, 0x0078, 0x1ae9, 0x2061, 0x4a80, - 0xc1fd, 0x792a, 0x6067, 0x0001, 0x6083, 0x000f, 0x60a7, 0x0000, - 0x60a8, 0x60b2, 0x60b6, 0x60d4, 0xd0b4, 0x0040, 0x1b03, 0xc0b4, - 0x60d6, 0x0c7e, 0x60b8, 0xa065, 0x6008, 0xc0d4, 0x600a, 0x6018, - 0x8001, 0x601a, 0x0c7f, 0x60d4, 0xa084, 0x77ff, 0x60d6, 0x78ac, - 0xc08d, 0x78ae, 0x6808, 0xa084, 0xfffd, 0x680a, 0x681b, 0x0047, - 0x2091, 0x8001, 0x007c, 0xd7fc, 0x00c0, 0x1b1a, 0x2069, 0x4a40, - 0x0078, 0x1b1c, 0x2069, 0x4a80, 0x78ac, 0xc08c, 0x78ae, 0xd084, - 0x00c0, 0x1b26, 0x0d7e, 0x1078, 0x1efa, 0x0d7f, 0x71c4, 0x71c6, - 0x6916, 0x81ff, 0x00c0, 0x1b2e, 0x68a7, 0x0001, 0x007c, 0x75d8, - 0x74dc, 0x75da, 0x74de, 0x0078, 0x1b38, 0x2029, 0x0000, 0x2520, - 0x71c4, 0x73c8, 0x72cc, 0x71c6, 0x73ca, 0x72ce, 0x2079, 0x4a00, - 0x7dde, 0x7cda, 0x7bd6, 0x7ad2, 0x1078, 0x1ddb, 0x0040, 0x1c3b, - 0x20a9, 0x0005, 0x20a1, 0x4a14, 0x2091, 0x8000, 0x41a1, 0x2091, - 0x8001, 0x2009, 0x0040, 0x1078, 0x1fcf, 0x0040, 0x1b5b, 0x1078, - 0x1de4, 0x0078, 0x1c3b, 0x6004, 0xa08c, 0x00ff, 0xa18e, 0x0009, - 0x00c0, 0x1b66, 0x007e, 0x1078, 0x234b, 0x007f, 0xa084, 0xff00, - 0x8007, 0x8009, 0x0040, 0x1bda, 0x0c7e, 0x2c68, 0x1078, 0x1ddb, - 0x0040, 0x1bac, 0x2c00, 0x689e, 0x8109, 0x00c0, 0x1b6d, 0x609f, - 0x0000, 0x0c7f, 0x0c7e, 0x7ddc, 0x7cd8, 0x7bd4, 0x7ad0, 0xa290, - 0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x7dde, - 0x7cda, 0x7bd6, 0x7ad2, 0x2c68, 0x689c, 0xa065, 0x0040, 0x1bd9, - 0x2009, 0x0040, 0x1078, 0x1fcf, 0x00c0, 0x1bc3, 0x6004, 0xa084, - 0x00ff, 0xa086, 0x0002, 0x00c0, 0x1bac, 0x6004, 0xa084, 0x00ff, - 0xa086, 0x000a, 0x00c0, 0x1ba8, 0x017e, 0x1078, 0x2347, 0x017f, - 0x2d00, 0x6002, 0x0078, 0x1b7b, 0x0c7f, 0x0c7e, 0x609c, 0x1078, - 0x1e5d, 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1c3f, 0x2009, 0x0018, - 0x6008, 0xc0cd, 0x600a, 0x6004, 0x6086, 0x1078, 0x1d92, 0x1078, - 0x1de4, 0x0078, 0x1c3b, 0x0c7f, 0x0c7e, 0x609c, 0x1078, 0x1e5d, - 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1c3f, 0x2009, 0x0018, 0x6087, - 0x0103, 0x601b, 0x0003, 0x1078, 0x1d92, 0x1078, 0x1de4, 0x0078, - 0x1c3b, 0x0c7f, 0x7814, 0xd0e4, 0x00c0, 0x1bff, 0x6114, 0xd1fc, - 0x0040, 0x1be8, 0x1078, 0x1d82, 0x0040, 0x1bff, 0x0078, 0x1bec, - 0x1078, 0x1d72, 0x0040, 0x1bff, 0x2029, 0x0000, 0x2520, 0x2009, - 0x0018, 0x73c8, 0x72cc, 0x6087, 0x0103, 0x601b, 0x0021, 0x1078, - 0x1d92, 0x1078, 0x1de4, 0x2001, 0x4007, 0x0078, 0x159f, 0x74c4, - 0x73c8, 0x72cc, 0x6014, 0x2091, 0x8000, 0x0e7e, 0x2009, 0x0012, - 0xd0fc, 0x00c0, 0x1c0f, 0x2071, 0x4a40, 0x0078, 0x1c12, 0x2071, - 0x4a80, 0xc1fd, 0x792a, 0x7067, 0x0005, 0x71d4, 0xa18c, 0xf77f, - 0x71d6, 0x736a, 0x726e, 0x7472, 0x7076, 0x707b, 0x0000, 0x2c00, - 0x707e, 0xa02e, 0x2530, 0x611c, 0xa184, 0x0060, 0x0040, 0x1c2a, - 0x1078, 0x43c1, 0x0e7f, 0x6596, 0x65a6, 0x669a, 0x66aa, 0x60af, - 0x0000, 0x60b3, 0x0000, 0x6714, 0x6023, 0x0000, 0x1078, 0x25de, - 0x2091, 0x8001, 0x007c, 0x70c3, 0x4005, 0x0078, 0x15a0, 0x20a9, - 0x0005, 0x2099, 0x4a14, 0x2091, 0x8000, 0x530a, 0x2091, 0x8001, - 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, - 0x007c, 0x71c4, 0x70c7, 0x0000, 0x791e, 0x0078, 0x159d, 0x71c4, - 0x71c6, 0x2168, 0x0078, 0x1c5e, 0x2069, 0x1000, 0x690c, 0xa016, - 0x2d04, 0xa210, 0x8d68, 0x8109, 0x00c0, 0x1c60, 0xa285, 0x0000, - 0x00c0, 0x1c6e, 0x70c3, 0x4000, 0x0078, 0x1c70, 0x70c3, 0x4003, - 0x70ca, 0x0078, 0x15a0, 0x7964, 0x71c6, 0x71c4, 0xa182, 0x0003, - 0x00c8, 0x1595, 0x7966, 0x0078, 0x159d, 0x7964, 0x71c6, 0x0078, - 0x159d, 0x7900, 0x71c6, 0x71c4, 0x7902, 0x0078, 0x159d, 0x7900, - 0x71c6, 0x0078, 0x159d, 0x70c4, 0xd08c, 0x0040, 0x1c94, 0x7a10, - 0xd2ec, 0x00c0, 0x1c94, 0xc08c, 0x2011, 0x0000, 0xa08c, 0x000d, - 0x0040, 0x1ca8, 0x810c, 0x0048, 0x1ca4, 0x8210, 0x810c, 0x810c, - 0x0048, 0x1ca4, 0x8210, 0x810c, 0x81ff, 0x00c0, 0x1596, 0x8210, - 0x7a0e, 0xd28c, 0x0040, 0x1cd4, 0x7910, 0xc1cd, 0x7912, 0x2009, - 0x0021, 0x2019, 0x0003, 0xd284, 0x0040, 0x1cce, 0x8108, 0x2019, - 0x0041, 0x2011, 0x924e, 0x2312, 0x2019, 0x0042, 0x8210, 0x2312, - 0x2019, 0x0043, 0x8210, 0x2312, 0x2019, 0x0046, 0x8210, 0x2312, - 0x2019, 0x0047, 0x8210, 0x2312, 0x2019, 0x0006, 0x2011, 0x9253, - 0x2112, 0x2011, 0x9273, 0x2312, 0x7904, 0x7806, 0x0078, 0x159c, - 0x7804, 0x70c6, 0x0078, 0x159d, 0x2091, 0x8000, 0x2019, 0x0000, - 0x2011, 0x0000, 0x2009, 0x0000, 0x2091, 0x8001, 0x0078, 0x159a, - 0x77c4, 0x1078, 0x1e02, 0x2091, 0x8000, 0x6830, 0xa084, 0xff00, - 0x8007, 0x2010, 0x2091, 0x8001, 0x2708, 0x0078, 0x159b, 0x77c4, - 0x1078, 0x1e02, 0x2091, 0x8000, 0x6a34, 0x2091, 0x8001, 0x2708, - 0x0078, 0x159b, 0x77c4, 0x077e, 0xa7bc, 0xff00, 0x20a9, 0x0008, - 0x72c8, 0x8217, 0x1078, 0x1e02, 0x2091, 0x8000, 0x6c30, 0x6a32, - 0x2091, 0x8001, 0x8738, 0x00f0, 0x1d0a, 0x077f, 0x2708, 0x8427, - 0x2410, 0x0078, 0x159b, 0x77c4, 0x077e, 0xa7bc, 0xff00, 0x20a9, - 0x0008, 0x72c8, 0x1078, 0x1e02, 0x2091, 0x8000, 0x6c34, 0x6a36, - 0x2091, 0x8001, 0x8738, 0x00f0, 0x1d22, 0x077f, 0x2708, 0x2410, - 0x0078, 0x159b, 0x2011, 0x4a3c, 0x220c, 0x70c4, 0x2012, 0x0078, - 0x159c, 0x71c4, 0xd1fc, 0x00c0, 0x1d41, 0x2011, 0x4ec0, 0x0078, - 0x1d43, 0x2011, 0x4f40, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, - 0x8003, 0xa268, 0x6a14, 0xd2b4, 0x0040, 0x1d52, 0x2011, 0x0001, - 0x0078, 0x1d54, 0x2011, 0x0000, 0x6b0c, 0x0078, 0x159a, 0x017e, - 0x7814, 0xd0f4, 0x0040, 0x1d64, 0x2001, 0x4007, 0x70db, 0x0000, - 0xa18d, 0x0001, 0x0078, 0x1d70, 0xd0fc, 0x0040, 0x1d6f, 0x2001, - 0x4007, 0x70db, 0x0001, 0xa18d, 0x0001, 0x0078, 0x1d70, 0xa006, - 0x017f, 0x007c, 0x017e, 0x7814, 0xd0f4, 0x0040, 0x1d7f, 0x2001, - 0x4007, 0x70db, 0x0000, 0xa18d, 0x0001, 0x0078, 0x1d80, 0xa006, - 0x017f, 0x007c, 0x017e, 0x7814, 0xd0fc, 0x0040, 0x1d8f, 0x2001, - 0x4007, 0x70db, 0x0001, 0xa18d, 0x0001, 0x0078, 0x1d90, 0xa006, - 0x017f, 0x007c, 0x7112, 0x721a, 0x731e, 0x7810, 0xd0c4, 0x0040, - 0x1d9b, 0x7422, 0x7526, 0xac80, 0x0001, 0x8108, 0x810c, 0x81a9, - 0x8098, 0x20a1, 0x0030, 0x7003, 0x0000, 0x6084, 0x20a2, 0x53a6, - 0x7007, 0x0001, 0x7974, 0xa184, 0xff00, 0x0040, 0x1db8, 0x810f, - 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0078, 0x1dbb, - 0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, 0xa006, 0xa211, - 0x7d10, 0xd5c4, 0x0040, 0x1dc8, 0x7b84, 0xa319, 0x7c80, 0xa421, - 0x7008, 0xd0fc, 0x0040, 0x1dc8, 0x7003, 0x0001, 0x7007, 0x0006, - 0x711a, 0x721e, 0x7d10, 0xd5c4, 0x0040, 0x1dd8, 0x7322, 0x7426, - 0xa084, 0x01e0, 0x007c, 0x7848, 0xa065, 0x0040, 0x1de3, 0x2c04, - 0x784a, 0x2063, 0x0000, 0x007c, 0x0f7e, 0x2079, 0x4a00, 0x7848, - 0x2062, 0x2c00, 0xa005, 0x00c0, 0x1def, 0x1078, 0x28ec, 0x784a, - 0x0f7f, 0x007c, 0x2011, 0x9400, 0x7a4a, 0x7bc4, 0x8319, 0x0040, - 0x1dff, 0xa280, 0x0032, 0x2012, 0x2010, 0x0078, 0x1df6, 0x2013, - 0x0000, 0x007c, 0x017e, 0x027e, 0xd7fc, 0x00c0, 0x1e0b, 0x2011, - 0x4fc0, 0x0078, 0x1e0d, 0x2011, 0x6fc0, 0xa784, 0x0f00, 0x800b, - 0xa784, 0x001f, 0x0040, 0x1e18, 0x8003, 0x8003, 0x8003, 0x8003, - 0xa105, 0xa268, 0x027f, 0x017f, 0x007c, 0x1078, 0x1e02, 0x2900, - 0x682a, 0x2a00, 0x682e, 0x6808, 0xa084, 0xf9ef, 0xa80d, 0x690a, - 0xd7fc, 0x00c0, 0x1e2f, 0x2009, 0x4a53, 0x0078, 0x1e31, 0x2009, - 0x4a93, 0x210c, 0x6804, 0xa005, 0x0040, 0x1e41, 0xa116, 0x00c0, - 0x1e41, 0x2060, 0x6000, 0x6806, 0x017e, 0x200b, 0x0000, 0x0078, - 0x1e44, 0x2009, 0x0000, 0x017e, 0x6804, 0xa065, 0x0040, 0x1e59, - 0x6000, 0x6806, 0x1078, 0x1e6f, 0x1078, 0x201b, 0x6810, 0x7908, - 0x8109, 0x790a, 0x8001, 0x6812, 0x00c0, 0x1e44, 0x7910, 0xc1a5, - 0x7912, 0x017f, 0x6902, 0x6906, 0x007c, 0xa065, 0x0040, 0x1e6e, - 0x2008, 0x609c, 0xa005, 0x0040, 0x1e6b, 0x2062, 0x609f, 0x0000, - 0xa065, 0x0078, 0x1e61, 0x7848, 0x794a, 0x2062, 0x007c, 0x6007, - 0x0103, 0x608f, 0x0000, 0x20a9, 0x001c, 0xac80, 0x0005, 0x20a0, - 0x2001, 0x0000, 0x40a4, 0x6828, 0x601a, 0x682c, 0x6022, 0x007c, - 0x0e7e, 0xd7fc, 0x00c0, 0x1e8a, 0x2071, 0x4a40, 0x2031, 0x4ac0, - 0x0078, 0x1e8e, 0x2071, 0x4a80, 0x2031, 0x4cc0, 0x7050, 0xa08c, - 0x0200, 0x00c0, 0x1e98, 0xa608, 0x2d0a, 0x8000, 0x7052, 0xa006, - 0x0e7f, 0x007c, 0x0f7e, 0xd7fc, 0x00c0, 0x1ea2, 0x2079, 0x4a40, - 0x0078, 0x1ea4, 0x2079, 0x4a80, 0x1078, 0x1e02, 0x2091, 0x8000, - 0x6804, 0x780a, 0xa065, 0x0040, 0x1ef8, 0x0078, 0x1eb6, 0x2c00, - 0x780a, 0x2060, 0x6000, 0xa065, 0x0040, 0x1ef8, 0x6010, 0xa306, - 0x00c0, 0x1eaf, 0x600c, 0xa206, 0x00c0, 0x1eaf, 0x2c28, 0x784c, - 0xac06, 0x00c0, 0x1ec5, 0x0078, 0x1ef5, 0x6804, 0xac06, 0x00c0, - 0x1ed3, 0x6000, 0x2060, 0x6806, 0xa005, 0x00c0, 0x1ed3, 0x6803, - 0x0000, 0x0078, 0x1edd, 0x6400, 0x7808, 0x2060, 0x6402, 0xa486, - 0x0000, 0x00c0, 0x1edd, 0x2c00, 0x6802, 0x2560, 0x0f7f, 0x1078, - 0x1e6f, 0x0f7e, 0x601b, 0x0005, 0x6023, 0x0020, 0x0f7f, 0x1078, - 0x201b, 0x0f7e, 0x7908, 0x8109, 0x790a, 0x6810, 0x8001, 0x6812, - 0x00c0, 0x1ef5, 0x7810, 0xc0a5, 0x7812, 0x2001, 0xffff, 0xa005, - 0x0f7f, 0x007c, 0x077e, 0x2700, 0x2039, 0x0000, 0xd0fc, 0x0040, - 0x1f02, 0xc7fd, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, - 0x2091, 0x8000, 0x1078, 0x1e1d, 0x8738, 0xa784, 0x001f, 0x00c0, - 0x1f0a, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, - 0x00c0, 0x1f0a, 0x2091, 0x8001, 0x077f, 0x007c, 0x2061, 0x0000, - 0x6018, 0xd084, 0x00c0, 0x1f3e, 0x7810, 0xd08c, 0x0040, 0x1f2f, - 0xc08c, 0x7812, 0xc7fc, 0x2069, 0x4a40, 0x0078, 0x1f34, 0xc08d, - 0x7812, 0x2069, 0x4a80, 0xc7fd, 0x2091, 0x8000, 0x681c, 0x681f, - 0x0000, 0x2091, 0x8001, 0xa005, 0x00c0, 0x1f3f, 0x007c, 0xa08c, - 0xfff0, 0x0040, 0x1f45, 0x1078, 0x28ec, 0x0079, 0x1f47, 0x1f57, - 0x1f5a, 0x1f60, 0x1f64, 0x1f58, 0x1f68, 0x1f58, 0x1f58, 0x1f58, - 0x1f6e, 0x1f9f, 0x1fa3, 0x1fa9, 0x1f58, 0x1f58, 0x1f58, 0x007c, - 0x1078, 0x28ec, 0x1078, 0x1efa, 0x2001, 0x8001, 0x0078, 0x1fbe, - 0x2001, 0x8003, 0x0078, 0x1fbe, 0x2001, 0x8004, 0x0078, 0x1fbe, - 0x1078, 0x1efa, 0x2001, 0x8006, 0x0078, 0x1fbe, 0x2091, 0x8000, - 0x077e, 0xd7fc, 0x00c0, 0x1f7a, 0x2069, 0x4a40, 0x2039, 0x0009, - 0x0078, 0x1f7e, 0x2069, 0x4a80, 0x2039, 0x0009, 0x6800, 0xa086, - 0x0000, 0x0040, 0x1f88, 0x007f, 0x6f1e, 0x2091, 0x8001, 0x007c, - 0x6874, 0x077f, 0xa0bc, 0xff00, 0x2041, 0x0021, 0x2049, 0x0004, - 0x2051, 0x0010, 0x1078, 0x1e1d, 0x8738, 0xa784, 0x001f, 0x00c0, - 0x1f92, 0x2091, 0x8001, 0x2001, 0x800a, 0x0078, 0x1fbe, 0x2001, - 0x800c, 0x0078, 0x1fbe, 0x1078, 0x1efa, 0x2001, 0x800d, 0x0078, - 0x1fbe, 0x7814, 0xd0e4, 0x00c0, 0x1fbc, 0xd0ec, 0x0040, 0x1fb6, - 0xd7fc, 0x0040, 0x1fb6, 0x78ec, 0x0078, 0x1fb7, 0x78e4, 0x70c6, - 0x2001, 0x800e, 0x0078, 0x1fbe, 0x0078, 0x1f58, 0x70c2, 0xd7fc, - 0x00c0, 0x1fc6, 0x70db, 0x0000, 0x0078, 0x1fc8, 0x70db, 0x0001, - 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x4080, 0x007c, 0xac80, - 0x0001, 0x81ff, 0x0040, 0x1ffa, 0x2099, 0x0030, 0x20a0, 0x700c, - 0xa084, 0x03ff, 0x0040, 0x1fdc, 0x7018, 0x007e, 0x701c, 0x007e, - 0x7020, 0x007e, 0x7024, 0x007e, 0x7112, 0x81ac, 0x721a, 0x731e, - 0x7422, 0x7526, 0x7003, 0x0001, 0x7007, 0x0001, 0x7008, 0x800b, - 0x00c8, 0x1fee, 0x7007, 0x0002, 0xa08c, 0x01e0, 0x00c0, 0x1ffa, - 0x53a5, 0xa006, 0x7003, 0x0000, 0x7007, 0x0004, 0x007f, 0x7026, - 0x007f, 0x7022, 0x007f, 0x701e, 0x007f, 0x701a, 0x007c, 0x2011, - 0x0020, 0x2009, 0x0010, 0x6b0a, 0x6c0e, 0x6803, 0xfd00, 0x6807, - 0x0018, 0x6a1a, 0x2d00, 0xa0e8, 0x0008, 0xa290, 0x0004, 0x8109, - 0x00c0, 0x200b, 0x007c, 0x6004, 0x6086, 0x2c08, 0x2063, 0x0000, - 0x7868, 0xa005, 0x796a, 0x0040, 0x2028, 0x2c02, 0x0078, 0x2029, - 0x796e, 0x007c, 0x0c7e, 0x2061, 0x4a00, 0x6887, 0x0103, 0x2d08, - 0x206b, 0x0000, 0x6068, 0xa005, 0x616a, 0x0040, 0x203a, 0x2d02, - 0x0078, 0x203b, 0x616e, 0x0c7f, 0x007c, 0x2091, 0x8000, 0x2c04, - 0x786e, 0xa005, 0x00c0, 0x2045, 0x786a, 0x2091, 0x8001, 0x609c, - 0xa005, 0x0040, 0x205e, 0x0c7e, 0x2060, 0x2008, 0x609c, 0xa005, - 0x0040, 0x205a, 0x2062, 0x609f, 0x0000, 0xa065, 0x609c, 0xa005, - 0x00c0, 0x2052, 0x7848, 0x794a, 0x2062, 0x0c7f, 0x7848, 0x2062, - 0x609f, 0x0000, 0xac85, 0x0000, 0x00c0, 0x2068, 0x1078, 0x28ec, - 0x784a, 0x007c, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e, - 0x00c8, 0x2073, 0xa200, 0x00f0, 0x206e, 0x8086, 0x818e, 0x007c, - 0x157e, 0x20a9, 0x0010, 0xa005, 0x0040, 0x2099, 0xa11a, 0x00c8, - 0x2099, 0x8213, 0x818d, 0x0048, 0x208c, 0xa11a, 0x00c8, 0x208d, - 0x00f0, 0x2081, 0x0078, 0x2091, 0xa11a, 0x2308, 0x8210, 0x00f0, - 0x2081, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f, 0x157f, - 0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078, 0x2095, 0x7d74, - 0x70d0, 0xa506, 0x0040, 0x2185, 0x7810, 0x2050, 0x7800, 0xd08c, - 0x0040, 0x20c1, 0xdaec, 0x0040, 0x20c1, 0x0e7e, 0x2091, 0x8000, - 0x2071, 0x0020, 0x7004, 0xa005, 0x00c0, 0x20be, 0x7008, 0x0e7f, - 0xa086, 0x0008, 0x0040, 0x20c1, 0x0078, 0x2185, 0x0e7f, 0x0078, - 0x2185, 0x1078, 0x1ddb, 0x0040, 0x2185, 0xa046, 0x7970, 0x2500, - 0x8000, 0xa112, 0x2009, 0x0040, 0x00c8, 0x20d0, 0x0078, 0x20d7, - 0x72d0, 0xa206, 0x0040, 0x20d7, 0x8840, 0x2009, 0x0080, 0x0c7e, - 0x7112, 0x7007, 0x0001, 0x2099, 0x0030, 0x20a9, 0x0020, 0xac80, - 0x0001, 0x20a0, 0x2061, 0x0000, 0x88ff, 0x0040, 0x20e9, 0x1078, - 0x1ddb, 0x7008, 0xd0fc, 0x0040, 0x20e9, 0x7007, 0x0002, 0x2091, - 0x8001, 0xa08c, 0x01e0, 0x00c0, 0x2120, 0x53a5, 0x8cff, 0x00c0, - 0x20fe, 0x88ff, 0x0040, 0x216f, 0x0078, 0x2108, 0x2c00, 0x788e, - 0x20a9, 0x0020, 0xac80, 0x0001, 0x20a0, 0x53a5, 0x0078, 0x216f, - 0xa046, 0x7218, 0x731c, 0xdac4, 0x0040, 0x2110, 0x7420, 0x7524, - 0xa292, 0x0040, 0xa39b, 0x0000, 0xa4a3, 0x0000, 0xa5ab, 0x0000, - 0x721a, 0x731e, 0xdac4, 0x0040, 0x2120, 0x7422, 0x7526, 0xa006, - 0x7007, 0x0004, 0x0040, 0x216f, 0x8cff, 0x0040, 0x2129, 0x1078, - 0x1de4, 0x0c7f, 0x1078, 0x1de4, 0xa046, 0x7888, 0x8000, 0x788a, - 0xa086, 0x0002, 0x0040, 0x214f, 0x7a7c, 0x7b78, 0xdac4, 0x0040, - 0x213b, 0x7c84, 0x7d80, 0x7974, 0x8107, 0x8004, 0x8004, 0xa210, - 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x721a, 0x731e, - 0xdac4, 0x0040, 0x2185, 0x7422, 0x7526, 0x0078, 0x2185, 0x6014, - 0xd0fc, 0x00c0, 0x2157, 0x2069, 0x4a40, 0x0078, 0x2159, 0x2069, - 0x4a80, 0x2091, 0x8000, 0x681f, 0x0002, 0x88ff, 0x0040, 0x2165, - 0xa046, 0x788c, 0x2060, 0x0078, 0x214f, 0x788b, 0x0000, 0x78ac, - 0xa085, 0x0003, 0x78ae, 0x2091, 0x8001, 0x0078, 0x2185, 0x0c7f, - 0x788b, 0x0000, 0x1078, 0x2319, 0x6004, 0xa084, 0x000f, 0x1078, - 0x2186, 0x88ff, 0x0040, 0x2183, 0x788c, 0x2060, 0x6004, 0xa084, - 0x000f, 0x1078, 0x2186, 0x0078, 0x209f, 0x007c, 0x0079, 0x2188, - 0x2198, 0x21b6, 0x21d4, 0x2198, 0x21e5, 0x21a9, 0x2198, 0x2198, - 0x2198, 0x21b4, 0x21d2, 0x2198, 0x2198, 0x2198, 0x2198, 0x2198, - 0x2039, 0x0400, 0x78bc, 0xa705, 0x78be, 0x6008, 0xa705, 0x600a, - 0x1078, 0x2228, 0x609c, 0x78ba, 0x609f, 0x0000, 0x1078, 0x2303, - 0x007c, 0x78bc, 0xd0c4, 0x0040, 0x21af, 0x0078, 0x2198, 0x601c, - 0xc0bd, 0x601e, 0x0078, 0x21bc, 0x1078, 0x234b, 0x78bc, 0xd0c4, - 0x0040, 0x21bc, 0x0078, 0x2198, 0x78bf, 0x0000, 0x6004, 0x8007, - 0xa084, 0x00ff, 0x78b2, 0x8001, 0x0040, 0x21cf, 0x1078, 0x2228, - 0x0040, 0x21cf, 0x78bc, 0xc0c5, 0x78be, 0x0078, 0x21d1, 0x0078, - 0x2247, 0x007c, 0x1078, 0x2347, 0x78bc, 0xa08c, 0x0e00, 0x00c0, - 0x21dc, 0xd0c4, 0x00c0, 0x21de, 0x0078, 0x2198, 0x1078, 0x2228, - 0x00c0, 0x21e4, 0x0078, 0x2247, 0x007c, 0x78bc, 0xd0c4, 0x0040, - 0x21eb, 0x0078, 0x2198, 0x78bf, 0x0000, 0x6714, 0x2011, 0x0001, - 0x22a8, 0x6018, 0xa084, 0x00ff, 0xa005, 0x0040, 0x220b, 0xa7bc, - 0xff00, 0x20a9, 0x0020, 0xa08e, 0x0001, 0x0040, 0x220b, 0xa7bc, - 0x8000, 0x2011, 0x0002, 0x20a9, 0x0100, 0xa08e, 0x0002, 0x0040, - 0x220b, 0x0078, 0x2225, 0x1078, 0x1e02, 0x2d00, 0x2091, 0x8000, - 0x682b, 0x0000, 0x682f, 0x0000, 0x6808, 0xa084, 0xffde, 0x680a, - 0xade8, 0x0010, 0x2091, 0x8001, 0x00f0, 0x220e, 0x8211, 0x0040, - 0x2225, 0x20a9, 0x0100, 0x0078, 0x220e, 0x1078, 0x1de4, 0x007c, - 0x609f, 0x0000, 0x78b4, 0xa06d, 0x2c00, 0x78b6, 0x00c0, 0x2233, - 0x78ba, 0x0078, 0x223b, 0x689e, 0x2d00, 0x6002, 0x78b8, 0xad06, - 0x00c0, 0x223b, 0x6002, 0x78b0, 0x8001, 0x78b2, 0x00c0, 0x2246, - 0x78bc, 0xc0c4, 0x78be, 0x78b8, 0x2060, 0xa006, 0x007c, 0x0e7e, - 0xa02e, 0x2530, 0x7dba, 0x7db6, 0x65ae, 0x65b2, 0x601c, 0x60a2, - 0x2048, 0xa984, 0xe1ff, 0x601e, 0xa984, 0x0060, 0x0040, 0x225a, - 0x1078, 0x43c1, 0x6596, 0x65a6, 0x669a, 0x66aa, 0x6714, 0x2071, - 0x4a80, 0xd7fc, 0x00c0, 0x2266, 0x2071, 0x4a40, 0xa784, 0x0f00, - 0x800b, 0xa784, 0x001f, 0x0040, 0x2271, 0x8003, 0x8003, 0x8003, - 0x8003, 0xa105, 0x71c4, 0xa168, 0x2700, 0x8007, 0xa084, 0x000f, - 0x8003, 0x8003, 0x8003, 0x71c8, 0xa100, 0x60c2, 0x2091, 0x8000, - 0x7810, 0xd0f4, 0x00c0, 0x228b, 0x6e08, 0xd684, 0x0040, 0x22a1, - 0xd9fc, 0x00c0, 0x22a1, 0x2091, 0x8001, 0x1078, 0x1e6f, 0x2091, - 0x8000, 0x1078, 0x201b, 0x2091, 0x8001, 0x7814, 0xd0e4, 0x00c0, - 0x2301, 0x7810, 0xd0f4, 0x0040, 0x2301, 0x601b, 0x0021, 0x0078, - 0x2301, 0x6024, 0xa096, 0x0001, 0x00c0, 0x22a8, 0x8000, 0x6026, - 0x6a10, 0x6814, 0xa202, 0x0048, 0x22bb, 0x0040, 0x22bb, 0x2091, - 0x8001, 0x2039, 0x0200, 0x609c, 0x78ba, 0x609f, 0x0000, 0x1078, - 0x2303, 0x0078, 0x2301, 0x2c08, 0xd9fc, 0x0040, 0x22de, 0x6800, - 0xa065, 0x0040, 0x22de, 0x6a04, 0x7000, 0xa084, 0x0002, 0x0040, - 0x22d9, 0x704c, 0xa206, 0x00c0, 0x22d9, 0x6b04, 0x2160, 0x2304, - 0x6002, 0xa005, 0x00c0, 0x22d5, 0x6902, 0x2260, 0x6102, 0x0078, - 0x22ea, 0x2160, 0x6202, 0x6906, 0x0078, 0x22ea, 0x6800, 0x6902, - 0xa065, 0x0040, 0x22e6, 0x6102, 0x0078, 0x22e7, 0x6906, 0x2160, - 0x6003, 0x0000, 0x2160, 0xd9fc, 0x0040, 0x22f1, 0xa6b4, 0xfffc, - 0x6e0a, 0x6810, 0x7d08, 0x8528, 0x7d0a, 0x8000, 0x6812, 0x2091, - 0x8001, 0xd6b4, 0x0040, 0x2301, 0xa6b6, 0x0040, 0x6e0a, 0x1078, - 0x1e80, 0x0e7f, 0x007c, 0x6008, 0xa705, 0x600a, 0x2091, 0x8000, - 0x1078, 0x201b, 0x2091, 0x8001, 0x78b8, 0xa065, 0x0040, 0x2316, - 0x609c, 0x78ba, 0x609f, 0x0000, 0x0078, 0x2303, 0x78b6, 0x78ba, - 0x007c, 0x7970, 0x7874, 0x2818, 0xd384, 0x0040, 0x2323, 0x8000, - 0xa112, 0x0048, 0x2328, 0x8000, 0xa112, 0x00c8, 0x2338, 0xc384, - 0x7a7c, 0x721a, 0x7a78, 0x721e, 0xdac4, 0x0040, 0x2333, 0x7a84, - 0x7222, 0x7a80, 0x7226, 0xa006, 0xd384, 0x0040, 0x2338, 0x8000, - 0x7876, 0x70d2, 0x781c, 0xa005, 0x0040, 0x2346, 0x8001, 0x781e, - 0x00c0, 0x2346, 0x0068, 0x2346, 0x2091, 0x4080, 0x007c, 0x2039, - 0x235f, 0x0078, 0x234d, 0x2039, 0x2365, 0x2704, 0xa005, 0x0040, - 0x235e, 0xac00, 0x2068, 0x6908, 0x6810, 0x6912, 0x680a, 0x690c, - 0x6814, 0x6916, 0x680e, 0x8738, 0x0078, 0x234d, 0x007c, 0x0003, - 0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0015, 0x001b, 0x0000, - 0x2041, 0x0000, 0x780c, 0x0079, 0x236d, 0x2535, 0x2508, 0x2371, - 0x23e5, 0x2039, 0x9274, 0x2734, 0x7d10, 0x0078, 0x238c, 0x6084, - 0xa086, 0x0103, 0x00c0, 0x23ce, 0x6114, 0x6018, 0xa105, 0x00c0, - 0x23ce, 0x8603, 0xa080, 0x9255, 0x620c, 0x2202, 0x8000, 0x6210, - 0x2202, 0x1078, 0x203d, 0x8630, 0xa68e, 0x000f, 0x0040, 0x2454, - 0x786c, 0xa065, 0x00c0, 0x2377, 0x7808, 0xa602, 0x00c8, 0x239d, - 0xd5ac, 0x00c0, 0x239d, 0x263a, 0x007c, 0xa682, 0x0003, 0x00c8, - 0x2454, 0x2091, 0x8000, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0, - 0x23c9, 0x2011, 0x9255, 0x2204, 0x70c6, 0x8210, 0x2204, 0x70ca, - 0xd684, 0x00c0, 0x23b9, 0x8210, 0x2204, 0x70da, 0x8210, 0x2204, - 0x70de, 0xa685, 0x8020, 0x70c2, 0x681b, 0x0001, 0x2091, 0x4080, - 0x7810, 0xa084, 0xffcf, 0x7812, 0x2091, 0x8001, 0x203b, 0x0000, - 0x007c, 0x7810, 0xc0ad, 0x7812, 0x0078, 0x2454, 0x263a, 0x1078, - 0x253f, 0x00c0, 0x254e, 0x786c, 0xa065, 0x00c0, 0x2377, 0x2091, - 0x8000, 0x7810, 0xa084, 0xffcf, 0x86ff, 0x0040, 0x23e0, 0xc0ad, - 0x7812, 0x2091, 0x8001, 0x0078, 0x254e, 0x2039, 0x9274, 0x2734, - 0x7d10, 0x0078, 0x23fc, 0x6084, 0xa086, 0x0103, 0x00c0, 0x243d, - 0x6114, 0x6018, 0xa105, 0x00c0, 0x243d, 0xa680, 0x9255, 0x620c, - 0x2202, 0x1078, 0x203d, 0x8630, 0xa68e, 0x001e, 0x0040, 0x2454, - 0x786c, 0xa065, 0x00c0, 0x23eb, 0x7808, 0xa602, 0x00c8, 0x240d, - 0xd5ac, 0x00c0, 0x240d, 0x263a, 0x007c, 0xa682, 0x0006, 0x00c8, - 0x2454, 0x2091, 0x8000, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0, - 0x2438, 0x2011, 0x9255, 0x2009, 0x924e, 0x26a8, 0x211c, 0x2204, - 0x201a, 0x8108, 0x8210, 0x00f0, 0x241e, 0xa685, 0x8030, 0x70c2, + 0xa1a2, 0x4d00, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, + 0xa192, 0x9700, 0x2009, 0x0000, 0x2001, 0x0032, 0x1078, 0x2061, + 0x2218, 0x2079, 0x4d00, 0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9, + 0x0040, 0x42a4, 0x8109, 0x00c0, 0x10bf, 0x2009, 0xff00, 0x3400, + 0xa102, 0x0048, 0x10cf, 0x0040, 0x10cf, 0x20a8, 0x42a4, 0x2001, + 0x04fc, 0x2004, 0xa086, 0x1080, 0x00c0, 0x10e5, 0x2071, 0x0100, + 0x0d7e, 0x2069, 0x4d40, 0x1078, 0x4c38, 0x0d7f, 0x7810, 0xc0ed, + 0x7812, 0x781b, 0x0064, 0x0078, 0x110a, 0x2001, 0x04fc, 0x2004, + 0xa086, 0x1280, 0x00c0, 0x1105, 0x7814, 0xc0ed, 0xc0d5, 0x7816, + 0x781b, 0x0064, 0x2071, 0x0200, 0x0d7e, 0x2069, 0x4d40, 0x1078, + 0x4c38, 0x2069, 0x4d80, 0x2071, 0x0100, 0x1078, 0x4c38, 0x7814, + 0xc0d4, 0x7816, 0x0d7f, 0x0078, 0x110a, 0x7814, 0xc0e5, 0x7816, + 0x781b, 0x003c, 0x7eca, 0x7cc2, 0x7bc6, 0x7867, 0x0000, 0x7800, + 0xc08d, 0x7802, 0x2031, 0x0030, 0x78af, 0x0101, 0x7823, 0x0002, + 0x7827, 0x0002, 0x2009, 0x0002, 0x2069, 0x4d40, 0x681b, 0x0003, + 0x6823, 0x0007, 0x6827, 0x00fa, 0x682b, 0x0008, 0x682f, 0x0028, + 0x6837, 0x0000, 0x683b, 0x0006, 0x6833, 0x0008, 0x683f, 0x0000, + 0x8109, 0x0040, 0x115e, 0x68d3, 0x000a, 0x68c3, 0x4dc0, 0x2079, + 0x4d00, 0x7814, 0xd0e4, 0x00c0, 0x1144, 0xd0ec, 0x00c0, 0x1148, + 0x68d7, 0x7329, 0x0078, 0x114a, 0x68d7, 0x730d, 0x0078, 0x114a, + 0x68d7, 0x732d, 0x68c7, 0x52c0, 0x68cb, 0x51c0, 0x68cf, 0x92c0, + 0x68ab, 0x9544, 0x68af, 0x9549, 0x68b3, 0x9544, 0x68b7, 0x9544, + 0x68a7, 0x0001, 0x2069, 0x4d80, 0x0078, 0x111e, 0x68d3, 0x000a, + 0x68c3, 0x4fc0, 0x7814, 0xd0e4, 0x00c0, 0x116a, 0x68d7, 0x7439, + 0x0078, 0x116c, 0x68d7, 0x7419, 0x68c7, 0x72c0, 0x68cb, 0x5240, + 0x68cf, 0x93d0, 0x68ab, 0x9549, 0x68af, 0x954e, 0x68b3, 0x9549, + 0x68b7, 0x9549, 0x68a7, 0x0001, 0x7810, 0xd0ec, 0x00c0, 0x11c2, + 0x7814, 0xd0e4, 0x00c0, 0x11b4, 0x0e7e, 0x2069, 0x51c0, 0x2071, + 0x0200, 0x70ec, 0xd0e4, 0x00c0, 0x1195, 0x2019, 0x0c0c, 0x2021, + 0x000c, 0x1078, 0x1ff0, 0x0078, 0x119b, 0x2019, 0x0c0a, 0x2021, + 0x000a, 0x1078, 0x1ff0, 0x2069, 0x5240, 0x2071, 0x0100, 0x70ec, + 0xd0e4, 0x00c0, 0x11ab, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x1078, + 0x1ff0, 0x0078, 0x11b1, 0x2019, 0x0c0a, 0x2021, 0x000a, 0x1078, + 0x1ff0, 0x0e7f, 0x0078, 0x11db, 0x2019, 0x0c0c, 0x2021, 0x000c, + 0x2069, 0x51c0, 0x1078, 0x1ff0, 0x2069, 0x5240, 0x1078, 0x1ff0, + 0x0078, 0x11db, 0x2069, 0x51c0, 0x0e7e, 0x2071, 0x0100, 0x70ec, + 0xd0e4, 0x00c0, 0x11d4, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x1078, + 0x1ff0, 0x0e7f, 0x0078, 0x11db, 0x2019, 0x0c0a, 0x2021, 0x000a, + 0x1078, 0x1ff0, 0x0e7f, 0x2011, 0x0002, 0x2069, 0x52c0, 0x2009, + 0x0002, 0x20a9, 0x0100, 0x6837, 0x0000, 0x680b, 0x0040, 0x7bc8, + 0xa386, 0xfeff, 0x00c0, 0x11f2, 0x6817, 0x0100, 0x681f, 0x0064, + 0x0078, 0x11f6, 0x6817, 0x0064, 0x681f, 0x0002, 0xade8, 0x0010, + 0x00f0, 0x11e3, 0x8109, 0x00c0, 0x11e1, 0x8211, 0x0040, 0x1204, + 0x2069, 0x72c0, 0x0078, 0x11df, 0x1078, 0x261d, 0x1078, 0x4603, + 0x1078, 0x1dbb, 0x1078, 0x4be1, 0x2091, 0x2100, 0x2079, 0x4d00, + 0x7810, 0xd0ec, 0x0040, 0x1218, 0x2071, 0x0020, 0x0078, 0x121a, + 0x2071, 0x0050, 0x2091, 0x2200, 0x2079, 0x4d00, 0x2071, 0x0020, + 0x2091, 0x2300, 0x2079, 0x4d00, 0x7810, 0xd0ec, 0x0040, 0x122c, + 0x2079, 0x0100, 0x0078, 0x122e, 0x2079, 0x0200, 0x2071, 0x4d40, + 0x2091, 0x2400, 0x2079, 0x0100, 0x2071, 0x4d80, 0x2091, 0x2000, + 0x2079, 0x4d00, 0x2071, 0x0010, 0x3200, 0xa085, 0x303d, 0x2090, + 0x2071, 0x0010, 0x70c3, 0x0000, 0x0090, 0x124d, 0x70c0, 0xa086, + 0x0002, 0x00c0, 0x124d, 0x1078, 0x15ba, 0x2039, 0x0000, 0x7810, + 0xd0ec, 0x00c0, 0x12cf, 0x1078, 0x148e, 0x78ac, 0xa005, 0x00c0, + 0x126b, 0x0068, 0x1261, 0x786c, 0xa065, 0x0040, 0x1261, 0x1078, + 0x2356, 0x1078, 0x2088, 0x0068, 0x1278, 0x786c, 0xa065, 0x0040, + 0x126b, 0x1078, 0x2356, 0x0068, 0x1278, 0x2009, 0x4d47, 0x2011, + 0x4d87, 0x2104, 0x220c, 0xa105, 0x0040, 0x1278, 0x1078, 0x1ef1, + 0x2071, 0x4d40, 0x70a4, 0xa005, 0x0040, 0x129d, 0x7450, 0xa485, + 0x0000, 0x0040, 0x129d, 0x2079, 0x0200, 0x2091, 0x8000, 0x72d4, + 0xa28c, 0x303d, 0x2190, 0x1078, 0x2b0b, 0x2091, 0x8000, 0x2091, + 0x303d, 0x0068, 0x129d, 0x2079, 0x4d00, 0x786c, 0xa065, 0x0040, + 0x129d, 0x2071, 0x0010, 0x1078, 0x2356, 0x00e0, 0x12a5, 0x2079, + 0x4d00, 0x2071, 0x0010, 0x1078, 0x49ba, 0x2071, 0x4d80, 0x70a4, + 0xa005, 0x0040, 0x12bd, 0x7050, 0xa025, 0x0040, 0x12bd, 0x2079, + 0x0100, 0x2091, 0x8000, 0x72d4, 0xa28c, 0x303d, 0x2190, 0x1078, + 0x2b0b, 0x2091, 0x8000, 0x2091, 0x303d, 0x2079, 0x4d00, 0x2071, + 0x0010, 0x0068, 0x12c9, 0x786c, 0xa065, 0x0040, 0x12c9, 0x1078, + 0x2356, 0x00e0, 0x1253, 0x1078, 0x49ba, 0x0078, 0x1253, 0x1078, + 0x148e, 0x78ac, 0xa005, 0x00c0, 0x12e7, 0x0068, 0x12dd, 0x786c, + 0xa065, 0x0040, 0x12dd, 0x1078, 0x2356, 0x1078, 0x2088, 0x0068, + 0x12f1, 0x786c, 0xa065, 0x0040, 0x12e7, 0x1078, 0x2356, 0x0068, + 0x12f1, 0x2009, 0x4d47, 0x2104, 0xa005, 0x0040, 0x12f1, 0x1078, + 0x1ef1, 0x2071, 0x4d40, 0x70a4, 0xa005, 0x0040, 0x130c, 0x7450, + 0xa485, 0x0000, 0x0040, 0x130c, 0x2079, 0x0100, 0x2091, 0x8000, + 0x72d4, 0xa28c, 0x303d, 0x2190, 0x1078, 0x2b0b, 0x2091, 0x8000, + 0x2091, 0x303d, 0x2079, 0x4d00, 0x2071, 0x0010, 0x0068, 0x1316, + 0x786c, 0xa065, 0x0040, 0x1316, 0x1078, 0x2356, 0x00e0, 0x12cf, + 0x1078, 0x49ba, 0x0078, 0x12cf, 0x133c, 0x133c, 0x133e, 0x133e, + 0x134b, 0x134b, 0x134b, 0x134b, 0x1356, 0x1356, 0x1363, 0x1363, + 0x134b, 0x134b, 0x134b, 0x134b, 0x133c, 0x133c, 0x133e, 0x133e, + 0x134b, 0x134b, 0x134b, 0x134b, 0x1356, 0x1356, 0x1363, 0x1363, + 0x134b, 0x134b, 0x134b, 0x134b, 0x0078, 0x133c, 0x007e, 0x107e, + 0x127e, 0x2091, 0x2400, 0x1078, 0x292b, 0x127f, 0x107f, 0x007f, + 0x2091, 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x1078, 0x13c8, + 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007e, 0x107e, + 0x127e, 0x2091, 0x2300, 0x1078, 0x292b, 0x127f, 0x107f, 0x007f, + 0x2091, 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x2091, 0x2300, + 0x1078, 0x292b, 0x2091, 0x2400, 0x1078, 0x292b, 0x127f, 0x107f, + 0x007f, 0x2091, 0x8001, 0x007c, 0x1394, 0x1394, 0x1396, 0x1396, + 0x13a3, 0x13a3, 0x13a3, 0x13a3, 0x13ae, 0x13ae, 0x1396, 0x1396, + 0x13a3, 0x13a3, 0x13a3, 0x13a3, 0x13af, 0x13af, 0x13af, 0x13af, + 0x13af, 0x13af, 0x13af, 0x13af, 0x13af, 0x13af, 0x13af, 0x13af, + 0x13af, 0x13af, 0x13af, 0x13af, 0x0078, 0x1394, 0x007e, 0x107e, + 0x127e, 0x2091, 0x2300, 0x1078, 0x292b, 0x127f, 0x107f, 0x007f, + 0x2091, 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x1078, 0x13d5, + 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007c, 0x107e, + 0x127e, 0x0d7e, 0x0e7e, 0x0f7e, 0x007e, 0x2071, 0x0100, 0x2069, + 0x4d40, 0x2079, 0x4d00, 0x70ec, 0xa084, 0x1c00, 0x78e2, 0x1078, + 0x4c38, 0x007f, 0x0f7f, 0x0e7f, 0x0d7f, 0x127f, 0x107f, 0x007c, + 0x3c00, 0xa084, 0x0007, 0x0079, 0x13cd, 0x13de, 0x13de, 0x13e0, + 0x13e0, 0x13e5, 0x13e5, 0x13ea, 0x13ea, 0x3c00, 0xa084, 0x0003, + 0x0079, 0x13da, 0x13de, 0x13de, 0x13f3, 0x13f3, 0x1078, 0x290c, + 0x2091, 0x2200, 0x1078, 0x46dd, 0x007c, 0x2091, 0x2100, 0x1078, + 0x46dd, 0x007c, 0x2091, 0x2100, 0x1078, 0x46dd, 0x2091, 0x2200, + 0x1078, 0x46dd, 0x007c, 0x2091, 0x2100, 0x1078, 0x46dd, 0x007c, + 0x1418, 0x1418, 0x141a, 0x141a, 0x1427, 0x1427, 0x1427, 0x1427, + 0x1432, 0x1432, 0x143f, 0x143f, 0x1427, 0x1427, 0x1427, 0x1427, + 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, + 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, + 0x0078, 0x1418, 0x007e, 0x107e, 0x127e, 0x2091, 0x2400, 0x1078, + 0x292b, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007e, + 0x107e, 0x127e, 0x1078, 0x13c8, 0x127f, 0x107f, 0x007f, 0x2091, + 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x2091, 0x2300, 0x1078, + 0x292b, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007e, + 0x107e, 0x127e, 0x2091, 0x2300, 0x1078, 0x292b, 0x2091, 0x2400, + 0x1078, 0x292b, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, + 0x007e, 0x107e, 0x127e, 0x0d7e, 0x0e7e, 0x0f7e, 0x2079, 0x4d00, + 0x2071, 0x0200, 0x2069, 0x4d40, 0x3d00, 0xd08c, 0x0040, 0x1466, + 0x70ec, 0xa084, 0x1c00, 0x78e2, 0x1078, 0x4c38, 0x3d00, 0xd084, + 0x0040, 0x1474, 0x2069, 0x4d80, 0x2071, 0x0100, 0x70ec, 0xa084, + 0x1c00, 0x78e6, 0x1078, 0x4c38, 0x0f7f, 0x0e7f, 0x0d7f, 0x127f, + 0x107f, 0x007f, 0x007c, 0x7008, 0x800b, 0x00c8, 0x1489, 0x7007, + 0x0002, 0xa08c, 0x01e0, 0x00c0, 0x148a, 0xd09c, 0x0040, 0x1489, + 0x087a, 0x097a, 0x70c3, 0x4002, 0x0078, 0x15bd, 0x0068, 0x1513, + 0x2061, 0x0000, 0x6018, 0xd084, 0x00c0, 0x1513, 0x7828, 0xa005, + 0x00c0, 0x149e, 0x0010, 0x1514, 0x0078, 0x1513, 0x7910, 0xd1f4, + 0x0040, 0x14a6, 0x2001, 0x4007, 0x0078, 0x15bc, 0x7914, 0xd1ec, + 0x0040, 0x14c1, 0xd0fc, 0x0040, 0x14b7, 0x007e, 0x1078, 0x1d4b, + 0x007f, 0x0040, 0x14c1, 0x2001, 0x4007, 0x0078, 0x15bc, 0x007e, + 0x1078, 0x1d3b, 0x007f, 0x0040, 0x14c1, 0x2001, 0x4007, 0x0078, + 0x15bc, 0x7910, 0xd0fc, 0x00c0, 0x14cb, 0x2061, 0x4d40, 0xc19c, + 0xc7fc, 0x0078, 0x14cf, 0x2061, 0x4d80, 0xc19d, 0xc7fd, 0x6064, + 0xa005, 0x00c0, 0x1513, 0x7912, 0x6083, 0x0000, 0x7828, 0xc0fc, + 0xa086, 0x0018, 0x00c0, 0x14e0, 0x0c7e, 0x1078, 0x1b44, 0x0c7f, + 0x782b, 0x0000, 0x607c, 0xa065, 0x0040, 0x14f9, 0x0c7e, 0x609c, + 0x1078, 0x1e30, 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1c6d, 0x2009, + 0x0018, 0x6087, 0x0103, 0x1078, 0x1d5b, 0x00c0, 0x150d, 0x1078, + 0x1dad, 0x7810, 0xd09c, 0x00c0, 0x1501, 0x2061, 0x4d40, 0x0078, + 0x1505, 0x2061, 0x4d80, 0xc09c, 0x7812, 0x607f, 0x0000, 0x60d4, + 0xd0dc, 0x0040, 0x1511, 0xc0dc, 0x60d6, 0x2001, 0x4005, 0x0078, + 0x15bc, 0x0078, 0x15ba, 0x007c, 0x7810, 0xd0f4, 0x0040, 0x151c, + 0x2001, 0x4007, 0x0078, 0x15bc, 0xa006, 0x70c2, 0x70c6, 0x70ca, + 0x70ce, 0x70da, 0x70c0, 0xa03d, 0xa08a, 0x0040, 0x00c8, 0x152a, + 0x0079, 0x1531, 0x2100, 0xa08a, 0x0040, 0x00c8, 0x15c8, 0x0079, + 0x1571, 0x15ba, 0x1610, 0x15d9, 0x1648, 0x1680, 0x1680, 0x15d0, + 0x1c85, 0x168b, 0x15c8, 0x15dd, 0x15df, 0x15e1, 0x15e3, 0x1c8a, + 0x15c8, 0x1699, 0x16f6, 0x1b64, 0x1c7f, 0x15e5, 0x19d4, 0x1a16, + 0x1a4e, 0x1a9c, 0x198f, 0x199c, 0x19b0, 0x19c3, 0x17cb, 0x15c8, + 0x172d, 0x173a, 0x1746, 0x1752, 0x1768, 0x1774, 0x1777, 0x1783, + 0x178f, 0x1797, 0x17b3, 0x17bf, 0x15c8, 0x15c8, 0x15c8, 0x15c8, + 0x17d8, 0x17ea, 0x1806, 0x183c, 0x1864, 0x1874, 0x1877, 0x18a8, + 0x18d9, 0x18eb, 0x195e, 0x196e, 0x15c8, 0x15c8, 0x15c8, 0x15c8, + 0x197e, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x1caf, 0x1cb5, + 0x15c8, 0x15c8, 0x15c8, 0x1cb9, 0x1cfe, 0x15c8, 0x15c8, 0x15c8, + 0x15c8, 0x160a, 0x167a, 0x1693, 0x16f0, 0x1b5e, 0x15c8, 0x15c8, + 0x15c8, 0x15c8, 0x1d02, 0x1ca1, 0x1cab, 0x15c8, 0x15c8, 0x15c8, + 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, + 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, + 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, + 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, + 0x15c8, 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0078, 0x15bc, 0x73ce, + 0x72ca, 0x71c6, 0x2001, 0x4000, 0x70c2, 0x0068, 0x15bd, 0x2061, + 0x0000, 0x601b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x007c, + 0x70c3, 0x4001, 0x0078, 0x15bd, 0x70c3, 0x4006, 0x0078, 0x15bd, + 0x2099, 0x0041, 0x20a1, 0x0041, 0x20a9, 0x0005, 0x53a3, 0x0078, + 0x15ba, 0x70c4, 0x70c3, 0x0004, 0x007a, 0x0078, 0x15ba, 0x0078, + 0x15ba, 0x0078, 0x15ba, 0x0078, 0x15ba, 0x2091, 0x8000, 0x70c3, + 0x0004, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, + 0x0008, 0x2001, 0x000d, 0x70d6, 0x2079, 0x0000, 0x781b, 0x0001, + 0x2031, 0x0030, 0x2059, 0x1000, 0x2029, 0x041a, 0x2051, 0x0445, + 0x2061, 0x0447, 0x20c1, 0x0020, 0x2091, 0x5000, 0x2091, 0x4080, + 0x0078, 0x0418, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x1613, + 0x2029, 0x0000, 0x2520, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x20a0, + 0x2099, 0x0030, 0x7003, 0x0001, 0x7007, 0x0006, 0x731a, 0x721e, + 0x7422, 0x7526, 0x2021, 0x0040, 0x81ff, 0x0040, 0x15ba, 0xa182, + 0x0040, 0x00c8, 0x162d, 0x2120, 0xa006, 0x2008, 0x8403, 0x7012, + 0x7007, 0x0004, 0x7007, 0x0001, 0x7008, 0xd0fc, 0x0040, 0x1634, + 0x7007, 0x0002, 0xa084, 0x01e0, 0x0040, 0x1642, 0x70c3, 0x4002, + 0x0078, 0x15bd, 0x24a8, 0x53a5, 0x0078, 0x1624, 0x0078, 0x15ba, + 0x2029, 0x0000, 0x2520, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x2098, + 0x20a1, 0x0030, 0x7003, 0x0000, 0x7007, 0x0006, 0x731a, 0x721e, + 0x7422, 0x7526, 0x2021, 0x0040, 0x7007, 0x0006, 0x81ff, 0x0040, + 0x15ba, 0xa182, 0x0040, 0x00c8, 0x1667, 0x2120, 0xa006, 0x2008, + 0x8403, 0x7012, 0x24a8, 0x53a6, 0x7007, 0x0001, 0x7008, 0xd0fc, + 0x0040, 0x166e, 0xa084, 0x01e0, 0x0040, 0x165c, 0x70c3, 0x4002, + 0x0078, 0x15bd, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x164b, + 0x71c4, 0x70c8, 0x2114, 0xa79e, 0x0004, 0x00c0, 0x1688, 0x200a, + 0x72ca, 0x0078, 0x15b9, 0x70c7, 0x0008, 0x70cb, 0x000d, 0x70cf, + 0x0008, 0x0078, 0x15ba, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078, + 0x169c, 0x2029, 0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d0, + 0x70c6, 0x72ca, 0x73ce, 0x74d2, 0xa005, 0x0040, 0x16eb, 0xa40a, + 0x0040, 0x16ac, 0x00c8, 0x15bc, 0x8001, 0x7872, 0xa084, 0xfc00, + 0x0040, 0x16b9, 0x78ac, 0xc085, 0x78ae, 0x2001, 0x4005, 0x0078, + 0x15bc, 0x7b7e, 0x7a7a, 0x7e86, 0x7d82, 0x7c76, 0xa48c, 0xff00, + 0x0040, 0x16d1, 0x8407, 0x8004, 0x8004, 0x810c, 0x810c, 0x810f, + 0xa118, 0xa291, 0x0000, 0xa6b1, 0x0000, 0xa581, 0x0000, 0x0078, + 0x16db, 0x8407, 0x8004, 0x8004, 0xa318, 0xa291, 0x0000, 0xa6b1, + 0x0000, 0xa581, 0x0000, 0x731a, 0x721e, 0x7622, 0x7026, 0xa605, + 0x0040, 0x16e5, 0x7a10, 0xc2c5, 0x7a12, 0x78ac, 0xa084, 0xfffc, + 0x78ae, 0x0078, 0x16ee, 0x78ac, 0xc085, 0x78ae, 0x0078, 0x15ba, + 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078, 0x16f9, 0x2029, 0x0000, + 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d4, 0x70c6, 0x72ca, 0x73ce, + 0x74d6, 0xa005, 0x0040, 0x1728, 0xa40a, 0x0040, 0x1709, 0x00c8, + 0x15bc, 0x8001, 0x7892, 0xa084, 0xfc00, 0x0040, 0x1716, 0x78ac, + 0xc0c5, 0x78ae, 0x2001, 0x4005, 0x0078, 0x15bc, 0x7a9a, 0x7b9e, + 0x7da2, 0x7ea6, 0x2600, 0xa505, 0x0040, 0x1721, 0x7a10, 0xc2c5, + 0x7a12, 0x7c96, 0x78ac, 0xa084, 0xfcff, 0x78ae, 0x0078, 0x172b, + 0x78ac, 0xc0c5, 0x78ae, 0x0078, 0x15ba, 0x2009, 0x0000, 0x786c, + 0xa065, 0x0040, 0x1737, 0x8108, 0x6000, 0x0078, 0x1730, 0x7ac4, + 0x0078, 0x15b8, 0x2009, 0x4d48, 0x210c, 0x7810, 0xd0ec, 0x00c0, + 0x15b9, 0x2011, 0x4d88, 0x2214, 0x0078, 0x15b8, 0x2009, 0x4d49, + 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x2011, 0x4d89, 0x2214, + 0x0078, 0x15b8, 0x2061, 0x4d40, 0x6128, 0x622c, 0x8214, 0x8214, + 0x8214, 0x7810, 0xd0ec, 0x00c0, 0x1766, 0x2061, 0x4d80, 0x6328, + 0x73da, 0x632c, 0x831c, 0x831c, 0x831c, 0x73de, 0x0078, 0x15b8, + 0x2009, 0x4d4c, 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x2011, + 0x4d8c, 0x2214, 0x0078, 0x15b8, 0x7918, 0x0078, 0x15b9, 0x2009, + 0x4d4d, 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x2011, 0x4d8d, + 0x2214, 0x0078, 0x15b8, 0x2009, 0x4d4e, 0x210c, 0x7810, 0xd0ec, + 0x00c0, 0x15b9, 0x2011, 0x4d8e, 0x2214, 0x0078, 0x15b8, 0x7920, + 0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x7a24, 0x0078, 0x15b8, 0x71c4, + 0xd1fc, 0x00c0, 0x179f, 0x2011, 0x51c0, 0x0078, 0x17a1, 0x2011, + 0x5240, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa268, + 0x6a00, 0x6804, 0xd09c, 0x0040, 0x17b0, 0x6b08, 0x0078, 0x17b1, + 0x6b0c, 0x0078, 0x15b7, 0x77c4, 0x1078, 0x1dcb, 0x2091, 0x8000, + 0x6b1c, 0x6a14, 0x2091, 0x8001, 0x2708, 0x0078, 0x15b7, 0x2061, + 0x4d40, 0x6118, 0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x2061, 0x4d80, + 0x6218, 0x0078, 0x15b8, 0x77c4, 0x1078, 0x1dcb, 0x2091, 0x8000, + 0x6908, 0x6a18, 0x6b10, 0x77da, 0x2091, 0x8001, 0x0078, 0x15b7, + 0x71c4, 0x2110, 0xa294, 0x000f, 0xa282, 0x0010, 0x00c8, 0x15b2, + 0x1078, 0x2735, 0xa384, 0x4000, 0x0040, 0x17e8, 0xa295, 0x0020, + 0x0078, 0x15b7, 0x71c4, 0x2100, 0xc0bc, 0xa082, 0x0010, 0x00c8, + 0x15b2, 0xd1bc, 0x00c0, 0x17f9, 0x2011, 0x4d48, 0x2204, 0x0078, + 0x17fd, 0x2011, 0x4d88, 0x2204, 0xc0bd, 0x007e, 0x2100, 0xc0bc, + 0x2012, 0x1078, 0x2692, 0x017f, 0x0078, 0x15b9, 0x71c4, 0x2021, + 0x4d49, 0x2404, 0x70c6, 0x2019, 0x0000, 0x0078, 0x1815, 0x71c8, + 0x2021, 0x4d89, 0x2404, 0x70ca, 0xc3fd, 0x2011, 0x1834, 0x20a9, + 0x0008, 0x2204, 0xa106, 0x0040, 0x1824, 0x8210, 0x00f0, 0x1819, + 0x71c4, 0x72c8, 0x0078, 0x15b1, 0xa292, 0x1834, 0x027e, 0x2122, + 0x017f, 0x1078, 0x26b3, 0x7810, 0xd0ec, 0x00c0, 0x1832, 0xd3fc, + 0x0040, 0x180f, 0x0078, 0x15ba, 0x03e8, 0x00fa, 0x01f4, 0x02ee, + 0x0064, 0x0019, 0x0032, 0x004b, 0x2061, 0x4d40, 0x6128, 0x622c, + 0x8214, 0x8214, 0x8214, 0x70c4, 0x602a, 0x70c8, 0x8003, 0x8003, + 0x8003, 0x602e, 0x7810, 0xd0ec, 0x00c0, 0x1862, 0x027e, 0x017e, + 0x2061, 0x4d80, 0x6128, 0x622c, 0x8214, 0x8214, 0x8214, 0x70d8, + 0x602a, 0x70dc, 0x8003, 0x8003, 0x8003, 0x602e, 0x71da, 0x72de, + 0x017f, 0x027f, 0x0078, 0x15b8, 0x2061, 0x4d40, 0x6130, 0x70c4, + 0x6032, 0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x2061, 0x4d80, 0x6230, + 0x70c8, 0x6032, 0x0078, 0x15b8, 0x7918, 0x0078, 0x15b9, 0x71c4, + 0xa184, 0xffcf, 0x0040, 0x1883, 0x7810, 0xd0ec, 0x00c0, 0x15b2, + 0x72c8, 0x0078, 0x15b1, 0x2011, 0x4d4d, 0x2204, 0x2112, 0x007e, + 0x2019, 0x0000, 0x1078, 0x271a, 0x7810, 0xd0ec, 0x0040, 0x1893, + 0x017f, 0x0078, 0x15b9, 0x71c8, 0xa184, 0xffcf, 0x0040, 0x189c, + 0x2110, 0x71c4, 0x0078, 0x15b1, 0x2011, 0x4d8d, 0x2204, 0x2112, + 0x007e, 0xc3fd, 0x1078, 0x271a, 0x027f, 0x017f, 0x0078, 0x15b8, + 0x71c4, 0xa182, 0x0010, 0x0048, 0x18b4, 0x7810, 0xd0ec, 0x00c0, + 0x15b2, 0x72c8, 0x0078, 0x15b1, 0x2011, 0x4d4e, 0x2204, 0x007e, + 0x2112, 0x2019, 0x0000, 0x1078, 0x26f8, 0x7810, 0xd0ec, 0x0040, + 0x18c4, 0x017f, 0x0078, 0x15b9, 0x71c8, 0xa182, 0x0010, 0x0048, + 0x18cd, 0x2110, 0x71c4, 0x0078, 0x15b1, 0x2011, 0x4d8e, 0x2204, + 0x007e, 0x2112, 0xc3fd, 0x1078, 0x26f8, 0x027f, 0x017f, 0x0078, + 0x15b8, 0x71c4, 0x72c8, 0xa184, 0xfffd, 0x00c0, 0x15b1, 0xa284, + 0xfffd, 0x00c0, 0x15b1, 0x2100, 0x7920, 0x7822, 0x2200, 0x7a24, + 0x7826, 0x0078, 0x15b8, 0x71c4, 0xd1fc, 0x00c0, 0x18f3, 0x2011, + 0x51c0, 0x0078, 0x18f5, 0x2011, 0x5240, 0x8107, 0xa084, 0x000f, + 0x8003, 0x8003, 0x8003, 0xa268, 0x2019, 0x0000, 0x72c8, 0x2091, + 0x8000, 0xa284, 0x0080, 0x0040, 0x190b, 0x6c14, 0x84ff, 0x00c0, + 0x190b, 0x6817, 0x0040, 0xa284, 0x0040, 0x0040, 0x1915, 0x6c10, + 0x84ff, 0x00c0, 0x1915, 0x6813, 0x0001, 0x6800, 0x007e, 0xa226, + 0x0040, 0x1932, 0x6a02, 0xd4ec, 0x0040, 0x191f, 0xc3a5, 0xd4e4, + 0x0040, 0x1923, 0xc39d, 0xd4f4, 0x0040, 0x1932, 0x810f, 0xd2f4, + 0x0040, 0x192e, 0x1078, 0x2777, 0x0078, 0x1932, 0x1078, 0x2755, + 0x0078, 0x1932, 0x72cc, 0x6808, 0xa206, 0x0040, 0x1954, 0xa2a4, + 0x00ff, 0x7814, 0xd0e4, 0x00c0, 0x1945, 0xa482, 0x0028, 0x0048, + 0x1951, 0x0040, 0x1951, 0x0078, 0x1949, 0xa482, 0x0043, 0x0048, + 0x1951, 0x71c4, 0x71c6, 0x027f, 0x72ca, 0x2091, 0x8001, 0x0078, + 0x15b3, 0x6a0a, 0xa39d, 0x000a, 0x6804, 0xa305, 0x6806, 0x027f, + 0x6b0c, 0x71c4, 0x2091, 0x8001, 0x0078, 0x15b7, 0x77c4, 0x1078, + 0x1dcb, 0x2091, 0x8000, 0x6a14, 0x6b1c, 0x2091, 0x8001, 0x70c8, + 0x6816, 0x70cc, 0x681e, 0x2708, 0x0078, 0x15b7, 0x70c4, 0x2061, + 0x4d40, 0x6118, 0x601a, 0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x70c8, + 0x2061, 0x4d80, 0x6218, 0x601a, 0x0078, 0x15b8, 0x71c4, 0x72c8, + 0x73cc, 0xa182, 0x0010, 0x00c8, 0x15b2, 0x1078, 0x2799, 0xa384, + 0x4000, 0x0040, 0x198d, 0xa295, 0x0020, 0x0078, 0x15b7, 0x77c4, + 0x1078, 0x1dcb, 0x2091, 0x8000, 0x6a08, 0xc28d, 0x6a0a, 0x2091, + 0x8001, 0x2708, 0x0078, 0x15b8, 0x77c4, 0x1078, 0x1dcb, 0x2091, + 0x8000, 0x6a08, 0xa294, 0xfff9, 0x6a0a, 0x6804, 0xa005, 0x0040, + 0x19ab, 0x1078, 0x25ea, 0x2091, 0x8001, 0x2708, 0x0078, 0x15b8, + 0x77c4, 0x1078, 0x1dcb, 0x2091, 0x8000, 0x6a08, 0xc295, 0x6a0a, + 0x6804, 0xa005, 0x0040, 0x19be, 0x1078, 0x25ea, 0x2091, 0x8001, + 0x2708, 0x0078, 0x15b8, 0x77c4, 0x2041, 0x0001, 0x2049, 0x0005, + 0x2051, 0x0020, 0x2091, 0x8000, 0x1078, 0x1de6, 0x2091, 0x8001, + 0x2708, 0x6a08, 0x0078, 0x15b8, 0x77c4, 0x7814, 0xd0e4, 0x00c0, + 0x19e8, 0xd7fc, 0x0040, 0x19e2, 0x1078, 0x1d4b, 0x0040, 0x19e8, + 0x0078, 0x15bc, 0x1078, 0x1d3b, 0x0040, 0x19e8, 0x0078, 0x15bc, + 0x73c8, 0x72cc, 0x77c6, 0x73ca, 0x72ce, 0x1078, 0x1e6d, 0x00c0, + 0x1a12, 0x6818, 0xa005, 0x0040, 0x1a0c, 0x2708, 0x077e, 0x1078, + 0x27c9, 0x077f, 0x00c0, 0x1a0c, 0x2001, 0x0015, 0xd7fc, 0x00c0, + 0x1a05, 0x2061, 0x4d40, 0x0078, 0x1a08, 0xc0fd, 0x2061, 0x4d80, + 0x782a, 0x2091, 0x8001, 0x007c, 0x2091, 0x8001, 0x2001, 0x4005, + 0x0078, 0x15bc, 0x2091, 0x8001, 0x0078, 0x15ba, 0x77c4, 0x7814, + 0xd0e4, 0x00c0, 0x1a2a, 0xd7fc, 0x0040, 0x1a24, 0x1078, 0x1d4b, + 0x0040, 0x1a2a, 0x0078, 0x15bc, 0x1078, 0x1d3b, 0x0040, 0x1a2a, + 0x0078, 0x15bc, 0x77c6, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, + 0x0020, 0x2091, 0x8000, 0x1078, 0x1de6, 0x2009, 0x0016, 0xd7fc, + 0x00c0, 0x1a3e, 0x2061, 0x4d40, 0x0078, 0x1a41, 0x2061, 0x4d80, + 0xc1fd, 0x6067, 0x0003, 0x607f, 0x0000, 0x6776, 0x6083, 0x000f, + 0x792a, 0x1078, 0x25ea, 0x2091, 0x8001, 0x007c, 0x77c8, 0x77ca, + 0x77c4, 0x77c6, 0x7814, 0xd0e4, 0x00c0, 0x1a65, 0xd7fc, 0x0040, + 0x1a5f, 0x1078, 0x1d4b, 0x0040, 0x1a65, 0x0078, 0x15bc, 0x1078, + 0x1d3b, 0x0040, 0x1a65, 0x0078, 0x15bc, 0xa7bc, 0xff00, 0x2091, + 0x8000, 0x2009, 0x0017, 0xd7fc, 0x00c0, 0x1a72, 0x2061, 0x4d40, + 0x0078, 0x1a75, 0x2061, 0x4d80, 0xc1fd, 0x607f, 0x0000, 0x6067, + 0x0002, 0x6776, 0x6083, 0x000f, 0x792a, 0x1078, 0x25ea, 0x2091, + 0x8001, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0010, 0x2091, + 0x8000, 0x70c8, 0xa005, 0x0040, 0x1a90, 0x60d4, 0xc0fd, 0x60d6, + 0x1078, 0x1de6, 0x70c8, 0x6836, 0x8738, 0xa784, 0x001f, 0x00c0, + 0x1a90, 0x2091, 0x8001, 0x007c, 0x7814, 0xd0e4, 0x00c0, 0x1ab0, + 0x72c8, 0xd284, 0x0040, 0x1aaa, 0x1078, 0x1d4b, 0x0040, 0x1ab0, + 0x0078, 0x15bc, 0x1078, 0x1d3b, 0x0040, 0x1ab0, 0x0078, 0x15bc, + 0x72c8, 0x72ca, 0x78ac, 0xa084, 0x0003, 0x00c0, 0x1adb, 0x2039, + 0x0000, 0xd284, 0x0040, 0x1abd, 0xc7fd, 0x2041, 0x0021, 0x2049, + 0x0004, 0x2051, 0x0008, 0x1078, 0x1dcb, 0x2091, 0x8000, 0x6808, + 0xc0d4, 0xa80d, 0x690a, 0x2091, 0x8001, 0x8738, 0xa784, 0x001f, + 0x00c0, 0x1ac3, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, + 0x0f00, 0x00c0, 0x1ac3, 0x2091, 0x8000, 0x72c8, 0xd284, 0x00c0, + 0x1aed, 0x7810, 0xd0ec, 0x0040, 0x1ae9, 0x2069, 0x0100, 0x0078, + 0x1aef, 0x2069, 0x0200, 0x0078, 0x1aef, 0x2069, 0x0100, 0x6808, + 0xa084, 0xfffd, 0x680a, 0x6830, 0xd0b4, 0x0040, 0x1b0f, 0x684b, + 0x0004, 0x20a9, 0x0014, 0x6848, 0xd094, 0x0040, 0x1b01, 0x00f0, + 0x1afb, 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xd084, 0x0040, + 0x1b0b, 0x00f0, 0x1b05, 0x20a9, 0x00fa, 0x00f0, 0x1b0d, 0x2079, + 0x4d00, 0x2009, 0x0018, 0x72c8, 0xd284, 0x00c0, 0x1b1b, 0x2061, + 0x4d40, 0x0078, 0x1b1e, 0x2061, 0x4d80, 0xc1fd, 0x792a, 0x6067, + 0x0001, 0x6083, 0x000f, 0x60a7, 0x0000, 0x60a8, 0x60b2, 0x60b6, + 0x60d4, 0xd0b4, 0x0040, 0x1b38, 0xc0b4, 0x60d6, 0x0c7e, 0x60b8, + 0xa065, 0x6008, 0xc0d4, 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f, + 0x60d4, 0xa084, 0x77ff, 0x60d6, 0x78ac, 0xc08d, 0x78ae, 0x681b, + 0x0047, 0x2091, 0x8001, 0x007c, 0xd7fc, 0x00c0, 0x1b4b, 0x2069, + 0x4d40, 0x0078, 0x1b4d, 0x2069, 0x4d80, 0x71c4, 0x71c6, 0x6916, + 0x81ff, 0x00c0, 0x1b55, 0x68a7, 0x0001, 0x78ac, 0xc08c, 0x78ae, + 0xd084, 0x00c0, 0x1b5d, 0x1078, 0x1ecd, 0x007c, 0x75d8, 0x74dc, + 0x75da, 0x74de, 0x0078, 0x1b67, 0x2029, 0x0000, 0x2520, 0x71c4, + 0x73c8, 0x72cc, 0x71c6, 0x73ca, 0x72ce, 0x2079, 0x4d00, 0x7dde, + 0x7cda, 0x7bd6, 0x7ad2, 0x1078, 0x1da4, 0x0040, 0x1c69, 0x20a9, + 0x0005, 0x20a1, 0x4d14, 0x2091, 0x8000, 0x41a1, 0x2091, 0x8001, + 0x2009, 0x0040, 0x1078, 0x1fb8, 0x0040, 0x1b8a, 0x1078, 0x1dad, + 0x0078, 0x1c69, 0x6004, 0xa08c, 0x00ff, 0xa18e, 0x0009, 0x00c0, + 0x1b95, 0x007e, 0x1078, 0x2339, 0x007f, 0xa084, 0xff00, 0x8007, + 0x8009, 0x0040, 0x1c09, 0x0c7e, 0x2c68, 0x1078, 0x1da4, 0x0040, + 0x1bdb, 0x2c00, 0x689e, 0x8109, 0x00c0, 0x1b9c, 0x609f, 0x0000, + 0x0c7f, 0x0c7e, 0x7ddc, 0x7cd8, 0x7bd4, 0x7ad0, 0xa290, 0x0040, + 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x7dde, 0x7cda, + 0x7bd6, 0x7ad2, 0x2c68, 0x689c, 0xa065, 0x0040, 0x1c08, 0x2009, + 0x0040, 0x1078, 0x1fb8, 0x00c0, 0x1bf2, 0x6004, 0xa084, 0x00ff, + 0xa086, 0x0002, 0x00c0, 0x1bdb, 0x6004, 0xa084, 0x00ff, 0xa086, + 0x000a, 0x00c0, 0x1bd7, 0x017e, 0x1078, 0x2335, 0x017f, 0x2d00, + 0x6002, 0x0078, 0x1baa, 0x0c7f, 0x0c7e, 0x609c, 0x1078, 0x1e30, + 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1c6d, 0x2009, 0x0018, 0x6008, + 0xc0cd, 0x600a, 0x6004, 0x6086, 0x1078, 0x1d5b, 0x1078, 0x1dad, + 0x0078, 0x1c69, 0x0c7f, 0x0c7e, 0x609c, 0x1078, 0x1e30, 0x0c7f, + 0x609f, 0x0000, 0x1078, 0x1c6d, 0x2009, 0x0018, 0x6087, 0x0103, + 0x601b, 0x0003, 0x1078, 0x1d5b, 0x1078, 0x1dad, 0x0078, 0x1c69, + 0x0c7f, 0x7814, 0xd0e4, 0x00c0, 0x1c2e, 0x6114, 0xd1fc, 0x0040, + 0x1c17, 0x1078, 0x1d4b, 0x0040, 0x1c2e, 0x0078, 0x1c1b, 0x1078, + 0x1d3b, 0x0040, 0x1c2e, 0x2029, 0x0000, 0x2520, 0x2009, 0x0018, + 0x73c8, 0x72cc, 0x6087, 0x0103, 0x601b, 0x0021, 0x1078, 0x1d5b, + 0x1078, 0x1dad, 0x2001, 0x4007, 0x0078, 0x15bc, 0x74c4, 0x73c8, + 0x72cc, 0x6014, 0x2091, 0x8000, 0x0e7e, 0x2009, 0x0012, 0xd0fc, + 0x00c0, 0x1c3e, 0x2071, 0x4d40, 0x0078, 0x1c41, 0x2071, 0x4d80, + 0xc1fd, 0x792a, 0x7067, 0x0005, 0x71d4, 0xc1dc, 0x71d6, 0x736a, + 0x726e, 0x7472, 0x7076, 0x707b, 0x0000, 0x2c00, 0x707e, 0xa02e, + 0x2530, 0x611c, 0xa184, 0x0060, 0x0040, 0x1c58, 0x1078, 0x45a7, + 0x0e7f, 0x6596, 0x65a6, 0x669a, 0x66aa, 0x60af, 0x0000, 0x60b3, + 0x0000, 0x6714, 0x6023, 0x0000, 0x1078, 0x25ea, 0x2091, 0x8001, + 0x007c, 0x70c3, 0x4005, 0x0078, 0x15bd, 0x20a9, 0x0005, 0x2099, + 0x4d14, 0x2091, 0x8000, 0x530a, 0x2091, 0x8001, 0x2100, 0xa210, + 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x007c, 0x71c4, + 0x70c7, 0x0000, 0x791e, 0x0078, 0x15ba, 0x71c4, 0x71c6, 0x2168, + 0x0078, 0x1c8c, 0x2069, 0x1000, 0x690c, 0xa016, 0x2d04, 0xa210, + 0x8d68, 0x8109, 0x00c0, 0x1c8e, 0xa285, 0x0000, 0x00c0, 0x1c9c, + 0x70c3, 0x4000, 0x0078, 0x1c9e, 0x70c3, 0x4003, 0x70ca, 0x0078, + 0x15bd, 0x7964, 0x71c6, 0x71c4, 0xa182, 0x0003, 0x00c8, 0x15b2, + 0x7966, 0x0078, 0x15ba, 0x7964, 0x71c6, 0x0078, 0x15ba, 0x7900, + 0x71c6, 0x71c4, 0x7902, 0x0078, 0x15ba, 0x7900, 0x71c6, 0x0078, + 0x15ba, 0x70c4, 0x2011, 0x0000, 0xa08c, 0x000d, 0x0040, 0x1cce, + 0x810c, 0x0048, 0x1cca, 0x8210, 0x810c, 0x810c, 0x0048, 0x1cca, + 0x8210, 0x810c, 0x81ff, 0x00c0, 0x15b3, 0x8210, 0x7a0e, 0xd28c, + 0x0040, 0x1cfa, 0x7910, 0xc1cd, 0x7912, 0x2009, 0x0021, 0x2019, + 0x0003, 0xd284, 0x0040, 0x1cf4, 0x8108, 0x2019, 0x0041, 0x2011, + 0x954e, 0x2312, 0x2019, 0x0042, 0x8210, 0x2312, 0x2019, 0x0043, + 0x8210, 0x2312, 0x2019, 0x0046, 0x8210, 0x2312, 0x2019, 0x0047, + 0x8210, 0x2312, 0x2019, 0x0006, 0x2011, 0x9553, 0x2112, 0x2011, + 0x9573, 0x2312, 0x7904, 0x7806, 0x0078, 0x15b9, 0x7804, 0x70c6, + 0x0078, 0x15ba, 0x71c4, 0xd1fc, 0x00c0, 0x1d0a, 0x2011, 0x51c0, + 0x0078, 0x1d0c, 0x2011, 0x5240, 0x8107, 0xa084, 0x000f, 0x8003, + 0x8003, 0x8003, 0xa268, 0x6a14, 0xd2b4, 0x0040, 0x1d1b, 0x2011, + 0x0001, 0x0078, 0x1d1d, 0x2011, 0x0000, 0x6b0c, 0x0078, 0x15b7, + 0x017e, 0x7814, 0xd0f4, 0x0040, 0x1d2d, 0x2001, 0x4007, 0x70db, + 0x0000, 0xa18d, 0x0001, 0x0078, 0x1d39, 0xd0fc, 0x0040, 0x1d38, + 0x2001, 0x4007, 0x70db, 0x0001, 0xa18d, 0x0001, 0x0078, 0x1d39, + 0xa006, 0x017f, 0x007c, 0x017e, 0x7814, 0xd0f4, 0x0040, 0x1d48, + 0x2001, 0x4007, 0x70db, 0x0000, 0xa18d, 0x0001, 0x0078, 0x1d49, + 0xa006, 0x017f, 0x007c, 0x017e, 0x7814, 0xd0fc, 0x0040, 0x1d58, + 0x2001, 0x4007, 0x70db, 0x0001, 0xa18d, 0x0001, 0x0078, 0x1d59, + 0xa006, 0x017f, 0x007c, 0x7112, 0x721a, 0x731e, 0x7810, 0xd0c4, + 0x0040, 0x1d64, 0x7422, 0x7526, 0xac80, 0x0001, 0x8108, 0x810c, + 0x81a9, 0x8098, 0x20a1, 0x0030, 0x7003, 0x0000, 0x6084, 0x20a2, + 0x53a6, 0x7007, 0x0001, 0x7974, 0xa184, 0xff00, 0x0040, 0x1d81, + 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0078, + 0x1d84, 0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, 0xa006, + 0xa211, 0x7d10, 0xd5c4, 0x0040, 0x1d91, 0x7b84, 0xa319, 0x7c80, + 0xa421, 0x7008, 0xd0fc, 0x0040, 0x1d91, 0x7003, 0x0001, 0x7007, + 0x0006, 0x711a, 0x721e, 0x7d10, 0xd5c4, 0x0040, 0x1da1, 0x7322, + 0x7426, 0xa084, 0x01e0, 0x007c, 0x7848, 0xa065, 0x0040, 0x1dac, + 0x2c04, 0x784a, 0x2063, 0x0000, 0x007c, 0x0f7e, 0x2079, 0x4d00, + 0x7848, 0x2062, 0x2c00, 0xa005, 0x00c0, 0x1db8, 0x1078, 0x290c, + 0x784a, 0x0f7f, 0x007c, 0x2011, 0x9700, 0x7a4a, 0x7bc4, 0x8319, + 0x0040, 0x1dc8, 0xa280, 0x0032, 0x2012, 0x2010, 0x0078, 0x1dbf, + 0x2013, 0x0000, 0x007c, 0x017e, 0x027e, 0xd7fc, 0x00c0, 0x1dd4, + 0x2011, 0x52c0, 0x0078, 0x1dd6, 0x2011, 0x72c0, 0xa784, 0x0f00, + 0x800b, 0xa784, 0x001f, 0x0040, 0x1de1, 0x8003, 0x8003, 0x8003, + 0x8003, 0xa105, 0xa268, 0x027f, 0x017f, 0x007c, 0x1078, 0x1dcb, + 0x2900, 0x682a, 0x2a00, 0x682e, 0x6808, 0xa084, 0xf9ef, 0xa80d, + 0x690a, 0x0e7e, 0xd7fc, 0x00c0, 0x1dfb, 0x2009, 0x4d53, 0x2071, + 0x4d40, 0x0078, 0x1dff, 0x2009, 0x4d93, 0x2071, 0x4d80, 0x210c, + 0x6804, 0xa005, 0x0040, 0x1e0f, 0xa116, 0x00c0, 0x1e0f, 0x2060, + 0x6000, 0x6806, 0x017e, 0x200b, 0x0000, 0x0078, 0x1e12, 0x2009, + 0x0000, 0x017e, 0x6804, 0xa065, 0x0040, 0x1e27, 0x6000, 0x6806, + 0x1078, 0x1e42, 0x1078, 0x2004, 0x6810, 0x7908, 0x8109, 0x790a, + 0x8001, 0x6812, 0x00c0, 0x1e12, 0x7910, 0xc1a5, 0x7912, 0x017f, + 0x6902, 0x6906, 0x2d00, 0x2060, 0x1078, 0x2a6d, 0x0e7f, 0x007c, + 0xa065, 0x0040, 0x1e41, 0x2008, 0x609c, 0xa005, 0x0040, 0x1e3e, + 0x2062, 0x609f, 0x0000, 0xa065, 0x0078, 0x1e34, 0x7848, 0x794a, + 0x2062, 0x007c, 0x6007, 0x0103, 0x608f, 0x0000, 0x20a9, 0x001c, + 0xac80, 0x0005, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x6828, 0x601a, + 0x682c, 0x6022, 0x007c, 0x0e7e, 0xd7fc, 0x00c0, 0x1e5d, 0x2071, + 0x4d40, 0x2031, 0x4dc0, 0x0078, 0x1e61, 0x2071, 0x4d80, 0x2031, + 0x4fc0, 0x7050, 0xa08c, 0x0200, 0x00c0, 0x1e6b, 0xa608, 0x2d0a, + 0x8000, 0x7052, 0xa006, 0x0e7f, 0x007c, 0x0f7e, 0xd7fc, 0x00c0, + 0x1e75, 0x2079, 0x4d40, 0x0078, 0x1e77, 0x2079, 0x4d80, 0x1078, + 0x1dcb, 0x2091, 0x8000, 0x6804, 0x780a, 0xa065, 0x0040, 0x1ecb, + 0x0078, 0x1e89, 0x2c00, 0x780a, 0x2060, 0x6000, 0xa065, 0x0040, + 0x1ecb, 0x6010, 0xa306, 0x00c0, 0x1e82, 0x600c, 0xa206, 0x00c0, + 0x1e82, 0x2c28, 0x784c, 0xac06, 0x00c0, 0x1e98, 0x0078, 0x1ec8, + 0x6804, 0xac06, 0x00c0, 0x1ea6, 0x6000, 0x2060, 0x6806, 0xa005, + 0x00c0, 0x1ea6, 0x6803, 0x0000, 0x0078, 0x1eb0, 0x6400, 0x7808, + 0x2060, 0x6402, 0xa486, 0x0000, 0x00c0, 0x1eb0, 0x2c00, 0x6802, + 0x2560, 0x0f7f, 0x1078, 0x1e42, 0x0f7e, 0x601b, 0x0005, 0x6023, + 0x0020, 0x0f7f, 0x1078, 0x2004, 0x0f7e, 0x7908, 0x8109, 0x790a, + 0x6810, 0x8001, 0x6812, 0x00c0, 0x1ec8, 0x7810, 0xc0a5, 0x7812, + 0x2001, 0xffff, 0xa005, 0x0f7f, 0x007c, 0x077e, 0x2700, 0x2039, + 0x0000, 0xd0fc, 0x0040, 0x1ed5, 0xc7fd, 0x2041, 0x0021, 0x2049, + 0x0004, 0x2051, 0x0008, 0x2091, 0x8000, 0x1078, 0x1de6, 0x8738, + 0xa784, 0x001f, 0x00c0, 0x1edd, 0xa7bc, 0xff00, 0x873f, 0x8738, + 0x873f, 0xa784, 0x0f00, 0x00c0, 0x1edd, 0x2091, 0x8001, 0x077f, + 0x007c, 0x786c, 0x2009, 0x9574, 0x210c, 0xa10d, 0x0040, 0x1efb, + 0xa065, 0x0078, 0x2356, 0x2061, 0x0000, 0x6018, 0xd084, 0x00c0, + 0x1f1b, 0x7810, 0xd08c, 0x0040, 0x1f0c, 0xc08c, 0x7812, 0xc7fc, + 0x2069, 0x4d40, 0x0078, 0x1f11, 0xc08d, 0x7812, 0x2069, 0x4d80, + 0xc7fd, 0x2091, 0x8000, 0x681c, 0x681f, 0x0000, 0x2091, 0x8001, + 0xa005, 0x00c0, 0x1f1c, 0x007c, 0xa08c, 0xfff0, 0x0040, 0x1f22, + 0x1078, 0x290c, 0x0079, 0x1f24, 0x1f34, 0x1f37, 0x1f3d, 0x1f41, + 0x1f35, 0x1f45, 0x1f35, 0x1f35, 0x1f35, 0x1f4b, 0x1f7c, 0x1f80, + 0x1f86, 0x1f9b, 0x1f35, 0x1f35, 0x007c, 0x1078, 0x290c, 0x1078, + 0x1ecd, 0x2001, 0x8001, 0x0078, 0x1fa7, 0x2001, 0x8003, 0x0078, + 0x1fa7, 0x2001, 0x8004, 0x0078, 0x1fa7, 0x1078, 0x1ecd, 0x2001, + 0x8006, 0x0078, 0x1fa7, 0x2091, 0x8000, 0x077e, 0xd7fc, 0x00c0, + 0x1f57, 0x2069, 0x4d40, 0x2039, 0x0009, 0x0078, 0x1f5b, 0x2069, + 0x4d80, 0x2039, 0x0009, 0x6800, 0xa086, 0x0000, 0x0040, 0x1f65, + 0x007f, 0x6f1e, 0x2091, 0x8001, 0x007c, 0x6874, 0x077f, 0xa0bc, + 0xff00, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0010, 0x1078, + 0x1de6, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1f6f, 0x2091, 0x8001, + 0x2001, 0x800a, 0x0078, 0x1fa7, 0x2001, 0x800c, 0x0078, 0x1fa7, + 0x1078, 0x1ecd, 0x2001, 0x800d, 0x0078, 0x1fa7, 0x7814, 0xd0e4, + 0x00c0, 0x1f99, 0xd0ec, 0x0040, 0x1f93, 0xd7fc, 0x0040, 0x1f93, + 0x78e4, 0x0078, 0x1f94, 0x78e0, 0x70c6, 0x2001, 0x800e, 0x0078, + 0x1fa7, 0x0078, 0x1f35, 0xd7fc, 0x0040, 0x1fa1, 0x78ec, 0x0078, + 0x1fa2, 0x78e8, 0x70c6, 0x2001, 0x000d, 0x0078, 0x1fa7, 0x70c2, + 0xd7fc, 0x00c0, 0x1faf, 0x70db, 0x0000, 0x0078, 0x1fb1, 0x70db, + 0x0001, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x4080, 0x007c, + 0xac80, 0x0001, 0x81ff, 0x0040, 0x1fe3, 0x2099, 0x0030, 0x20a0, + 0x700c, 0xa084, 0x03ff, 0x0040, 0x1fc5, 0x7018, 0x007e, 0x701c, + 0x007e, 0x7020, 0x007e, 0x7024, 0x007e, 0x7112, 0x81ac, 0x721a, + 0x731e, 0x7422, 0x7526, 0x7003, 0x0001, 0x7007, 0x0001, 0x7008, + 0x800b, 0x00c8, 0x1fd7, 0x7007, 0x0002, 0xa08c, 0x01e0, 0x00c0, + 0x1fe3, 0x53a5, 0xa006, 0x7003, 0x0000, 0x7007, 0x0004, 0x007f, + 0x7026, 0x007f, 0x7022, 0x007f, 0x701e, 0x007f, 0x701a, 0x007c, + 0x2011, 0x0020, 0x2009, 0x0010, 0x6b0a, 0x6c0e, 0x6803, 0xfd00, + 0x6807, 0x0018, 0x6a1a, 0x2d00, 0xa0e8, 0x0008, 0xa290, 0x0004, + 0x8109, 0x00c0, 0x1ff4, 0x007c, 0x6004, 0x6086, 0x2c08, 0x2063, + 0x0000, 0x7868, 0xa005, 0x796a, 0x0040, 0x2011, 0x2c02, 0x0078, + 0x2012, 0x796e, 0x007c, 0x0c7e, 0x2061, 0x4d00, 0x6887, 0x0103, + 0x2d08, 0x206b, 0x0000, 0x6068, 0xa005, 0x616a, 0x0040, 0x2023, + 0x2d02, 0x0078, 0x2024, 0x616e, 0x0c7f, 0x007c, 0x2091, 0x8000, + 0x2c04, 0x786e, 0xa005, 0x00c0, 0x202e, 0x786a, 0x2091, 0x8001, + 0x609c, 0xa005, 0x0040, 0x2047, 0x0c7e, 0x2060, 0x2008, 0x609c, + 0xa005, 0x0040, 0x2043, 0x2062, 0x609f, 0x0000, 0xa065, 0x609c, + 0xa005, 0x00c0, 0x203b, 0x7848, 0x794a, 0x2062, 0x0c7f, 0x7848, + 0x2062, 0x609f, 0x0000, 0xac85, 0x0000, 0x00c0, 0x2051, 0x1078, + 0x290c, 0x784a, 0x007c, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, + 0x818e, 0x00c8, 0x205c, 0xa200, 0x00f0, 0x2057, 0x8086, 0x818e, + 0x007c, 0x157e, 0x20a9, 0x0010, 0xa005, 0x0040, 0x2082, 0xa11a, + 0x00c8, 0x2082, 0x8213, 0x818d, 0x0048, 0x2075, 0xa11a, 0x00c8, + 0x2076, 0x00f0, 0x206a, 0x0078, 0x207a, 0xa11a, 0x2308, 0x8210, + 0x00f0, 0x206a, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f, + 0x157f, 0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078, 0x207e, + 0x7d74, 0x70d0, 0xa506, 0x0040, 0x216e, 0x7810, 0x2050, 0x7800, + 0xd08c, 0x0040, 0x20aa, 0xdaec, 0x0040, 0x20aa, 0x0e7e, 0x2091, + 0x8000, 0x2071, 0x0020, 0x7004, 0xa005, 0x00c0, 0x20a7, 0x7008, + 0x0e7f, 0xa086, 0x0008, 0x0040, 0x20aa, 0x0078, 0x216e, 0x0e7f, + 0x0078, 0x216e, 0x1078, 0x1da4, 0x0040, 0x216e, 0xa046, 0x7970, + 0x2500, 0x8000, 0xa112, 0x2009, 0x0040, 0x00c8, 0x20b9, 0x0078, + 0x20c0, 0x72d0, 0xa206, 0x0040, 0x20c0, 0x8840, 0x2009, 0x0080, + 0x0c7e, 0x7112, 0x7007, 0x0001, 0x2099, 0x0030, 0x20a9, 0x0020, + 0xac80, 0x0001, 0x20a0, 0x2061, 0x0000, 0x88ff, 0x0040, 0x20d2, + 0x1078, 0x1da4, 0x7008, 0xd0fc, 0x0040, 0x20d2, 0x7007, 0x0002, + 0x2091, 0x8001, 0xa08c, 0x01e0, 0x00c0, 0x2109, 0x53a5, 0x8cff, + 0x00c0, 0x20e7, 0x88ff, 0x0040, 0x2158, 0x0078, 0x20f1, 0x2c00, + 0x788e, 0x20a9, 0x0020, 0xac80, 0x0001, 0x20a0, 0x53a5, 0x0078, + 0x2158, 0xa046, 0x7218, 0x731c, 0xdac4, 0x0040, 0x20f9, 0x7420, + 0x7524, 0xa292, 0x0040, 0xa39b, 0x0000, 0xa4a3, 0x0000, 0xa5ab, + 0x0000, 0x721a, 0x731e, 0xdac4, 0x0040, 0x2109, 0x7422, 0x7526, + 0xa006, 0x7007, 0x0004, 0x0040, 0x2158, 0x8cff, 0x0040, 0x2112, + 0x1078, 0x1dad, 0x0c7f, 0x1078, 0x1dad, 0xa046, 0x7888, 0x8000, + 0x788a, 0xa086, 0x0002, 0x0040, 0x2138, 0x7a7c, 0x7b78, 0xdac4, + 0x0040, 0x2124, 0x7c84, 0x7d80, 0x7974, 0x8107, 0x8004, 0x8004, + 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x721a, + 0x731e, 0xdac4, 0x0040, 0x216e, 0x7422, 0x7526, 0x0078, 0x216e, + 0x6014, 0xd0fc, 0x00c0, 0x2140, 0x2069, 0x4d40, 0x0078, 0x2142, + 0x2069, 0x4d80, 0x2091, 0x8000, 0x681f, 0x0002, 0x88ff, 0x0040, + 0x214e, 0xa046, 0x788c, 0x2060, 0x0078, 0x2138, 0x788b, 0x0000, + 0x78ac, 0xa085, 0x0003, 0x78ae, 0x2091, 0x8001, 0x0078, 0x216e, + 0x0c7f, 0x788b, 0x0000, 0x1078, 0x2307, 0x6004, 0xa084, 0x000f, + 0x1078, 0x216f, 0x88ff, 0x0040, 0x216c, 0x788c, 0x2060, 0x6004, + 0xa084, 0x000f, 0x1078, 0x216f, 0x0078, 0x2088, 0x007c, 0x0079, + 0x2171, 0x2181, 0x219f, 0x21bd, 0x2181, 0x21ce, 0x2192, 0x2181, + 0x2181, 0x2181, 0x219d, 0x21bb, 0x2181, 0x2181, 0x2181, 0x2181, + 0x2181, 0x2039, 0x0400, 0x78bc, 0xa705, 0x78be, 0x6008, 0xa705, + 0x600a, 0x1078, 0x2211, 0x609c, 0x78ba, 0x609f, 0x0000, 0x1078, + 0x22f1, 0x007c, 0x78bc, 0xd0c4, 0x0040, 0x2198, 0x0078, 0x2181, + 0x601c, 0xc0bd, 0x601e, 0x0078, 0x21a5, 0x1078, 0x2339, 0x78bc, + 0xd0c4, 0x0040, 0x21a5, 0x0078, 0x2181, 0x78bf, 0x0000, 0x6004, + 0x8007, 0xa084, 0x00ff, 0x78b2, 0x8001, 0x0040, 0x21b8, 0x1078, + 0x2211, 0x0040, 0x21b8, 0x78bc, 0xc0c5, 0x78be, 0x0078, 0x21ba, + 0x0078, 0x2230, 0x007c, 0x1078, 0x2335, 0x78bc, 0xa08c, 0x0e00, + 0x00c0, 0x21c5, 0xd0c4, 0x00c0, 0x21c7, 0x0078, 0x2181, 0x1078, + 0x2211, 0x00c0, 0x21cd, 0x0078, 0x2230, 0x007c, 0x78bc, 0xd0c4, + 0x0040, 0x21d4, 0x0078, 0x2181, 0x78bf, 0x0000, 0x6714, 0x2011, + 0x0001, 0x22a8, 0x6018, 0xa084, 0x00ff, 0xa005, 0x0040, 0x21f4, + 0xa7bc, 0xff00, 0x20a9, 0x0020, 0xa08e, 0x0001, 0x0040, 0x21f4, + 0xa7bc, 0x8000, 0x2011, 0x0002, 0x20a9, 0x0100, 0xa08e, 0x0002, + 0x0040, 0x21f4, 0x0078, 0x220e, 0x1078, 0x1dcb, 0x2d00, 0x2091, + 0x8000, 0x682b, 0x0000, 0x682f, 0x0000, 0x6808, 0xa084, 0xffde, + 0x680a, 0xade8, 0x0010, 0x2091, 0x8001, 0x00f0, 0x21f7, 0x8211, + 0x0040, 0x220e, 0x20a9, 0x0100, 0x0078, 0x21f7, 0x1078, 0x1dad, + 0x007c, 0x609f, 0x0000, 0x78b4, 0xa06d, 0x2c00, 0x78b6, 0x00c0, + 0x221c, 0x78ba, 0x0078, 0x2224, 0x689e, 0x2d00, 0x6002, 0x78b8, + 0xad06, 0x00c0, 0x2224, 0x6002, 0x78b0, 0x8001, 0x78b2, 0x00c0, + 0x222f, 0x78bc, 0xc0c4, 0x78be, 0x78b8, 0x2060, 0xa006, 0x007c, + 0x0e7e, 0xa02e, 0x2530, 0x7dba, 0x7db6, 0x65ae, 0x65b2, 0x601c, + 0x60a2, 0x2048, 0xa984, 0xe1ff, 0x601e, 0xa984, 0x0060, 0x0040, + 0x2243, 0x1078, 0x45a7, 0x6596, 0x65a6, 0x669a, 0x66aa, 0x6714, + 0x2071, 0x4d80, 0xd7fc, 0x00c0, 0x224f, 0x2071, 0x4d40, 0xa784, + 0x0f00, 0x800b, 0xa784, 0x001f, 0x0040, 0x225a, 0x8003, 0x8003, + 0x8003, 0x8003, 0xa105, 0x71c4, 0xa168, 0x2700, 0x8007, 0xa084, + 0x000f, 0x8003, 0x8003, 0x8003, 0x71c8, 0xa100, 0x60c2, 0x2091, + 0x8000, 0x7810, 0xd0f4, 0x00c0, 0x2274, 0x6e08, 0xd684, 0x0040, + 0x228a, 0xd9fc, 0x00c0, 0x228a, 0x2091, 0x8001, 0x1078, 0x1e42, + 0x2091, 0x8000, 0x1078, 0x2004, 0x2091, 0x8001, 0x7814, 0xd0e4, + 0x00c0, 0x22ef, 0x7810, 0xd0f4, 0x0040, 0x22ef, 0x601b, 0x0021, + 0x0078, 0x22ef, 0x6024, 0xa096, 0x0001, 0x00c0, 0x2291, 0x8000, + 0x6026, 0x6a10, 0x6814, 0xa202, 0x0048, 0x22a4, 0x0040, 0x22a4, + 0x2091, 0x8001, 0x2039, 0x0200, 0x609c, 0x78ba, 0x609f, 0x0000, + 0x1078, 0x22f1, 0x0078, 0x22ef, 0x2c08, 0xd9fc, 0x0040, 0x22cc, + 0x6800, 0xa065, 0x0040, 0x22cc, 0x6a04, 0x7000, 0xa084, 0x0002, + 0x0040, 0x22c2, 0x704c, 0xa206, 0x00c0, 0x22c2, 0x6b04, 0x2160, + 0x2304, 0x6002, 0xa005, 0x00c0, 0x22be, 0x6902, 0x2260, 0x6102, + 0x0078, 0x22d8, 0x2d00, 0x2060, 0x1078, 0x2a6d, 0x6e08, 0x2160, + 0x6202, 0x6906, 0x0078, 0x22d8, 0x6800, 0x6902, 0xa065, 0x0040, + 0x22d4, 0x6102, 0x0078, 0x22d5, 0x6906, 0x2160, 0x6003, 0x0000, + 0x2160, 0xd9fc, 0x0040, 0x22df, 0xa6b4, 0xfffc, 0x6e0a, 0x6810, + 0x7d08, 0x8528, 0x7d0a, 0x8000, 0x6812, 0x2091, 0x8001, 0xd6b4, + 0x0040, 0x22ef, 0xa6b6, 0x0040, 0x6e0a, 0x1078, 0x1e53, 0x0e7f, + 0x007c, 0x6008, 0xa705, 0x600a, 0x2091, 0x8000, 0x1078, 0x2004, + 0x2091, 0x8001, 0x78b8, 0xa065, 0x0040, 0x2304, 0x609c, 0x78ba, + 0x609f, 0x0000, 0x0078, 0x22f1, 0x78b6, 0x78ba, 0x007c, 0x7970, + 0x7874, 0x2818, 0xd384, 0x0040, 0x2311, 0x8000, 0xa112, 0x0048, + 0x2316, 0x8000, 0xa112, 0x00c8, 0x2326, 0xc384, 0x7a7c, 0x721a, + 0x7a78, 0x721e, 0xdac4, 0x0040, 0x2321, 0x7a84, 0x7222, 0x7a80, + 0x7226, 0xa006, 0xd384, 0x0040, 0x2326, 0x8000, 0x7876, 0x70d2, + 0x781c, 0xa005, 0x0040, 0x2334, 0x8001, 0x781e, 0x00c0, 0x2334, + 0x0068, 0x2334, 0x2091, 0x4080, 0x007c, 0x2039, 0x234d, 0x0078, + 0x233b, 0x2039, 0x2353, 0x2704, 0xa005, 0x0040, 0x234c, 0xac00, + 0x2068, 0x6908, 0x6810, 0x6912, 0x680a, 0x690c, 0x6814, 0x6916, + 0x680e, 0x8738, 0x0078, 0x233b, 0x007c, 0x0003, 0x0009, 0x000f, + 0x0015, 0x001b, 0x0000, 0x0015, 0x001b, 0x0000, 0x2041, 0x0000, + 0x780c, 0x0079, 0x235b, 0x252d, 0x2500, 0x235f, 0x23d8, 0x2039, + 0x9574, 0x2734, 0x7d10, 0x0078, 0x237f, 0x6084, 0xa086, 0x0103, + 0x00c0, 0x23c1, 0x6114, 0x6018, 0xa105, 0x0040, 0x2374, 0x86ff, + 0x00c0, 0x2390, 0x0078, 0x23c1, 0x8603, 0xa080, 0x9555, 0x620c, + 0x2202, 0x8000, 0x6210, 0x2202, 0x1078, 0x2026, 0x8630, 0xa68e, + 0x000f, 0x0040, 0x244c, 0x786c, 0xa065, 0x00c0, 0x2365, 0x7808, + 0xa602, 0x00c8, 0x2390, 0xd5ac, 0x00c0, 0x2390, 0x263a, 0x007c, + 0xa682, 0x0003, 0x00c8, 0x244c, 0x2091, 0x8000, 0x2069, 0x0000, + 0x6818, 0xd084, 0x00c0, 0x23bc, 0x2011, 0x9555, 0x2204, 0x70c6, + 0x8210, 0x2204, 0x70ca, 0xd684, 0x00c0, 0x23ac, 0x8210, 0x2204, + 0x70da, 0x8210, 0x2204, 0x70de, 0xa685, 0x8020, 0x70c2, 0x681b, + 0x0001, 0x2091, 0x4080, 0x7810, 0xa084, 0xffcf, 0x7812, 0x2091, + 0x8001, 0x203b, 0x0000, 0x007c, 0x7810, 0xc0ad, 0x7812, 0x0078, + 0x244c, 0x263a, 0x1078, 0x2537, 0x00c0, 0x255a, 0x786c, 0xa065, + 0x00c0, 0x2365, 0x2091, 0x8000, 0x7810, 0xa084, 0xffcf, 0x86ff, + 0x0040, 0x23d3, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0078, 0x255a, + 0x2039, 0x9574, 0x2734, 0x7d10, 0x0078, 0x23f4, 0x6084, 0xa086, + 0x0103, 0x00c0, 0x2435, 0x6114, 0x6018, 0xa105, 0x0040, 0x23ed, + 0x86ff, 0x00c0, 0x2405, 0x0078, 0x2435, 0xa680, 0x9555, 0x620c, + 0x2202, 0x1078, 0x2026, 0x8630, 0xa68e, 0x001e, 0x0040, 0x244c, + 0x786c, 0xa065, 0x00c0, 0x23de, 0x7808, 0xa602, 0x00c8, 0x2405, + 0xd5ac, 0x00c0, 0x2405, 0x263a, 0x007c, 0xa682, 0x0006, 0x00c8, + 0x244c, 0x2091, 0x8000, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0, + 0x2430, 0x2011, 0x9555, 0x2009, 0x954e, 0x26a8, 0x211c, 0x2204, + 0x201a, 0x8108, 0x8210, 0x00f0, 0x2416, 0xa685, 0x8030, 0x70c2, 0x681b, 0x0001, 0x2091, 0x4080, 0x7810, 0xa084, 0xffcf, 0x7812, - 0x2091, 0x8001, 0xa006, 0x2009, 0x9275, 0x200a, 0x203a, 0x007c, - 0x7810, 0xc0ad, 0x7812, 0x0078, 0x2454, 0x263a, 0x1078, 0x253f, - 0x00c0, 0x254e, 0x786c, 0xa065, 0x00c0, 0x23eb, 0x2091, 0x8000, - 0x7810, 0xa084, 0xffcf, 0x86ff, 0x0040, 0x244f, 0xc0ad, 0x7812, - 0x2091, 0x8001, 0x0078, 0x254e, 0x2091, 0x8000, 0x7007, 0x0004, - 0x7994, 0x70d4, 0xa102, 0x0048, 0x2465, 0x0040, 0x246f, 0x7b90, - 0xa302, 0x00c0, 0x246f, 0x0078, 0x2468, 0x8002, 0x00c0, 0x246f, + 0x2091, 0x8001, 0xa006, 0x2009, 0x9575, 0x200a, 0x203a, 0x007c, + 0x7810, 0xc0ad, 0x7812, 0x0078, 0x244c, 0x263a, 0x1078, 0x2537, + 0x00c0, 0x255a, 0x786c, 0xa065, 0x00c0, 0x23de, 0x2091, 0x8000, + 0x7810, 0xa084, 0xffcf, 0x86ff, 0x0040, 0x2447, 0xc0ad, 0x7812, + 0x2091, 0x8001, 0x0078, 0x255a, 0x2091, 0x8000, 0x7007, 0x0004, + 0x7994, 0x70d4, 0xa102, 0x0048, 0x245d, 0x0040, 0x2467, 0x7b90, + 0xa302, 0x00c0, 0x2467, 0x0078, 0x2460, 0x8002, 0x00c0, 0x2467, 0x263a, 0x7810, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x007c, 0xa184, - 0xff00, 0x0040, 0x247c, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, - 0x8007, 0xa100, 0x0078, 0x247f, 0x8107, 0x8004, 0x8004, 0x7a9c, + 0xff00, 0x0040, 0x2474, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, + 0x8007, 0xa100, 0x0078, 0x2477, 0x8107, 0x8004, 0x8004, 0x7a9c, 0xa210, 0x721a, 0x7a98, 0xa006, 0xa211, 0x721e, 0xd4c4, 0x0040, - 0x248f, 0x7aa4, 0xa211, 0x7222, 0x7aa0, 0xa211, 0x7226, 0x20a1, - 0x0030, 0x7003, 0x0000, 0x2009, 0x9254, 0x260a, 0x8109, 0x2198, - 0x2104, 0xd084, 0x0040, 0x249d, 0x8633, 0xa6b0, 0x0002, 0x26a8, + 0x2487, 0x7aa4, 0xa211, 0x7222, 0x7aa0, 0xa211, 0x7226, 0x20a1, + 0x0030, 0x7003, 0x0000, 0x2009, 0x9554, 0x260a, 0x8109, 0x2198, + 0x2104, 0xd084, 0x0040, 0x2495, 0x8633, 0xa6b0, 0x0002, 0x26a8, 0x53a6, 0x8603, 0x7012, 0x7007, 0x0001, 0x7990, 0x7894, 0x8000, - 0xa10a, 0x00c8, 0x24ac, 0xa006, 0x2028, 0x7974, 0xa184, 0xff00, - 0x0040, 0x24bb, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, - 0xa100, 0x0078, 0x24be, 0x8107, 0x8004, 0x8004, 0x797c, 0xa108, - 0x7a78, 0xa006, 0xa211, 0xd4c4, 0x0040, 0x24ca, 0x7b84, 0xa319, - 0x7c80, 0xa421, 0x7008, 0xd0fc, 0x0040, 0x24ca, 0xa084, 0x01e0, - 0x0040, 0x24ef, 0x7d10, 0x2031, 0x9254, 0x2634, 0x78a8, 0x8000, - 0x78aa, 0xd08c, 0x00c0, 0x24e4, 0x7007, 0x0006, 0x7004, 0xd094, - 0x00c0, 0x24de, 0x0078, 0x2456, 0x2069, 0x4a47, 0x206b, 0x0003, - 0x78ac, 0xa085, 0x0300, 0x78ae, 0xa006, 0x0078, 0x24f8, 0x2030, + 0xa10a, 0x00c8, 0x24a4, 0xa006, 0x2028, 0x7974, 0xa184, 0xff00, + 0x0040, 0x24b3, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, + 0xa100, 0x0078, 0x24b6, 0x8107, 0x8004, 0x8004, 0x797c, 0xa108, + 0x7a78, 0xa006, 0xa211, 0xd4c4, 0x0040, 0x24c2, 0x7b84, 0xa319, + 0x7c80, 0xa421, 0x7008, 0xd0fc, 0x0040, 0x24c2, 0xa084, 0x01e0, + 0x0040, 0x24e7, 0x7d10, 0x2031, 0x9554, 0x2634, 0x78a8, 0x8000, + 0x78aa, 0xd08c, 0x00c0, 0x24dc, 0x7007, 0x0006, 0x7004, 0xd094, + 0x00c0, 0x24d6, 0x0078, 0x244e, 0x2069, 0x4d47, 0x206b, 0x0003, + 0x78ac, 0xa085, 0x0300, 0x78ae, 0xa006, 0x0078, 0x24f0, 0x2030, 0x75d6, 0x2091, 0x4080, 0x7d96, 0x7d10, 0xa5ac, 0xffcf, 0x7d12, 0x2091, 0x8001, 0x78aa, 0x7007, 0x0006, 0x263a, 0x7003, 0x0001, - 0x711a, 0x721e, 0xd5c4, 0x0040, 0x2507, 0x7322, 0x7426, 0x007c, - 0x6084, 0xa086, 0x0103, 0x00c0, 0x252b, 0x6114, 0x6018, 0xa105, - 0x00c0, 0x252b, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0, 0x252b, + 0x711a, 0x721e, 0xd5c4, 0x0040, 0x24ff, 0x7322, 0x7426, 0x007c, + 0x6084, 0xa086, 0x0103, 0x00c0, 0x2523, 0x6114, 0x6018, 0xa105, + 0x00c0, 0x2523, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0, 0x2523, 0x600c, 0x70c6, 0x6010, 0x70ca, 0x70c3, 0x8020, 0x681b, 0x0001, - 0x2091, 0x4080, 0x1078, 0x203d, 0x0068, 0x252a, 0x786c, 0xa065, - 0x00c0, 0x2508, 0x007c, 0x1078, 0x253f, 0x00c0, 0x254e, 0x786c, - 0xa065, 0x00c0, 0x2508, 0x0078, 0x254e, 0x1078, 0x253f, 0x00c0, - 0x254e, 0x786c, 0xa065, 0x00c0, 0x2535, 0x0078, 0x254e, 0x1078, - 0x2554, 0x00c0, 0x2546, 0xa085, 0x0001, 0x007c, 0x1078, 0x2563, - 0x00c0, 0x254c, 0x2041, 0x0001, 0x7d10, 0x007c, 0x88ff, 0x0040, - 0x2553, 0x2091, 0x4080, 0x007c, 0x7b90, 0x7994, 0x70d4, 0xa102, - 0x00c0, 0x255d, 0xa385, 0x0000, 0x007c, 0x0048, 0x2561, 0xa302, - 0x007c, 0x8002, 0x007c, 0x7810, 0xd0ec, 0x0040, 0x257b, 0x0e7e, - 0x2091, 0x8000, 0x2071, 0x0020, 0x7004, 0xa005, 0x00c0, 0x2578, - 0x7008, 0x0e7f, 0xa086, 0x0008, 0x0040, 0x257b, 0x0078, 0x25cc, - 0x0e7f, 0x0078, 0x25cc, 0xa184, 0xff00, 0x0040, 0x2588, 0x810f, - 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0078, 0x258b, - 0x8107, 0x8004, 0x8004, 0x7a9c, 0x7b98, 0x7ca4, 0x7da0, 0xa210, - 0xa006, 0xa319, 0xa421, 0xa529, 0x2009, 0x0018, 0x6028, 0xa005, - 0x0040, 0x259c, 0x2009, 0x0040, 0x1078, 0x1d92, 0x0040, 0x25be, - 0x78a8, 0x8000, 0x78aa, 0xd08c, 0x00c0, 0x25cc, 0x6014, 0xd0fc, - 0x00c0, 0x25ae, 0x2069, 0x4a40, 0x0078, 0x25b0, 0x2069, 0x4a80, - 0x2091, 0x8000, 0x681f, 0x0003, 0x78ab, 0x0000, 0x78ac, 0xa085, - 0x0300, 0x78ae, 0x2091, 0x8001, 0x0078, 0x25cc, 0x78ab, 0x0000, - 0x1078, 0x203d, 0x7990, 0x7894, 0x8000, 0xa10a, 0x00c8, 0x25c9, - 0xa006, 0x7896, 0x70d6, 0xa006, 0x2071, 0x0010, 0x2091, 0x8001, - 0x007c, 0x2138, 0xd7fc, 0x00c0, 0x25d9, 0x2009, 0x4a59, 0x0078, - 0x25db, 0x2009, 0x4a99, 0x2091, 0x8000, 0x200a, 0x0f7e, 0xd7fc, - 0x00c0, 0x25f2, 0x2009, 0x4a40, 0x2001, 0x4a04, 0x2004, 0xd0ec, - 0x0040, 0x25ee, 0x2079, 0x0100, 0x0078, 0x25f6, 0x2079, 0x0200, - 0x0078, 0x25f6, 0x2009, 0x4a80, 0x2079, 0x0100, 0x2104, 0xa086, - 0x0000, 0x00c0, 0x260f, 0xd7fc, 0x00c0, 0x2602, 0x2009, 0x4a45, - 0x0078, 0x2604, 0x2009, 0x4a85, 0x2104, 0xa005, 0x00c0, 0x260f, - 0x7830, 0xa084, 0x00c0, 0x00c0, 0x260f, 0x781b, 0x0045, 0x0f7f, - 0x007c, 0x2009, 0x0002, 0x2069, 0x4a00, 0x6810, 0xd0ec, 0x00c0, - 0x2672, 0x2071, 0x4a80, 0x2079, 0x0100, 0x2021, 0x4cbf, 0x784b, - 0x000f, 0x2019, 0x4205, 0xd184, 0x0040, 0x2632, 0x6810, 0xd0ec, - 0x0040, 0x262e, 0x20a1, 0x012b, 0x0078, 0x2634, 0x20a1, 0x022b, - 0x0078, 0x2634, 0x20a1, 0x012b, 0x2304, 0xa005, 0x0040, 0x2641, - 0x789a, 0x8318, 0x23ac, 0x8318, 0x2398, 0x53a6, 0x3318, 0x0078, - 0x2634, 0x789b, 0x0020, 0x20a9, 0x0010, 0x78af, 0x0000, 0x78af, - 0x8020, 0x00f0, 0x2645, 0x7003, 0x0000, 0x017e, 0xd18c, 0x2009, - 0x0000, 0x0040, 0x2654, 0xc1bd, 0x1078, 0x283d, 0x017f, 0x7020, - 0xa084, 0x000f, 0x007e, 0x6814, 0xd0e4, 0x007f, 0x00c0, 0x2664, - 0xa085, 0x6340, 0x0078, 0x2666, 0xa085, 0x62c0, 0x7806, 0x780f, - 0x9200, 0x7843, 0x00d8, 0x7853, 0x0080, 0x780b, 0x0008, 0x7456, - 0x7053, 0x0000, 0x8109, 0x0040, 0x2685, 0x2071, 0x4a40, 0x6810, - 0xd0ec, 0x0040, 0x267f, 0x2079, 0x0100, 0x0078, 0x2681, 0x2079, - 0x0200, 0x2021, 0x4abf, 0x0078, 0x261f, 0x007c, 0x017e, 0xd1bc, - 0x00c0, 0x269a, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, - 0x0040, 0x2696, 0x2011, 0x0101, 0x0078, 0x269c, 0x2011, 0x0201, - 0x0078, 0x269c, 0x2011, 0x0101, 0xa18c, 0x000f, 0x2204, 0xa084, - 0xfff0, 0xa105, 0x2012, 0x017f, 0x1078, 0x283d, 0x007c, 0xd3fc, - 0x00c0, 0x26ba, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, - 0x0040, 0x26b6, 0x2011, 0x0101, 0x0078, 0x26bc, 0x2011, 0x0201, - 0x0078, 0x26bc, 0x2011, 0x0101, 0x20a9, 0x0009, 0x810b, 0x00f0, - 0x26be, 0xa18c, 0x0e00, 0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012, - 0x007c, 0x2019, 0x0002, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x0040, - 0x26d6, 0x8319, 0x2009, 0x0101, 0x0078, 0x26d8, 0x2009, 0x0101, - 0x20a9, 0x0005, 0x8213, 0x00f0, 0x26da, 0xa294, 0x00e0, 0x2104, - 0xa084, 0xff1f, 0xa205, 0x200a, 0x8319, 0x0040, 0x26eb, 0x2009, - 0x0201, 0x0078, 0x26d8, 0x007c, 0xd3fc, 0x00c0, 0x26ff, 0x007e, - 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x26fb, 0x2011, - 0x0101, 0x0078, 0x2701, 0x2011, 0x0201, 0x0078, 0x2701, 0x2011, - 0x0101, 0x20a9, 0x000c, 0x810b, 0x00f0, 0x2703, 0xa18c, 0xf000, - 0x2204, 0xa084, 0x0fff, 0xa105, 0x2012, 0x007c, 0xd3fc, 0x00c0, - 0x2721, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040, - 0x271d, 0x2011, 0x0102, 0x0078, 0x2723, 0x2011, 0x0202, 0x0078, - 0x2723, 0x2011, 0x0102, 0x2204, 0xa084, 0xffcf, 0xa105, 0x2012, - 0x007c, 0x0c7e, 0xd1bc, 0x00c0, 0x273d, 0x007e, 0x2001, 0x4a04, - 0x2004, 0xd0ec, 0x007f, 0x0040, 0x2739, 0x2061, 0x0100, 0x0078, - 0x273f, 0x2061, 0x0200, 0x0078, 0x273f, 0x2061, 0x0100, 0xc1bc, - 0x8103, 0x8003, 0xa080, 0x0020, 0x609a, 0x62ac, 0x63ac, 0x0c7f, - 0x007c, 0x0c7e, 0xd1bc, 0x00c0, 0x275d, 0x007e, 0x2001, 0x4a04, - 0x2004, 0xd0ec, 0x007f, 0x0040, 0x2759, 0x2061, 0x0100, 0x0078, - 0x275f, 0x2061, 0x0200, 0x0078, 0x275f, 0x2061, 0x0100, 0xc1bc, - 0x8103, 0x8003, 0xa080, 0x0022, 0x609a, 0x60a4, 0xa084, 0xffdf, - 0x60ae, 0x0c7f, 0x007c, 0x0c7e, 0xd1bc, 0x00c0, 0x277f, 0x007e, - 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x277b, 0x2061, - 0x0100, 0x0078, 0x2781, 0x2061, 0x0200, 0x0078, 0x2781, 0x2061, - 0x0100, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0022, 0x609a, 0x60a4, - 0xa085, 0x0020, 0x60ae, 0x0c7f, 0x007c, 0x0c7e, 0xd1bc, 0x00c0, - 0x27a1, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040, - 0x279d, 0x2061, 0x0100, 0x0078, 0x27a3, 0x2061, 0x0200, 0x0078, - 0x27a3, 0x2061, 0x0100, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0020, - 0x609a, 0x60a4, 0xa28c, 0x0020, 0x0040, 0x27b1, 0xc2ac, 0xa39d, - 0x4000, 0xc3fc, 0xd3b4, 0x00c0, 0x27b6, 0xc3fd, 0x62ae, 0x2010, - 0x60a4, 0x63ae, 0x2018, 0x0c7f, 0x007c, 0x2091, 0x8000, 0x0c7e, - 0x0e7e, 0x6818, 0xa005, 0x0040, 0x281b, 0xd1fc, 0x0040, 0x27cc, - 0x2061, 0x91d0, 0x0078, 0x27ce, 0x2061, 0x90c0, 0x1078, 0x2823, - 0x0040, 0x2801, 0x20a9, 0x0101, 0xd1fc, 0x0040, 0x27db, 0x2061, - 0x90d0, 0x0078, 0x27dd, 0x2061, 0x8fc0, 0x0c7e, 0x1078, 0x2823, - 0x0040, 0x27e8, 0x0c7f, 0x8c60, 0x00f0, 0x27dd, 0x0078, 0x281b, - 0x007f, 0xd1fc, 0x0040, 0x27f2, 0xa082, 0x90d0, 0x2071, 0x4a80, - 0x0078, 0x27f6, 0xa082, 0x8fc0, 0x2071, 0x4a40, 0x707a, 0x7176, - 0x2001, 0x0004, 0x7066, 0x7083, 0x000f, 0x1078, 0x25d1, 0x0078, - 0x2817, 0xd1fc, 0x00c0, 0x2808, 0x2071, 0x4a40, 0x0078, 0x280a, - 0x2071, 0x4a80, 0x6020, 0xc0dd, 0x6022, 0x7176, 0x2c00, 0x707e, - 0x2001, 0x0006, 0x7066, 0x7083, 0x000f, 0x1078, 0x25d1, 0x2001, - 0x0000, 0x0078, 0x281d, 0x2001, 0x0001, 0x2091, 0x8001, 0xa005, - 0x0e7f, 0x0c7f, 0x007c, 0x2c04, 0xa005, 0x0040, 0x283a, 0x2060, - 0x6010, 0xa306, 0x00c0, 0x2837, 0x600c, 0xa206, 0x00c0, 0x2837, - 0x6014, 0xa106, 0x00c0, 0x2837, 0xa006, 0x0078, 0x283c, 0x6000, - 0x0078, 0x2824, 0xa085, 0x0001, 0x007c, 0x0f7e, 0x0e7e, 0x017e, - 0xd1bc, 0x00c0, 0x2855, 0x2079, 0x4a40, 0x007e, 0x2001, 0x4a04, - 0x2004, 0xd0ec, 0x007f, 0x0040, 0x2851, 0x2071, 0x0100, 0x0078, - 0x2859, 0x2071, 0x0200, 0x0078, 0x2859, 0x2079, 0x4a80, 0x2071, - 0x0100, 0x7920, 0xa18c, 0x000f, 0x70ec, 0xd0c4, 0x00c0, 0x2863, - 0x017f, 0x0078, 0x287e, 0x810b, 0x810b, 0x810b, 0x810b, 0x007f, - 0xd0bc, 0x00c0, 0x287b, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, - 0x007f, 0x0040, 0x2877, 0xa18d, 0x0f00, 0x0078, 0x287d, 0xa18d, - 0x0f00, 0x0078, 0x287d, 0xa18d, 0x0800, 0x2104, 0x0e7f, 0x0f7f, - 0x007c, 0x0e7e, 0x2001, 0x4a01, 0x2004, 0xd0ac, 0x00c0, 0x28ea, - 0x68e4, 0xd0ac, 0x0040, 0x28ea, 0xa084, 0x0006, 0x00c0, 0x28ea, - 0x6014, 0xd0fc, 0x00c0, 0x2898, 0x2071, 0x4ec0, 0x0078, 0x289a, - 0x2071, 0x4f40, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, - 0xae70, 0x7004, 0xa084, 0x000a, 0x00c0, 0x28ea, 0x7108, 0xa194, - 0xff00, 0x0040, 0x28ea, 0xa18c, 0x00ff, 0x2001, 0x000a, 0xa106, - 0x0040, 0x28cd, 0x2001, 0x000c, 0xa106, 0x0040, 0x28d1, 0x2001, - 0x0012, 0xa106, 0x0040, 0x28d5, 0x2001, 0x0014, 0xa106, 0x0040, - 0x28d9, 0x2001, 0x0019, 0xa106, 0x0040, 0x28dd, 0x2001, 0x0032, - 0xa106, 0x0040, 0x28e1, 0x0078, 0x28e5, 0x2009, 0x000c, 0x0078, - 0x28e7, 0x2009, 0x0012, 0x0078, 0x28e7, 0x2009, 0x0014, 0x0078, - 0x28e7, 0x2009, 0x0019, 0x0078, 0x28e7, 0x2009, 0x0020, 0x0078, - 0x28e7, 0x2009, 0x003f, 0x0078, 0x28e7, 0x2011, 0x0000, 0x2100, - 0xa205, 0x700a, 0x0e7f, 0x007c, 0x0068, 0x28ec, 0x2091, 0x8000, - 0x2071, 0x0000, 0x007e, 0x7018, 0xd084, 0x00c0, 0x28f3, 0x007f, + 0x2091, 0x4080, 0x1078, 0x2026, 0x0068, 0x2522, 0x786c, 0xa065, + 0x00c0, 0x2500, 0x007c, 0x1078, 0x2537, 0x00c0, 0x255a, 0x786c, + 0xa065, 0x00c0, 0x2500, 0x0078, 0x255a, 0x1078, 0x2537, 0x00c0, + 0x255a, 0x786c, 0xa065, 0x00c0, 0x252d, 0x0078, 0x255a, 0x6084, + 0xa086, 0x0103, 0x00c0, 0x254b, 0x6018, 0xc0fc, 0x601a, 0xa086, + 0x0004, 0x00c0, 0x254b, 0x7804, 0xd0a4, 0x0040, 0x254b, 0x1078, + 0x2026, 0xa006, 0x007c, 0x1078, 0x2560, 0x00c0, 0x2552, 0xa085, + 0x0001, 0x007c, 0x1078, 0x256f, 0x00c0, 0x2558, 0x2041, 0x0001, + 0x7d10, 0x007c, 0x88ff, 0x0040, 0x255f, 0x2091, 0x4080, 0x007c, + 0x7b90, 0x7994, 0x70d4, 0xa102, 0x00c0, 0x2569, 0xa385, 0x0000, + 0x007c, 0x0048, 0x256d, 0xa302, 0x007c, 0x8002, 0x007c, 0x7810, + 0xd0ec, 0x0040, 0x2587, 0x0e7e, 0x2091, 0x8000, 0x2071, 0x0020, + 0x7004, 0xa005, 0x00c0, 0x2584, 0x7008, 0x0e7f, 0xa086, 0x0008, + 0x0040, 0x2587, 0x0078, 0x25d8, 0x0e7f, 0x0078, 0x25d8, 0xa184, + 0xff00, 0x0040, 0x2594, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, + 0x8007, 0xa100, 0x0078, 0x2597, 0x8107, 0x8004, 0x8004, 0x7a9c, + 0x7b98, 0x7ca4, 0x7da0, 0xa210, 0xa006, 0xa319, 0xa421, 0xa529, + 0x2009, 0x0018, 0x6028, 0xa005, 0x0040, 0x25a8, 0x2009, 0x0040, + 0x1078, 0x1d5b, 0x0040, 0x25ca, 0x78a8, 0x8000, 0x78aa, 0xd08c, + 0x00c0, 0x25d8, 0x6014, 0xd0fc, 0x00c0, 0x25ba, 0x2069, 0x4d40, + 0x0078, 0x25bc, 0x2069, 0x4d80, 0x2091, 0x8000, 0x681f, 0x0003, + 0x78ab, 0x0000, 0x78ac, 0xa085, 0x0300, 0x78ae, 0x2091, 0x8001, + 0x0078, 0x25d8, 0x78ab, 0x0000, 0x1078, 0x2026, 0x7990, 0x7894, + 0x8000, 0xa10a, 0x00c8, 0x25d5, 0xa006, 0x7896, 0x70d6, 0xa006, + 0x2071, 0x0010, 0x2091, 0x8001, 0x007c, 0x2138, 0xd7fc, 0x00c0, + 0x25e5, 0x2009, 0x4d59, 0x0078, 0x25e7, 0x2009, 0x4d99, 0x2091, + 0x8000, 0x200a, 0x0f7e, 0xd7fc, 0x00c0, 0x25fe, 0x2009, 0x4d40, + 0x2001, 0x4d04, 0x2004, 0xd0ec, 0x0040, 0x25fa, 0x2079, 0x0100, + 0x0078, 0x2602, 0x2079, 0x0200, 0x0078, 0x2602, 0x2009, 0x4d80, + 0x2079, 0x0100, 0x2104, 0xa086, 0x0000, 0x00c0, 0x261b, 0xd7fc, + 0x00c0, 0x260e, 0x2009, 0x4d45, 0x0078, 0x2610, 0x2009, 0x4d85, + 0x2104, 0xa005, 0x00c0, 0x261b, 0x7830, 0xa084, 0x00c0, 0x00c0, + 0x261b, 0x781b, 0x0045, 0x0f7f, 0x007c, 0x2009, 0x0002, 0x2069, + 0x4d00, 0x6810, 0xd0ec, 0x00c0, 0x267e, 0x2071, 0x4d80, 0x2079, + 0x0100, 0x2021, 0x4fbf, 0x784b, 0x000f, 0x2019, 0x43d2, 0xd184, + 0x0040, 0x263e, 0x6810, 0xd0ec, 0x0040, 0x263a, 0x20a1, 0x012b, + 0x0078, 0x2640, 0x20a1, 0x022b, 0x0078, 0x2640, 0x20a1, 0x012b, + 0x2304, 0xa005, 0x0040, 0x264d, 0x789a, 0x8318, 0x23ac, 0x8318, + 0x2398, 0x53a6, 0x3318, 0x0078, 0x2640, 0x789b, 0x0020, 0x20a9, + 0x0010, 0x78af, 0x0000, 0x78af, 0x8020, 0x00f0, 0x2651, 0x7003, + 0x0000, 0x017e, 0xd18c, 0x2009, 0x0000, 0x0040, 0x2660, 0xc1bd, + 0x1078, 0x2849, 0x017f, 0x7020, 0xa084, 0x000f, 0x007e, 0x6814, + 0xd0e4, 0x007f, 0x00c0, 0x2670, 0xa085, 0x6340, 0x0078, 0x2672, + 0xa085, 0x62c0, 0x7806, 0x780f, 0x9200, 0x7843, 0x00d8, 0x7853, + 0x0080, 0x780b, 0x0008, 0x7456, 0x7053, 0x0000, 0x8109, 0x0040, + 0x2691, 0x2071, 0x4d40, 0x6810, 0xd0ec, 0x0040, 0x268b, 0x2079, + 0x0100, 0x0078, 0x268d, 0x2079, 0x0200, 0x2021, 0x4dbf, 0x0078, + 0x262b, 0x007c, 0x017e, 0xd1bc, 0x00c0, 0x26a6, 0x007e, 0x2001, + 0x4d04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x26a2, 0x2011, 0x0101, + 0x0078, 0x26a8, 0x2011, 0x0201, 0x0078, 0x26a8, 0x2011, 0x0101, + 0xa18c, 0x000f, 0x2204, 0xa084, 0xfff0, 0xa105, 0x2012, 0x017f, + 0x1078, 0x2849, 0x007c, 0xd3fc, 0x00c0, 0x26c6, 0x007e, 0x2001, + 0x4d04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x26c2, 0x2011, 0x0101, + 0x0078, 0x26c8, 0x2011, 0x0201, 0x0078, 0x26c8, 0x2011, 0x0101, + 0x20a9, 0x0009, 0x810b, 0x00f0, 0x26ca, 0xa18c, 0x0e00, 0x2204, + 0xa084, 0xf1ff, 0xa105, 0x2012, 0x007c, 0x2019, 0x0002, 0x2001, + 0x4d04, 0x2004, 0xd0ec, 0x0040, 0x26e2, 0x8319, 0x2009, 0x0101, + 0x0078, 0x26e4, 0x2009, 0x0101, 0x20a9, 0x0005, 0x8213, 0x00f0, + 0x26e6, 0xa294, 0x00e0, 0x2104, 0xa084, 0xff1f, 0xa205, 0x200a, + 0x8319, 0x0040, 0x26f7, 0x2009, 0x0201, 0x0078, 0x26e4, 0x007c, + 0xd3fc, 0x00c0, 0x270b, 0x007e, 0x2001, 0x4d04, 0x2004, 0xd0ec, + 0x007f, 0x0040, 0x2707, 0x2011, 0x0101, 0x0078, 0x270d, 0x2011, + 0x0201, 0x0078, 0x270d, 0x2011, 0x0101, 0x20a9, 0x000c, 0x810b, + 0x00f0, 0x270f, 0xa18c, 0xf000, 0x2204, 0xa084, 0x0fff, 0xa105, + 0x2012, 0x007c, 0xd3fc, 0x00c0, 0x272d, 0x007e, 0x2001, 0x4d04, + 0x2004, 0xd0ec, 0x007f, 0x0040, 0x2729, 0x2011, 0x0102, 0x0078, + 0x272f, 0x2011, 0x0202, 0x0078, 0x272f, 0x2011, 0x0102, 0x2204, + 0xa084, 0xffcf, 0xa105, 0x2012, 0x007c, 0x0c7e, 0xd1bc, 0x00c0, + 0x2749, 0x007e, 0x2001, 0x4d04, 0x2004, 0xd0ec, 0x007f, 0x0040, + 0x2745, 0x2061, 0x0100, 0x0078, 0x274b, 0x2061, 0x0200, 0x0078, + 0x274b, 0x2061, 0x0100, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0020, + 0x609a, 0x62ac, 0x63ac, 0x0c7f, 0x007c, 0x0c7e, 0xd1bc, 0x00c0, + 0x2769, 0x007e, 0x2001, 0x4d04, 0x2004, 0xd0ec, 0x007f, 0x0040, + 0x2765, 0x2061, 0x0100, 0x0078, 0x276b, 0x2061, 0x0200, 0x0078, + 0x276b, 0x2061, 0x0100, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0022, + 0x609a, 0x60a4, 0xa084, 0xffdf, 0x60ae, 0x0c7f, 0x007c, 0x0c7e, + 0xd1bc, 0x00c0, 0x278b, 0x007e, 0x2001, 0x4d04, 0x2004, 0xd0ec, + 0x007f, 0x0040, 0x2787, 0x2061, 0x0100, 0x0078, 0x278d, 0x2061, + 0x0200, 0x0078, 0x278d, 0x2061, 0x0100, 0xc1bc, 0x8103, 0x8003, + 0xa080, 0x0022, 0x609a, 0x60a4, 0xa085, 0x0020, 0x60ae, 0x0c7f, + 0x007c, 0x0c7e, 0xd1bc, 0x00c0, 0x27ad, 0x007e, 0x2001, 0x4d04, + 0x2004, 0xd0ec, 0x007f, 0x0040, 0x27a9, 0x2061, 0x0100, 0x0078, + 0x27af, 0x2061, 0x0200, 0x0078, 0x27af, 0x2061, 0x0100, 0xc1bc, + 0x8103, 0x8003, 0xa080, 0x0020, 0x609a, 0x60a4, 0xa28c, 0x0020, + 0x0040, 0x27bd, 0xc2ac, 0xa39d, 0x4000, 0xc3fc, 0xd3b4, 0x00c0, + 0x27c2, 0xc3fd, 0x62ae, 0x2010, 0x60a4, 0x63ae, 0x2018, 0x0c7f, + 0x007c, 0x2091, 0x8000, 0x0c7e, 0x0e7e, 0x6818, 0xa005, 0x0040, + 0x2827, 0xd1fc, 0x0040, 0x27d8, 0x2061, 0x94d0, 0x0078, 0x27da, + 0x2061, 0x93c0, 0x1078, 0x282f, 0x0040, 0x280d, 0x20a9, 0x0101, + 0xd1fc, 0x0040, 0x27e7, 0x2061, 0x93d0, 0x0078, 0x27e9, 0x2061, + 0x92c0, 0x0c7e, 0x1078, 0x282f, 0x0040, 0x27f4, 0x0c7f, 0x8c60, + 0x00f0, 0x27e9, 0x0078, 0x2827, 0x007f, 0xd1fc, 0x0040, 0x27fe, + 0xa082, 0x93d0, 0x2071, 0x4d80, 0x0078, 0x2802, 0xa082, 0x92c0, + 0x2071, 0x4d40, 0x707a, 0x7176, 0x2001, 0x0004, 0x7066, 0x7083, + 0x000f, 0x1078, 0x25dd, 0x0078, 0x2823, 0xd1fc, 0x00c0, 0x2814, + 0x2071, 0x4d40, 0x0078, 0x2816, 0x2071, 0x4d80, 0x6020, 0xc0dd, + 0x6022, 0x7176, 0x2c00, 0x707e, 0x2001, 0x0006, 0x7066, 0x7083, + 0x000f, 0x1078, 0x25dd, 0x2001, 0x0000, 0x0078, 0x2829, 0x2001, + 0x0001, 0x2091, 0x8001, 0xa005, 0x0e7f, 0x0c7f, 0x007c, 0x2c04, + 0xa005, 0x0040, 0x2846, 0x2060, 0x6010, 0xa306, 0x00c0, 0x2843, + 0x600c, 0xa206, 0x00c0, 0x2843, 0x6014, 0xa106, 0x00c0, 0x2843, + 0xa006, 0x0078, 0x2848, 0x6000, 0x0078, 0x2830, 0xa085, 0x0001, + 0x007c, 0x0f7e, 0x0e7e, 0x017e, 0xd1bc, 0x00c0, 0x2861, 0x2079, + 0x4d40, 0x007e, 0x2001, 0x4d04, 0x2004, 0xd0ec, 0x007f, 0x0040, + 0x285d, 0x2071, 0x0100, 0x0078, 0x2865, 0x2071, 0x0200, 0x0078, + 0x2865, 0x2079, 0x4d80, 0x2071, 0x0100, 0x7920, 0xa18c, 0x000f, + 0x70ec, 0xd0c4, 0x00c0, 0x286f, 0x017f, 0x0078, 0x288a, 0x810b, + 0x810b, 0x810b, 0x810b, 0x007f, 0xd0bc, 0x00c0, 0x2887, 0x007e, + 0x2001, 0x4d04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x2883, 0xa18d, + 0x0f00, 0x0078, 0x2889, 0xa18d, 0x0f00, 0x0078, 0x2889, 0xa18d, + 0x0800, 0x2104, 0x0e7f, 0x0f7f, 0x007c, 0x0e7e, 0x2001, 0x4d01, + 0x2004, 0xd0ac, 0x00c0, 0x290a, 0x68e4, 0xd0ac, 0x0040, 0x290a, + 0xa084, 0x0006, 0x00c0, 0x290a, 0x6014, 0xd0fc, 0x00c0, 0x28a4, + 0x2071, 0x51c0, 0x0078, 0x28a6, 0x2071, 0x5240, 0x8007, 0xa084, + 0x000f, 0x8003, 0x8003, 0x8003, 0xae70, 0x7004, 0xa084, 0x000a, + 0x00c0, 0x290a, 0x7108, 0xa194, 0xff00, 0x0040, 0x290a, 0xa18c, + 0x00ff, 0x2001, 0x000a, 0xa106, 0x0040, 0x28d9, 0x2001, 0x000c, + 0xa106, 0x0040, 0x28dd, 0x2001, 0x0012, 0xa106, 0x0040, 0x28e1, + 0x2001, 0x0014, 0xa106, 0x0040, 0x28e5, 0x2001, 0x0019, 0xa106, + 0x0040, 0x28e9, 0x2001, 0x0032, 0xa106, 0x0040, 0x28ed, 0x0078, + 0x28f1, 0x2009, 0x000c, 0x0078, 0x28f3, 0x2009, 0x0012, 0x0078, + 0x28f3, 0x2009, 0x0014, 0x0078, 0x28f3, 0x2009, 0x0019, 0x0078, + 0x28f3, 0x2009, 0x0020, 0x0078, 0x28f3, 0x2009, 0x003f, 0x0078, + 0x28f3, 0x2011, 0x0000, 0x2100, 0xa205, 0x700a, 0x2071, 0x4d00, + 0x7004, 0xd0bc, 0x0040, 0x290a, 0x6014, 0xd0fc, 0x00c0, 0x2905, + 0x70ea, 0x2071, 0x4d40, 0x0078, 0x2908, 0x70ee, 0x2071, 0x4d80, + 0x701f, 0x800f, 0x0e7f, 0x007c, 0x0068, 0x290c, 0x2091, 0x8000, + 0x2071, 0x0000, 0x007e, 0x7018, 0xd084, 0x00c0, 0x2913, 0x007f, 0x2071, 0x0010, 0x70ca, 0x007f, 0x70c6, 0x70c3, 0x8002, 0x70db, - 0x0809, 0x70df, 0x0000, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, - 0x4080, 0x0078, 0x2909, 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x78a0, + 0x080d, 0x70df, 0x0008, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, + 0x4080, 0x0078, 0x2929, 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x78a0, 0x708e, 0x7592, 0x7496, 0x769a, 0x779e, 0xa594, 0x003f, 0xd4f4, - 0x0040, 0x2920, 0xa784, 0x007d, 0x00c0, 0x417b, 0x1078, 0x28ec, - 0xa49c, 0x000f, 0xa382, 0x0004, 0x0050, 0x292b, 0xa3a6, 0x0007, - 0x00c0, 0x28ec, 0x2418, 0x8507, 0xa084, 0x000f, 0x0079, 0x2930, - 0x2f45, 0x3035, 0x3060, 0x32c1, 0x363b, 0x36a1, 0x3741, 0x37bd, - 0x38a1, 0x398a, 0x2943, 0x2940, 0x2d2a, 0x2e43, 0x360e, 0x2940, - 0x1078, 0x28ec, 0x007c, 0xa006, 0x0078, 0x294d, 0x7808, 0xc08d, + 0x0040, 0x2940, 0xa784, 0x007d, 0x00c0, 0x4348, 0x1078, 0x290c, + 0xa49c, 0x000f, 0xa382, 0x0004, 0x0050, 0x294b, 0xa3a6, 0x0007, + 0x00c0, 0x290c, 0x2418, 0x8507, 0xa084, 0x000f, 0x0079, 0x2950, + 0x2fc6, 0x30b5, 0x30e0, 0x3341, 0x372a, 0x379f, 0x3853, 0x38cf, + 0x39bd, 0x3aac, 0x2963, 0x2960, 0x2d99, 0x2eba, 0x36fb, 0x2960, + 0x1078, 0x290c, 0x007c, 0xa006, 0x0078, 0x296d, 0x7808, 0xc08d, 0x780a, 0xa006, 0x7002, 0x704e, 0x7046, 0x70d2, 0x7060, 0xa005, - 0x00c0, 0x2a64, 0x7064, 0xa084, 0x0007, 0x0079, 0x2957, 0x295f, - 0x29cf, 0x29d8, 0x29e3, 0x29ee, 0x2a4a, 0x29f9, 0x29cf, 0x7830, - 0xd0bc, 0x00c0, 0x2942, 0x71d4, 0xd1b4, 0x00c0, 0x29ac, 0x70a4, - 0xa086, 0x0001, 0x0040, 0x2942, 0x70b4, 0xa06d, 0x6800, 0xa065, - 0xa055, 0x789b, 0x0010, 0x6b0c, 0x7baa, 0x6808, 0xa045, 0x6d10, - 0x6804, 0xa06d, 0xa05d, 0xa886, 0x0001, 0x0040, 0x2982, 0x69bc, - 0x7daa, 0x79aa, 0x68c0, 0xa04d, 0x6e1c, 0x2001, 0x0010, 0x0078, - 0x2bbd, 0x7060, 0xa005, 0x00c0, 0x2942, 0x0c7e, 0x0d7e, 0x70b4, + 0x00c0, 0x2ad3, 0x7064, 0xa084, 0x0007, 0x0079, 0x2977, 0x297f, + 0x29f2, 0x29fb, 0x2a06, 0x2a11, 0x2ab9, 0x2a1c, 0x29f2, 0x7830, + 0xd0bc, 0x00c0, 0x2962, 0x71d4, 0xd1bc, 0x00c0, 0x2962, 0xd1b4, + 0x00c0, 0x29cf, 0x70a4, 0xa086, 0x0001, 0x0040, 0x2962, 0x70b4, 0xa06d, 0x6800, 0xa065, 0xa055, 0x789b, 0x0010, 0x6b0c, 0x7baa, 0x6808, 0xa045, 0x6d10, 0x6804, 0xa06d, 0xa05d, 0xa886, 0x0001, 0x0040, 0x29a5, 0x69bc, 0x7daa, 0x79aa, 0x68c0, 0xa04d, 0x6e1c, - 0x2001, 0x0020, 0x0078, 0x2bbd, 0x1078, 0x411c, 0x00c0, 0x2942, - 0x781b, 0x005b, 0x70bc, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, - 0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d, 0x780a, 0x68bc, - 0x7042, 0xc1b4, 0x71d6, 0x70b8, 0xa065, 0x68c0, 0x705a, 0x7003, - 0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x007c, 0x1078, - 0x411c, 0x00c0, 0x29d7, 0x781b, 0x0047, 0x7003, 0x0004, 0x007c, - 0x1078, 0x411c, 0x00c0, 0x29e2, 0x2011, 0x000c, 0x1078, 0x2a09, - 0x7003, 0x0004, 0x007c, 0x1078, 0x411c, 0x00c0, 0x29ed, 0x2011, - 0x0006, 0x1078, 0x2a09, 0x7003, 0x0004, 0x007c, 0x1078, 0x411c, - 0x00c0, 0x29f8, 0x2011, 0x000d, 0x1078, 0x2a09, 0x7003, 0x0004, - 0x007c, 0x1078, 0x411c, 0x00c0, 0x2a08, 0x2011, 0x0006, 0x1078, - 0x2a09, 0x707c, 0x707f, 0x0000, 0x2068, 0x704e, 0x7003, 0x0001, - 0x007c, 0x7174, 0xc1fc, 0x8107, 0x7882, 0x789b, 0x0010, 0xa286, - 0x000c, 0x00c0, 0x2a18, 0x7aaa, 0x2001, 0x0001, 0x0078, 0x2a2d, - 0xa18c, 0x001f, 0xa18d, 0x00c0, 0x79aa, 0xa286, 0x000d, 0x0040, - 0x2a26, 0x7aaa, 0x2001, 0x0002, 0x0078, 0x2a2d, 0x78ab, 0x0020, - 0x7178, 0x79aa, 0x7aaa, 0x2001, 0x0004, 0x789b, 0x0060, 0x78aa, - 0x785b, 0x0004, 0x781b, 0x0108, 0x1078, 0x4131, 0x7083, 0x000f, - 0x70d4, 0xd0b4, 0x0040, 0x2a49, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8, - 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, - 0x0c7f, 0x007c, 0x1078, 0x411c, 0x00c0, 0x2942, 0x707c, 0x2068, - 0x7774, 0x1078, 0x3fe1, 0x2c50, 0x1078, 0x41f0, 0x789b, 0x0010, - 0x6814, 0xa084, 0x001f, 0xc0bd, 0x78aa, 0x6e1c, 0x2041, 0x0001, - 0x2001, 0x0004, 0x0078, 0x2bc3, 0x1078, 0x411c, 0x00c0, 0x2942, - 0x789b, 0x0010, 0x7060, 0x2068, 0x6f14, 0x70d4, 0xd0b4, 0x0040, - 0x2a7e, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084, - 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f, 0x1078, 0x3fe1, - 0x2c50, 0x1078, 0x41f0, 0x6824, 0xa005, 0x0040, 0x2a8f, 0xa082, - 0x0006, 0x0048, 0x2a8d, 0x0078, 0x2a8f, 0x6827, 0x0005, 0x6814, - 0xa084, 0x001f, 0xc0bd, 0x78aa, 0x2031, 0x0020, 0x2041, 0x0001, - 0x2001, 0x0003, 0x0078, 0x2bc3, 0xc28d, 0x72d6, 0x72c0, 0xa200, - 0xa015, 0x7154, 0x8108, 0xa12a, 0x0048, 0x2aa7, 0x71c0, 0x2164, - 0x6504, 0x85ff, 0x00c0, 0x2abe, 0x7156, 0x8421, 0x00c0, 0x2aa2, - 0x70d4, 0xd08c, 0x0040, 0x2aba, 0x70d0, 0xa005, 0x00c0, 0x2aba, - 0x70d3, 0x000a, 0x007c, 0x2200, 0x0078, 0x2aac, 0x70d4, 0xc08c, - 0x70d6, 0x70d3, 0x0000, 0x603c, 0xa005, 0x00c0, 0x2abb, 0x6708, - 0xa784, 0x073f, 0x0040, 0x2aed, 0xd7d4, 0x00c0, 0x2abb, 0xa784, - 0x0021, 0x00c0, 0x2abb, 0xa784, 0x0002, 0x0040, 0x2ade, 0xa784, - 0x0004, 0x0040, 0x2abb, 0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0218, - 0x00c0, 0x2abb, 0xa784, 0x0100, 0x0040, 0x2aed, 0x6018, 0xa005, - 0x00c0, 0x2abb, 0xa7bc, 0xfeff, 0x670a, 0x2568, 0x6823, 0x0000, - 0x6e1c, 0xa684, 0x000e, 0x6318, 0x0040, 0x2afe, 0x601c, 0xa302, - 0x0048, 0x2b01, 0x0040, 0x2b01, 0x0078, 0x2abb, 0x83ff, 0x00c0, - 0x2abb, 0x2d58, 0x2c50, 0x7156, 0xd7bc, 0x00c0, 0x2b09, 0x7028, - 0x6022, 0xc7bc, 0x670a, 0x68c0, 0xa065, 0xa04d, 0x6100, 0x2a60, - 0x2041, 0x0001, 0x6b14, 0xa39c, 0x001f, 0xa39d, 0x00c0, 0xd1fc, - 0x0040, 0x2b1d, 0xd684, 0x0040, 0x2b1f, 0xa39c, 0xffbf, 0xd6a4, - 0x0040, 0x2b24, 0xa39d, 0x0020, 0xa684, 0x000e, 0x00c0, 0x2b6f, - 0xc7a5, 0x670a, 0x2c00, 0x68c6, 0x77a4, 0xa786, 0x0001, 0x00c0, - 0x2b43, 0x70d4, 0xd0b4, 0x00c0, 0x2b43, 0x7000, 0xa082, 0x0002, - 0x00c8, 0x2b43, 0x7830, 0xd0bc, 0x00c0, 0x2b43, 0x789b, 0x0010, - 0x7baa, 0x0078, 0x2bbb, 0x8739, 0x77a6, 0x2750, 0x77b0, 0xa7b0, - 0x0005, 0x70ac, 0xa606, 0x00c0, 0x2b4e, 0x76a8, 0x76b2, 0x2c3a, - 0x8738, 0x2d3a, 0x8738, 0x283a, 0x8738, 0x233a, 0x8738, 0x253a, - 0x7830, 0xd0bc, 0x0040, 0x2b66, 0x2091, 0x8000, 0x2091, 0x303d, - 0x70d4, 0xa084, 0x303d, 0x2091, 0x8000, 0x2090, 0xaad5, 0x0000, - 0x0040, 0x2b6e, 0x8421, 0x2200, 0x00c0, 0x2aa1, 0x007c, 0xd1dc, - 0x0040, 0x3be5, 0x2029, 0x0020, 0xd69c, 0x00c0, 0x2b7c, 0x8528, - 0xd68c, 0x00c0, 0x2b7c, 0x8528, 0x8840, 0x6f14, 0x610c, 0x8108, - 0xa18c, 0x00ff, 0x70cc, 0xa160, 0x2c64, 0x8cff, 0x0040, 0x2b9b, - 0x6014, 0xa706, 0x00c0, 0x2b84, 0x60b8, 0x8001, 0x60ba, 0x00c0, - 0x2b7f, 0x2a60, 0x6008, 0xa085, 0x0100, 0x600a, 0x2200, 0x8421, - 0x00c0, 0x2aa1, 0x007c, 0x2a60, 0x610e, 0x69be, 0x2c00, 0x68c6, - 0x8840, 0x6008, 0xc0d5, 0x600a, 0x77a4, 0xa786, 0x0001, 0x00c0, - 0x2b43, 0x70d4, 0xd0b4, 0x00c0, 0x2b43, 0x7000, 0xa082, 0x0002, - 0x00c8, 0x2b43, 0x7830, 0xd0bc, 0x00c0, 0x2b43, 0x789b, 0x0010, - 0x7baa, 0x7daa, 0x79aa, 0x2001, 0x0002, 0x007e, 0x6018, 0x8000, - 0x601a, 0x0078, 0x2bc4, 0x007e, 0x2960, 0x6104, 0x2a60, 0xa184, - 0x0018, 0x0040, 0x2be0, 0xa184, 0x0010, 0x0040, 0x2bd3, 0x1078, - 0x3df6, 0x00c0, 0x2c05, 0xa184, 0x0008, 0x0040, 0x2be0, 0x69a0, - 0xa184, 0x0600, 0x00c0, 0x2be0, 0x1078, 0x3cda, 0x0078, 0x2c05, - 0x69a0, 0xa184, 0x1e00, 0x0040, 0x2c10, 0xa184, 0x0800, 0x0040, - 0x2bf9, 0x0c7e, 0x2960, 0x6000, 0xa085, 0x2000, 0x6002, 0x6104, - 0xa18d, 0x0010, 0x6106, 0x0c7f, 0x1078, 0x3df6, 0x00c0, 0x2c05, - 0x69a0, 0xa184, 0x0200, 0x0040, 0x2c01, 0x1078, 0x3d3a, 0x0078, - 0x2c05, 0xa184, 0x0400, 0x00c0, 0x2bdc, 0x69a0, 0xa184, 0x1000, - 0x0040, 0x2c10, 0x6914, 0xa18c, 0xff00, 0x810f, 0x1078, 0x2749, - 0x027f, 0xa68c, 0x00e0, 0xa684, 0x0060, 0x0040, 0x2c1d, 0xa086, - 0x0060, 0x00c0, 0x2c1d, 0xa18d, 0x4000, 0xa18d, 0x0104, 0x69b6, - 0x789b, 0x0060, 0x2800, 0x78aa, 0x6818, 0xc0fd, 0x681a, 0xd6bc, - 0x0040, 0x2c38, 0xc0fc, 0x7087, 0x0000, 0xa08a, 0x000d, 0x0050, - 0x2c36, 0xa08a, 0x000c, 0x7186, 0x2001, 0x000c, 0x800c, 0x718a, - 0x78aa, 0x3518, 0x3340, 0x3428, 0x8000, 0x80ac, 0xaf80, 0x002b, - 0x20a0, 0x789b, 0x0000, 0xad80, 0x000b, 0x2098, 0x53a6, 0x23a8, - 0x2898, 0x25a0, 0xa286, 0x0020, 0x00c0, 0x2c70, 0x70d4, 0xc0b5, - 0x70d6, 0x2c00, 0x70ba, 0x2d00, 0x70be, 0x6814, 0xc0fc, 0x8007, - 0x7882, 0xa286, 0x0002, 0x0040, 0x2ca6, 0x70a4, 0x8000, 0x70a6, - 0x74b4, 0xa498, 0x0005, 0x70ac, 0xa306, 0x00c0, 0x2c68, 0x73a8, - 0x73b6, 0xa286, 0x0010, 0x0040, 0x2942, 0x0d7f, 0x0c7f, 0x007c, - 0x7000, 0xa005, 0x00c0, 0x2c4e, 0xa286, 0x0002, 0x00c0, 0x2cc0, - 0x1078, 0x411c, 0x00c0, 0x2c4e, 0x6814, 0xc0fc, 0x8007, 0x7882, - 0x2091, 0x8000, 0x781b, 0x005b, 0x68b4, 0x785a, 0x6894, 0x78d6, - 0x78de, 0x6898, 0x78d2, 0x78da, 0x2091, 0x8001, 0x7808, 0xc08d, - 0x780a, 0x127e, 0x0d7e, 0x0c7e, 0x70d4, 0xa084, 0x2700, 0x2090, - 0x0c7f, 0x0d7f, 0x127f, 0x2900, 0x705a, 0x68bc, 0x7042, 0x7003, - 0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x7830, 0xd0bc, - 0x0040, 0x2cb2, 0x2091, 0x303d, 0x70d4, 0xa084, 0x303d, 0x2091, - 0x8000, 0x2090, 0x70a4, 0xa005, 0x00c0, 0x2cb7, 0x007c, 0x8421, - 0x0040, 0x2cb6, 0x7250, 0x70c0, 0xa200, 0xa015, 0x0078, 0x2aa1, - 0xa286, 0x0010, 0x00c0, 0x2cf1, 0x1078, 0x411c, 0x00c0, 0x2c4e, - 0x6814, 0xc0fc, 0x8007, 0x7882, 0x781b, 0x005b, 0x68b4, 0x785a, - 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d, - 0x780a, 0x70a4, 0x8000, 0x70a6, 0x74b4, 0xa490, 0x0005, 0x70ac, - 0xa206, 0x00c0, 0x2ce4, 0x72a8, 0x72b6, 0x2900, 0x705a, 0x68bc, - 0x7042, 0x7003, 0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, - 0x007c, 0x6bb4, 0xa39d, 0x2000, 0x7b5a, 0x6814, 0xc0fc, 0x8007, - 0x7882, 0x6b94, 0x7bd6, 0x7bde, 0x6e98, 0x7ed2, 0x7eda, 0x781b, - 0x005b, 0x2900, 0x705a, 0x7202, 0x7808, 0xc08d, 0x780a, 0x2300, - 0xa605, 0x0040, 0x2d1c, 0x70d4, 0xa084, 0x2700, 0xa086, 0x2300, - 0x00c0, 0x2d16, 0x2009, 0x0000, 0x0078, 0x2d18, 0x2009, 0x0001, - 0xa284, 0x000f, 0x1079, 0x2d20, 0xad80, 0x0009, 0x7046, 0x007c, - 0x2d28, 0x45f7, 0x45f7, 0x45e4, 0x45f7, 0x2d28, 0x2d28, 0x2d28, - 0x1078, 0x28ec, 0x7808, 0xa084, 0xfffd, 0x780a, 0x0f7e, 0x2079, - 0x4a00, 0x78ac, 0x0f7f, 0xd084, 0x0040, 0x2d4e, 0x7064, 0xa086, - 0x0001, 0x00c0, 0x2d3e, 0x7066, 0x0078, 0x2e27, 0x7064, 0xa086, - 0x0005, 0x00c0, 0x2d4c, 0x707c, 0x2068, 0x681b, 0x0004, 0x6817, - 0x0000, 0x6820, 0xc09d, 0x6822, 0x7067, 0x0000, 0x70a7, 0x0000, - 0x70a8, 0x70b2, 0x70b6, 0x70d4, 0xd0b4, 0x0040, 0x2d64, 0xc0b4, + 0x2001, 0x0010, 0x0078, 0x2c2c, 0x7060, 0xa005, 0x00c0, 0x2962, + 0x0c7e, 0x0d7e, 0x70b4, 0xa06d, 0x6800, 0xa065, 0xa055, 0x789b, + 0x0010, 0x6b0c, 0x7baa, 0x6808, 0xa045, 0x6d10, 0x6804, 0xa06d, + 0xa05d, 0xa886, 0x0001, 0x0040, 0x29c8, 0x69bc, 0x7daa, 0x79aa, + 0x68c0, 0xa04d, 0x6e1c, 0x2001, 0x0020, 0x0078, 0x2c2c, 0x1078, + 0x42e9, 0x00c0, 0x2962, 0x781b, 0x005b, 0x70bc, 0xa06d, 0x68b4, + 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, + 0xc08d, 0x780a, 0x68bc, 0x7042, 0xc1b4, 0x71d6, 0x70b8, 0xa065, + 0x68c0, 0x705a, 0x7003, 0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, + 0x7046, 0x007c, 0x1078, 0x42e9, 0x00c0, 0x29fa, 0x781b, 0x0047, + 0x7003, 0x0004, 0x007c, 0x1078, 0x42e9, 0x00c0, 0x2a05, 0x2011, + 0x000c, 0x1078, 0x2a2c, 0x7003, 0x0004, 0x007c, 0x1078, 0x42e9, + 0x00c0, 0x2a10, 0x2011, 0x0006, 0x1078, 0x2a2c, 0x7003, 0x0004, + 0x007c, 0x1078, 0x42e9, 0x00c0, 0x2a1b, 0x2011, 0x000d, 0x1078, + 0x2a2c, 0x7003, 0x0004, 0x007c, 0x1078, 0x42e9, 0x00c0, 0x2a2b, + 0x2011, 0x0006, 0x1078, 0x2a2c, 0x707c, 0x707f, 0x0000, 0x2068, + 0x704e, 0x7003, 0x0001, 0x007c, 0x7174, 0xc1fc, 0x8107, 0x7882, + 0x789b, 0x0010, 0xa286, 0x000c, 0x00c0, 0x2a3b, 0x7aaa, 0x2001, + 0x0001, 0x0078, 0x2a50, 0xa18c, 0x001f, 0xa18d, 0x00c0, 0x79aa, + 0xa286, 0x000d, 0x0040, 0x2a49, 0x7aaa, 0x2001, 0x0002, 0x0078, + 0x2a50, 0x78ab, 0x0020, 0x7178, 0x79aa, 0x7aaa, 0x2001, 0x0004, + 0x789b, 0x0060, 0x78aa, 0x785b, 0x0004, 0x781b, 0x0110, 0x1078, + 0x42fe, 0x7083, 0x000f, 0x70d4, 0xd0b4, 0x0040, 0x2a6c, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, - 0x6018, 0x8001, 0x601a, 0x0c7f, 0x157e, 0x2011, 0x0004, 0x7164, - 0xa186, 0x0001, 0x0040, 0x2d7d, 0xa186, 0x0007, 0x00c0, 0x2d74, - 0x701f, 0x0005, 0x0078, 0x2d7d, 0x701f, 0x0001, 0x7067, 0x0000, - 0x70d4, 0xc0dd, 0x70d6, 0x0078, 0x2d7f, 0x7067, 0x0000, 0x2001, - 0x4a0a, 0x2004, 0xa084, 0x00ff, 0xa086, 0x0018, 0x0040, 0x2d8f, - 0x7018, 0x7016, 0xa005, 0x00c0, 0x2d8f, 0x70a7, 0x0001, 0x1078, - 0x4326, 0x20a9, 0x0010, 0x2039, 0x0000, 0x1078, 0x3edb, 0xa7b8, - 0x0100, 0x00f0, 0x2d95, 0x7000, 0x0079, 0x2d9e, 0x2dcd, 0x2db3, - 0x2db3, 0x2da8, 0x2dcd, 0x2dcd, 0x2dcd, 0x2da6, 0x1078, 0x28ec, - 0x7060, 0xa005, 0x0040, 0x2dcd, 0xad06, 0x00c0, 0x2db3, 0x6800, - 0x7062, 0x0078, 0x2dc5, 0x6820, 0xd084, 0x00c0, 0x2dc1, 0x6f14, - 0x1078, 0x3fe1, 0x6008, 0xc0d4, 0x600a, 0x1078, 0x3bb5, 0x0078, - 0x2dc5, 0x705c, 0x2060, 0x6800, 0x6002, 0x6a1a, 0x6817, 0x0000, - 0x6820, 0xc09d, 0x6822, 0x1078, 0x202a, 0xb284, 0x0400, 0x0040, - 0x2dd5, 0x2021, 0x91d0, 0x0078, 0x2dd7, 0x2021, 0x90c0, 0x1078, - 0x2e2c, 0xb284, 0x0400, 0x0040, 0x2de1, 0x2021, 0x4a98, 0x0078, - 0x2de3, 0x2021, 0x4a58, 0x1078, 0x2e2c, 0x20a9, 0x0101, 0xb284, - 0x0400, 0x0040, 0x2def, 0x2021, 0x90d0, 0x0078, 0x2df1, 0x2021, - 0x8fc0, 0x1078, 0x2e2c, 0x8420, 0x00f0, 0x2df1, 0xb284, 0x0300, - 0x0040, 0x2dfe, 0x2061, 0x4fc0, 0x0078, 0x2e00, 0x2061, 0x6fc0, - 0x2021, 0x0002, 0x20a9, 0x0100, 0x6110, 0x81ff, 0x0040, 0x2e1d, - 0x6018, 0x017e, 0x007e, 0x2011, 0x4a02, 0x220c, 0xa102, 0x2012, - 0x007f, 0x017f, 0xa102, 0x0050, 0x2e1d, 0x6012, 0x00c0, 0x2e1d, - 0x2011, 0x4a04, 0x2204, 0xc0a5, 0x2012, 0x601b, 0x0000, 0xace0, - 0x0010, 0x00f0, 0x2e04, 0x8421, 0x00c0, 0x2e02, 0x157f, 0x7003, - 0x0000, 0x704f, 0x0000, 0x007c, 0x047e, 0x2404, 0xa005, 0x0040, - 0x2e3f, 0x2068, 0x6800, 0x007e, 0x6a1a, 0x6817, 0x0000, 0x6820, - 0xc09d, 0x6822, 0x1078, 0x202a, 0x007f, 0x0078, 0x2e2e, 0x047f, - 0x2023, 0x0000, 0x007c, 0xa282, 0x0003, 0x0050, 0x2e49, 0x1078, - 0x28ec, 0x2300, 0x0079, 0x2e4c, 0x2e4f, 0x2eda, 0x2ef7, 0xa282, - 0x0002, 0x0040, 0x2e55, 0x1078, 0x28ec, 0x7064, 0x7067, 0x0000, - 0x7083, 0x0000, 0x0079, 0x2e5c, 0x2e64, 0x2e64, 0x2e66, 0x2ea6, - 0x3bf1, 0x2e64, 0x2ea6, 0x2e64, 0x1078, 0x28ec, 0x7774, 0x1078, - 0x3edb, 0x7774, 0xa7bc, 0x8f00, 0x1078, 0x3fe1, 0x6018, 0xa005, - 0x0040, 0x2e9d, 0xd7fc, 0x00c0, 0x2e79, 0x2021, 0x90c0, 0x0078, - 0x2e7b, 0x2021, 0x91d0, 0x2009, 0x0005, 0x2011, 0x0010, 0x1078, - 0x2f12, 0x0040, 0x2e9d, 0x157e, 0x20a9, 0x0101, 0xd7fc, 0x00c0, - 0x2e8d, 0x2021, 0x8fc0, 0x0078, 0x2e8f, 0x2021, 0x90d0, 0x047e, - 0x2009, 0x0005, 0x2011, 0x0010, 0x1078, 0x2f12, 0x047f, 0x0040, - 0x2e9c, 0x8420, 0x00f0, 0x2e8f, 0x157f, 0x8738, 0xa784, 0x001f, - 0x00c0, 0x2e6c, 0x0078, 0x2946, 0x0078, 0x2946, 0x7774, 0x1078, - 0x3fe1, 0x6018, 0xa005, 0x0040, 0x2ed8, 0xd7fc, 0x00c0, 0x2eb4, - 0x2021, 0x90c0, 0x0078, 0x2eb6, 0x2021, 0x91d0, 0x2009, 0x0005, - 0x2011, 0x0020, 0x1078, 0x2f12, 0x0040, 0x2ed8, 0x157e, 0x20a9, - 0x0101, 0xd7fc, 0x00c0, 0x2ec8, 0x2021, 0x8fc0, 0x0078, 0x2eca, - 0x2021, 0x90d0, 0x047e, 0x2009, 0x0005, 0x2011, 0x0020, 0x1078, - 0x2f12, 0x047f, 0x0040, 0x2ed7, 0x8420, 0x00f0, 0x2eca, 0x157f, - 0x0078, 0x2946, 0x2200, 0x0079, 0x2edd, 0x2ee0, 0x2ee2, 0x2ee2, - 0x1078, 0x28ec, 0x2009, 0x0012, 0x7064, 0xa086, 0x0002, 0x0040, - 0x2eeb, 0x2009, 0x000e, 0x6818, 0xd0fc, 0x0040, 0x2ef0, 0x691a, - 0x7067, 0x0000, 0x70d4, 0xc0dd, 0x70d6, 0x0078, 0x40c9, 0x2200, - 0x0079, 0x2efa, 0x2eff, 0x2ee2, 0x2efd, 0x1078, 0x28ec, 0x1078, - 0x4326, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3b7a, 0x1078, 0x3bd2, - 0x6008, 0xa084, 0xfbef, 0x600a, 0x1078, 0x3b6b, 0x0040, 0x3b7a, - 0x0078, 0x2946, 0x2404, 0xa005, 0x0040, 0x2f41, 0x2068, 0x2d04, - 0x007e, 0x6814, 0xa706, 0x0040, 0x2f21, 0x2d20, 0x007f, 0x0078, - 0x2f13, 0x007f, 0x2022, 0x691a, 0x6817, 0x0000, 0x6820, 0xa205, - 0x6822, 0x1078, 0x202a, 0x2021, 0x4a02, 0x241c, 0x8319, 0x2322, - 0x6010, 0x8001, 0x6012, 0x00c0, 0x2f3a, 0x2021, 0x4a04, 0x2404, - 0xc0a5, 0x2022, 0x6008, 0xa084, 0xf9ef, 0x600a, 0x1078, 0x3bd2, - 0x007c, 0xa085, 0x0001, 0x0078, 0x2f40, 0x2300, 0x0079, 0x2f48, - 0x2f4d, 0x2f4b, 0x2fce, 0x1078, 0x28ec, 0x78e4, 0xa005, 0x00d0, - 0x2f84, 0x3208, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, - 0x0040, 0x2f5e, 0xa18c, 0x0300, 0x0078, 0x2f60, 0xa18c, 0x0400, - 0x0040, 0x2f66, 0x0018, 0x2942, 0x0078, 0x2f68, 0x0028, 0x2942, - 0x2008, 0xa084, 0x0030, 0x00c0, 0x2f70, 0x781b, 0x005b, 0x007c, - 0x78ec, 0xa084, 0x0003, 0x0040, 0x2f6d, 0x2100, 0xa084, 0x0007, - 0x0079, 0x2f7a, 0x2fae, 0x2fb8, 0x2fa3, 0x2f82, 0x4111, 0x4111, - 0x2f82, 0x2fc3, 0x1078, 0x28ec, 0x7000, 0xa086, 0x0004, 0x00c0, - 0x2f9e, 0x7064, 0xa086, 0x0002, 0x00c0, 0x2f94, 0x2011, 0x0002, - 0x2019, 0x0000, 0x0078, 0x2e43, 0x7064, 0xa086, 0x0006, 0x0040, - 0x2f8e, 0x7064, 0xa086, 0x0004, 0x0040, 0x2f8e, 0x79e4, 0x2001, - 0x0003, 0x0078, 0x3304, 0x6818, 0xd0fc, 0x0040, 0x2fa9, 0x681b, - 0x001d, 0x1078, 0x3eae, 0x781b, 0x0061, 0x007c, 0x6818, 0xd0fc, - 0x0040, 0x2fb4, 0x681b, 0x001d, 0x1078, 0x3eae, 0x0078, 0x40ed, - 0x6818, 0xd0fc, 0x0040, 0x2fbe, 0x681b, 0x001d, 0x1078, 0x3eae, - 0x781b, 0x00ef, 0x007c, 0x6818, 0xd0fc, 0x0040, 0x2fc9, 0x681b, - 0x001d, 0x1078, 0x3eae, 0x781b, 0x00bf, 0x007c, 0xa584, 0x000f, - 0x00c0, 0x2feb, 0x7000, 0x0079, 0x2fd5, 0x2946, 0x2fdd, 0x2fdf, - 0x3b7a, 0x3b7a, 0x3b7a, 0x2fdd, 0x2fdd, 0x1078, 0x28ec, 0x1078, - 0x3bd2, 0x6008, 0xa084, 0xfbef, 0x600a, 0x1078, 0x3b6b, 0x0040, - 0x3b7a, 0x0078, 0x2946, 0x78e4, 0xa005, 0x00d0, 0x2f84, 0x3208, - 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x2ffc, - 0xa18c, 0x0300, 0x0078, 0x2ffe, 0xa18c, 0x0400, 0x0040, 0x3004, - 0x0018, 0x2f84, 0x0078, 0x3006, 0x0028, 0x2f84, 0x2008, 0xa084, - 0x0030, 0x00c0, 0x300e, 0x781b, 0x005b, 0x007c, 0x78ec, 0xa084, - 0x0003, 0x0040, 0x300b, 0x2100, 0xa184, 0x0007, 0x0079, 0x3018, - 0x3027, 0x302b, 0x3022, 0x3020, 0x4111, 0x4111, 0x3020, 0x410b, - 0x1078, 0x28ec, 0x1078, 0x3eb6, 0x781b, 0x0061, 0x007c, 0x1078, - 0x3eb6, 0x0078, 0x40ed, 0x1078, 0x3eb6, 0x781b, 0x00ef, 0x007c, - 0x1078, 0x3eb6, 0x781b, 0x00bf, 0x007c, 0x2300, 0x0079, 0x3038, - 0x303d, 0x303b, 0x303f, 0x1078, 0x28ec, 0x0078, 0x37bd, 0x681b, - 0x0016, 0x78a3, 0x0000, 0x79e4, 0xa184, 0x0030, 0x0040, 0x37bd, - 0x78ec, 0xa084, 0x0003, 0x0040, 0x37bd, 0xa184, 0x0100, 0x0040, - 0x3043, 0xa184, 0x0007, 0x0079, 0x3055, 0x305d, 0x302b, 0x2fa3, - 0x40c9, 0x4111, 0x4111, 0x40c9, 0x410b, 0x1078, 0x40d5, 0x007c, - 0xa282, 0x0005, 0x0050, 0x3066, 0x1078, 0x28ec, 0x2300, 0x0079, - 0x3069, 0x306c, 0x328b, 0x3296, 0x2200, 0x0079, 0x306f, 0x3089, - 0x3076, 0x3089, 0x3074, 0x326e, 0x1078, 0x28ec, 0x789b, 0x0018, - 0x78a8, 0xa084, 0x00ff, 0xa082, 0x0020, 0x0048, 0x3e9d, 0xa08a, - 0x0004, 0x00c8, 0x3e9d, 0x0079, 0x3085, 0x3e9d, 0x3e9d, 0x3e9d, - 0x3e47, 0x789b, 0x0018, 0x79a8, 0xa184, 0x0080, 0x0040, 0x309a, - 0x0078, 0x3e9d, 0x7000, 0xa005, 0x00c0, 0x3090, 0x2011, 0x0004, - 0x0078, 0x3998, 0xa184, 0x00ff, 0xa08a, 0x0010, 0x00c8, 0x3e9d, - 0x0079, 0x30a2, 0x30b4, 0x30b2, 0x30c9, 0x30cd, 0x318f, 0x3e9d, - 0x3e9d, 0x3191, 0x3e9d, 0x3e9d, 0x326a, 0x326a, 0x3e9d, 0x3e9d, - 0x3e9d, 0x326c, 0x1078, 0x28ec, 0xd6e4, 0x0040, 0x30bf, 0x2001, - 0x0300, 0x8000, 0x8000, 0x783a, 0x781b, 0x00ba, 0x007c, 0x6818, - 0xd0fc, 0x0040, 0x30c7, 0x681b, 0x001d, 0x0078, 0x30b7, 0x0078, - 0x40c9, 0x681b, 0x001d, 0x0078, 0x3ea7, 0x6920, 0x6922, 0xa684, - 0x1800, 0x00c0, 0x3121, 0x6820, 0xd084, 0x00c0, 0x3127, 0x6818, - 0xa086, 0x0008, 0x00c0, 0x30de, 0x681b, 0x0000, 0xd6d4, 0x0040, - 0x318c, 0xd6bc, 0x0040, 0x311e, 0x7087, 0x0000, 0x6818, 0xa084, - 0x003f, 0xa08a, 0x000d, 0x0050, 0x311e, 0xa08a, 0x000c, 0x7186, + 0x6018, 0x8001, 0x601a, 0x0c7f, 0x007c, 0x7014, 0xa005, 0x00c0, + 0x2a7b, 0x70d4, 0xd0b4, 0x0040, 0x2a7c, 0x70b8, 0xac06, 0x00c0, + 0x2a7c, 0x1078, 0x2a5b, 0x007c, 0x017e, 0x71a4, 0xa186, 0x0001, + 0x0040, 0x2aae, 0x0d7e, 0x027e, 0x2100, 0x2011, 0x0001, 0xa212, + 0x70b4, 0x2068, 0x6800, 0xac06, 0x0040, 0x2a95, 0x8211, 0x0040, + 0x2aac, 0x1078, 0x2ab0, 0x0078, 0x2a8a, 0x0c7e, 0x2100, 0x2011, + 0x0001, 0xa212, 0x70b4, 0x2068, 0x6800, 0x2060, 0x6008, 0xa084, + 0xfbef, 0x600a, 0x8211, 0x0040, 0x2aa9, 0x1078, 0x2ab0, 0x0078, + 0x2a9c, 0x70a7, 0x0001, 0x0c7f, 0x027f, 0x0d7f, 0x017f, 0x007c, + 0xade8, 0x0005, 0x70ac, 0xad06, 0x00c0, 0x2ab8, 0x70a8, 0x2068, + 0x007c, 0x1078, 0x42e9, 0x00c0, 0x2962, 0x707c, 0x2068, 0x7774, + 0x1078, 0x4187, 0x2c50, 0x1078, 0x43bd, 0x789b, 0x0010, 0x6814, + 0xa084, 0x001f, 0xc0bd, 0x78aa, 0x6e1c, 0x2041, 0x0001, 0x2001, + 0x0004, 0x0078, 0x2c32, 0x1078, 0x42e9, 0x00c0, 0x2962, 0x789b, + 0x0010, 0x7060, 0x2068, 0x6f14, 0x70d4, 0xd0b4, 0x0040, 0x2aed, + 0xc0b4, 0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, + 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f, 0x1078, 0x4187, 0x2c50, + 0x1078, 0x43bd, 0x6824, 0xa005, 0x0040, 0x2afe, 0xa082, 0x0006, + 0x0048, 0x2afc, 0x0078, 0x2afe, 0x6827, 0x0005, 0x6814, 0xa084, + 0x001f, 0xc0bd, 0x78aa, 0x2031, 0x0020, 0x2041, 0x0001, 0x2001, + 0x0003, 0x0078, 0x2c32, 0xc28d, 0x72d6, 0x72c0, 0xa200, 0xa015, + 0x7154, 0x8108, 0xa12a, 0x0048, 0x2b16, 0x71c0, 0x2164, 0x6504, + 0x85ff, 0x00c0, 0x2b2d, 0x7156, 0x8421, 0x00c0, 0x2b11, 0x70d4, + 0xd08c, 0x0040, 0x2b29, 0x70d0, 0xa005, 0x00c0, 0x2b29, 0x70d3, + 0x000a, 0x007c, 0x2200, 0x0078, 0x2b1b, 0x70d4, 0xc08c, 0x70d6, + 0x70d3, 0x0000, 0x6034, 0xa005, 0x00c0, 0x2b2a, 0x6708, 0xa784, + 0x073f, 0x0040, 0x2b5c, 0xd7d4, 0x00c0, 0x2b2a, 0xa784, 0x0021, + 0x00c0, 0x2b2a, 0xa784, 0x0002, 0x0040, 0x2b4d, 0xa784, 0x0004, + 0x0040, 0x2b2a, 0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0218, 0x00c0, + 0x2b2a, 0xa784, 0x0100, 0x0040, 0x2b5c, 0x6018, 0xa005, 0x00c0, + 0x2b2a, 0xa7bc, 0xfeff, 0x670a, 0x2568, 0x6823, 0x0000, 0x6e1c, + 0xa684, 0x000e, 0x6318, 0x0040, 0x2b6d, 0x601c, 0xa302, 0x0048, + 0x2b70, 0x0040, 0x2b70, 0x0078, 0x2b2a, 0x83ff, 0x00c0, 0x2b2a, + 0x2d58, 0x2c50, 0x7156, 0xd7bc, 0x00c0, 0x2b78, 0x7028, 0x6022, + 0xc7bc, 0x670a, 0x68c0, 0xa065, 0xa04d, 0x6100, 0x2a60, 0x2041, + 0x0001, 0x6b14, 0xa39c, 0x001f, 0xa39d, 0x00c0, 0xd1fc, 0x0040, + 0x2b8c, 0xd684, 0x0040, 0x2b8e, 0xa39c, 0xffbf, 0xd6a4, 0x0040, + 0x2b93, 0xa39d, 0x0020, 0xa684, 0x000e, 0x00c0, 0x2bde, 0xc7a5, + 0x670a, 0x2c00, 0x68c6, 0x77a4, 0xa786, 0x0001, 0x00c0, 0x2bb2, + 0x70d4, 0xd0b4, 0x00c0, 0x2bb2, 0x7000, 0xa082, 0x0002, 0x00c8, + 0x2bb2, 0x7830, 0xd0bc, 0x00c0, 0x2bb2, 0x789b, 0x0010, 0x7baa, + 0x0078, 0x2c2a, 0x8739, 0x77a6, 0x2750, 0x77b0, 0xa7b0, 0x0005, + 0x70ac, 0xa606, 0x00c0, 0x2bbd, 0x76a8, 0x76b2, 0x2c3a, 0x8738, + 0x2d3a, 0x8738, 0x283a, 0x8738, 0x233a, 0x8738, 0x253a, 0x7830, + 0xd0bc, 0x0040, 0x2bd5, 0x2091, 0x8000, 0x2091, 0x303d, 0x70d4, + 0xa084, 0x303d, 0x2091, 0x8000, 0x2090, 0xaad5, 0x0000, 0x0040, + 0x2bdd, 0x8421, 0x2200, 0x00c0, 0x2b10, 0x007c, 0xd1dc, 0x0040, + 0x3d86, 0x2029, 0x0020, 0xd69c, 0x00c0, 0x2beb, 0x8528, 0xd68c, + 0x00c0, 0x2beb, 0x8528, 0x8840, 0x6f14, 0x610c, 0x8108, 0xa18c, + 0x00ff, 0x70cc, 0xa160, 0x2c64, 0x8cff, 0x0040, 0x2c0a, 0x6014, + 0xa706, 0x00c0, 0x2bf3, 0x60b8, 0x8001, 0x60ba, 0x00c0, 0x2bee, + 0x2a60, 0x6008, 0xa085, 0x0100, 0x600a, 0x2200, 0x8421, 0x00c0, + 0x2b10, 0x007c, 0x2a60, 0x610e, 0x69be, 0x2c00, 0x68c6, 0x8840, + 0x6008, 0xc0d5, 0x600a, 0x77a4, 0xa786, 0x0001, 0x00c0, 0x2bb2, + 0x70d4, 0xd0b4, 0x00c0, 0x2bb2, 0x7000, 0xa082, 0x0002, 0x00c8, + 0x2bb2, 0x7830, 0xd0bc, 0x00c0, 0x2bb2, 0x789b, 0x0010, 0x7baa, + 0x7daa, 0x79aa, 0x2001, 0x0002, 0x007e, 0x6018, 0x8000, 0x601a, + 0x0078, 0x2c33, 0x007e, 0x2960, 0x6104, 0x2a60, 0xa184, 0x0018, + 0x0040, 0x2c4f, 0xa184, 0x0010, 0x0040, 0x2c42, 0x1078, 0x3f99, + 0x00c0, 0x2c74, 0xa184, 0x0008, 0x0040, 0x2c4f, 0x69a0, 0xa184, + 0x0600, 0x00c0, 0x2c4f, 0x1078, 0x3e7c, 0x0078, 0x2c74, 0x69a0, + 0xa184, 0x1e00, 0x0040, 0x2c7f, 0xa184, 0x0800, 0x0040, 0x2c68, + 0x0c7e, 0x2960, 0x6000, 0xa085, 0x2000, 0x6002, 0x6104, 0xa18d, + 0x0010, 0x6106, 0x0c7f, 0x1078, 0x3f99, 0x00c0, 0x2c74, 0x69a0, + 0xa184, 0x0200, 0x0040, 0x2c70, 0x1078, 0x3edc, 0x0078, 0x2c74, + 0xa184, 0x0400, 0x00c0, 0x2c4b, 0x69a0, 0xa184, 0x1000, 0x0040, + 0x2c7f, 0x6914, 0xa18c, 0xff00, 0x810f, 0x1078, 0x2755, 0x027f, + 0xa68c, 0x00e0, 0xa684, 0x0060, 0x0040, 0x2c8c, 0xa086, 0x0060, + 0x00c0, 0x2c8c, 0xa18d, 0x4000, 0xa18d, 0x0104, 0x69b6, 0x789b, + 0x0060, 0x2800, 0x78aa, 0x6818, 0xc0fd, 0x681a, 0xd6bc, 0x0040, + 0x2ca7, 0xc0fc, 0x7087, 0x0000, 0xa08a, 0x000d, 0x0050, 0x2ca5, + 0xa08a, 0x000c, 0x7186, 0x2001, 0x000c, 0x800c, 0x718a, 0x78aa, + 0x3518, 0x3340, 0x3428, 0x8000, 0x80ac, 0xaf80, 0x002b, 0x20a0, + 0x789b, 0x0000, 0xad80, 0x000b, 0x2098, 0x53a6, 0x23a8, 0x2898, + 0x25a0, 0xa286, 0x0020, 0x00c0, 0x2cdf, 0x70d4, 0xc0b5, 0x70d6, + 0x2c00, 0x70ba, 0x2d00, 0x70be, 0x6814, 0xc0fc, 0x8007, 0x7882, + 0xa286, 0x0002, 0x0040, 0x2d15, 0x70a4, 0x8000, 0x70a6, 0x74b4, + 0xa498, 0x0005, 0x70ac, 0xa306, 0x00c0, 0x2cd7, 0x73a8, 0x73b6, + 0xa286, 0x0010, 0x0040, 0x2962, 0x0d7f, 0x0c7f, 0x007c, 0x7000, + 0xa005, 0x00c0, 0x2cbd, 0xa286, 0x0002, 0x00c0, 0x2d2f, 0x1078, + 0x42e9, 0x00c0, 0x2cbd, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x2091, + 0x8000, 0x781b, 0x005b, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, + 0x6898, 0x78d2, 0x78da, 0x2091, 0x8001, 0x7808, 0xc08d, 0x780a, + 0x127e, 0x0d7e, 0x0c7e, 0x70d4, 0xa084, 0x2700, 0x2090, 0x0c7f, + 0x0d7f, 0x127f, 0x2900, 0x705a, 0x68bc, 0x7042, 0x7003, 0x0002, + 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x7830, 0xd0bc, 0x0040, + 0x2d21, 0x2091, 0x303d, 0x70d4, 0xa084, 0x303d, 0x2091, 0x8000, + 0x2090, 0x70a4, 0xa005, 0x00c0, 0x2d26, 0x007c, 0x8421, 0x0040, + 0x2d25, 0x7250, 0x70c0, 0xa200, 0xa015, 0x0078, 0x2b10, 0xa286, + 0x0010, 0x00c0, 0x2d60, 0x1078, 0x42e9, 0x00c0, 0x2cbd, 0x6814, + 0xc0fc, 0x8007, 0x7882, 0x781b, 0x005b, 0x68b4, 0x785a, 0x6894, + 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d, 0x780a, + 0x70a4, 0x8000, 0x70a6, 0x74b4, 0xa490, 0x0005, 0x70ac, 0xa206, + 0x00c0, 0x2d53, 0x72a8, 0x72b6, 0x2900, 0x705a, 0x68bc, 0x7042, + 0x7003, 0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x007c, + 0x6bb4, 0xa39d, 0x2000, 0x7b5a, 0x6814, 0xc0fc, 0x8007, 0x7882, + 0x6b94, 0x7bd6, 0x7bde, 0x6e98, 0x7ed2, 0x7eda, 0x781b, 0x005b, + 0x2900, 0x705a, 0x7202, 0x7808, 0xc08d, 0x780a, 0x2300, 0xa605, + 0x0040, 0x2d8b, 0x70d4, 0xa084, 0x2700, 0xa086, 0x2300, 0x00c0, + 0x2d85, 0x2009, 0x0000, 0x0078, 0x2d87, 0x2009, 0x0001, 0xa284, + 0x000f, 0x1079, 0x2d8f, 0xad80, 0x0009, 0x7046, 0x007c, 0x2d97, + 0x4834, 0x4834, 0x4821, 0x4834, 0x2d97, 0x2d97, 0x2d97, 0x1078, + 0x290c, 0x7808, 0xa084, 0xfffd, 0x780a, 0x0f7e, 0x2079, 0x4d00, + 0x78ac, 0x0f7f, 0xd084, 0x0040, 0x2dbf, 0x7064, 0xa086, 0x0001, + 0x00c0, 0x2dad, 0x7066, 0x0078, 0x2e96, 0x7064, 0xa086, 0x0005, + 0x00c0, 0x2dbd, 0x707c, 0x2068, 0x681b, 0x0004, 0x6817, 0x0000, + 0x6820, 0xa084, 0x00ff, 0xc09d, 0x6822, 0x7067, 0x0000, 0x70a7, + 0x0000, 0x70a8, 0x70b2, 0x70b6, 0x1078, 0x2a5b, 0x157e, 0x2011, + 0x0004, 0x7164, 0xa186, 0x0001, 0x0040, 0x2ddf, 0xa186, 0x0007, + 0x00c0, 0x2dd6, 0x701f, 0x0005, 0x0078, 0x2ddf, 0x701f, 0x0001, + 0x7067, 0x0000, 0x70d4, 0xc0dd, 0x70d6, 0x0078, 0x2de1, 0x7067, + 0x0000, 0x2001, 0x4d0a, 0x2004, 0xa084, 0x00ff, 0xa086, 0x0018, + 0x0040, 0x2df1, 0x7018, 0x7016, 0xa005, 0x00c0, 0x2df1, 0x70a7, + 0x0001, 0x067e, 0x1078, 0x44fb, 0x20a9, 0x0010, 0x2039, 0x0000, + 0x1078, 0x4081, 0xa7b8, 0x0100, 0x00f0, 0x2df8, 0x067f, 0x7000, + 0x0079, 0x2e02, 0x2e3c, 0x2e17, 0x2e17, 0x2e0c, 0x2e3c, 0x2e3c, + 0x2e3c, 0x2e0a, 0x1078, 0x290c, 0x7060, 0xa005, 0x0040, 0x2e3c, + 0xad06, 0x00c0, 0x2e17, 0x6800, 0x7062, 0x0078, 0x2e29, 0x6820, + 0xd084, 0x00c0, 0x2e25, 0x6f14, 0x1078, 0x4187, 0x6008, 0xc0d4, + 0x600a, 0x1078, 0x3d56, 0x0078, 0x2e29, 0x705c, 0x2060, 0x6800, + 0x6002, 0xa684, 0x5f00, 0x681e, 0x6818, 0xd0fc, 0x0040, 0x2e31, + 0x6a1a, 0x6817, 0x0000, 0x682b, 0x0000, 0x6820, 0xa084, 0x00ff, + 0xc09d, 0x6822, 0x1078, 0x2013, 0xb284, 0x0400, 0x0040, 0x2e44, + 0x2021, 0x94d0, 0x0078, 0x2e46, 0x2021, 0x93c0, 0x1078, 0x2e9b, + 0xb284, 0x0400, 0x0040, 0x2e50, 0x2021, 0x4d98, 0x0078, 0x2e52, + 0x2021, 0x4d58, 0x1078, 0x2e9b, 0x20a9, 0x0101, 0xb284, 0x0400, + 0x0040, 0x2e5e, 0x2021, 0x93d0, 0x0078, 0x2e60, 0x2021, 0x92c0, + 0x1078, 0x2e9b, 0x8420, 0x00f0, 0x2e60, 0xb284, 0x0300, 0x0040, + 0x2e6d, 0x2061, 0x52c0, 0x0078, 0x2e6f, 0x2061, 0x72c0, 0x2021, + 0x0002, 0x20a9, 0x0100, 0x6110, 0x81ff, 0x0040, 0x2e8c, 0x6018, + 0x017e, 0x007e, 0x2011, 0x4d02, 0x220c, 0xa102, 0x2012, 0x007f, + 0x017f, 0xa102, 0x0050, 0x2e8c, 0x6012, 0x00c0, 0x2e8c, 0x2011, + 0x4d04, 0x2204, 0xc0a5, 0x2012, 0x601b, 0x0000, 0xace0, 0x0010, + 0x00f0, 0x2e73, 0x8421, 0x00c0, 0x2e71, 0x157f, 0x7003, 0x0000, + 0x704f, 0x0000, 0x007c, 0x047e, 0x2404, 0xa005, 0x0040, 0x2eb6, + 0x2068, 0x6800, 0x007e, 0x6a1a, 0x6817, 0x0000, 0x682b, 0x0000, + 0x68b4, 0xa084, 0x5f00, 0x681e, 0x6820, 0xa084, 0x00ff, 0xc09d, + 0x6822, 0x1078, 0x2013, 0x007f, 0x0078, 0x2e9d, 0x047f, 0x2023, + 0x0000, 0x007c, 0xa282, 0x0003, 0x0050, 0x2ec0, 0x1078, 0x290c, + 0x2300, 0x0079, 0x2ec3, 0x2ec6, 0x2f51, 0x2f6e, 0xa282, 0x0002, + 0x0040, 0x2ecc, 0x1078, 0x290c, 0x7064, 0x7067, 0x0000, 0x7083, + 0x0000, 0x0079, 0x2ed3, 0x2edb, 0x2edb, 0x2edd, 0x2f1d, 0x3d92, + 0x2edb, 0x2f1d, 0x2edb, 0x1078, 0x290c, 0x7774, 0x1078, 0x4081, + 0x7774, 0xa7bc, 0x8f00, 0x1078, 0x4187, 0x6018, 0xa005, 0x0040, + 0x2f14, 0xd7fc, 0x00c0, 0x2ef0, 0x2021, 0x93c0, 0x0078, 0x2ef2, + 0x2021, 0x94d0, 0x2009, 0x0005, 0x2011, 0x0010, 0x1078, 0x2f89, + 0x0040, 0x2f14, 0x157e, 0x20a9, 0x0101, 0xd7fc, 0x00c0, 0x2f04, + 0x2021, 0x92c0, 0x0078, 0x2f06, 0x2021, 0x93d0, 0x047e, 0x2009, + 0x0005, 0x2011, 0x0010, 0x1078, 0x2f89, 0x047f, 0x0040, 0x2f13, + 0x8420, 0x00f0, 0x2f06, 0x157f, 0x8738, 0xa784, 0x001f, 0x00c0, + 0x2ee3, 0x0078, 0x2966, 0x0078, 0x2966, 0x7774, 0x1078, 0x4187, + 0x6018, 0xa005, 0x0040, 0x2f4f, 0xd7fc, 0x00c0, 0x2f2b, 0x2021, + 0x93c0, 0x0078, 0x2f2d, 0x2021, 0x94d0, 0x2009, 0x0005, 0x2011, + 0x0020, 0x1078, 0x2f89, 0x0040, 0x2f4f, 0x157e, 0x20a9, 0x0101, + 0xd7fc, 0x00c0, 0x2f3f, 0x2021, 0x92c0, 0x0078, 0x2f41, 0x2021, + 0x93d0, 0x047e, 0x2009, 0x0005, 0x2011, 0x0020, 0x1078, 0x2f89, + 0x047f, 0x0040, 0x2f4e, 0x8420, 0x00f0, 0x2f41, 0x157f, 0x0078, + 0x2966, 0x2200, 0x0079, 0x2f54, 0x2f57, 0x2f59, 0x2f59, 0x1078, + 0x290c, 0x2009, 0x0012, 0x7064, 0xa086, 0x0002, 0x0040, 0x2f62, + 0x2009, 0x000e, 0x6818, 0xd0fc, 0x0040, 0x2f67, 0x691a, 0x7067, + 0x0000, 0x70d4, 0xc0dd, 0x70d6, 0x0078, 0x4296, 0x2200, 0x0079, + 0x2f71, 0x2f76, 0x2f59, 0x2f74, 0x1078, 0x290c, 0x1078, 0x44fb, + 0x7000, 0xa086, 0x0002, 0x00c0, 0x3d04, 0x1078, 0x3d73, 0x6008, + 0xa084, 0xfbef, 0x600a, 0x1078, 0x3cf5, 0x0040, 0x3d04, 0x0078, + 0x2966, 0x2404, 0xa005, 0x0040, 0x2fc2, 0x2068, 0x2d04, 0x007e, + 0x6814, 0xa706, 0x0040, 0x2f98, 0x2d20, 0x007f, 0x0078, 0x2f8a, + 0x007f, 0x2022, 0x691a, 0x6817, 0x0000, 0x682b, 0x0000, 0x68b4, + 0xa084, 0x5f00, 0x681e, 0x6820, 0xa084, 0x00ff, 0xa205, 0x6822, + 0x1078, 0x2013, 0x2021, 0x4d02, 0x241c, 0x8319, 0x2322, 0x6010, + 0x8001, 0x6012, 0x00c0, 0x2fb9, 0x2021, 0x4d04, 0x2404, 0xc0a5, + 0x2022, 0x6008, 0xa084, 0xf9ef, 0x600a, 0x1078, 0x2a7c, 0x1078, + 0x3d73, 0x007c, 0xa085, 0x0001, 0x0078, 0x2fc1, 0x2300, 0x0079, + 0x2fc9, 0x2fce, 0x2fcc, 0x304e, 0x1078, 0x290c, 0x78e4, 0xa005, + 0x00d0, 0x3004, 0x3208, 0x007e, 0x2001, 0x4d04, 0x2004, 0xd0ec, + 0x007f, 0x0040, 0x2fdf, 0xa18c, 0x0300, 0x0078, 0x2fe1, 0xa18c, + 0x0400, 0x0040, 0x2fe7, 0x0018, 0x2962, 0x0078, 0x2fe9, 0x0028, + 0x2962, 0x2008, 0xa084, 0x0030, 0x00c0, 0x2ff0, 0x0078, 0x36fb, + 0x78ec, 0xa084, 0x0003, 0x0040, 0x2fee, 0x2100, 0xa084, 0x0007, + 0x0079, 0x2ffa, 0x302e, 0x3038, 0x3023, 0x3002, 0x42de, 0x42de, + 0x3002, 0x3043, 0x1078, 0x290c, 0x7000, 0xa086, 0x0004, 0x00c0, + 0x301e, 0x7064, 0xa086, 0x0002, 0x00c0, 0x3014, 0x2011, 0x0002, + 0x2019, 0x0000, 0x0078, 0x2eba, 0x7064, 0xa086, 0x0006, 0x0040, + 0x300e, 0x7064, 0xa086, 0x0004, 0x0040, 0x300e, 0x79e4, 0x2001, + 0x0003, 0x0078, 0x3385, 0x6818, 0xd0fc, 0x0040, 0x3029, 0x681b, + 0x001d, 0x1078, 0x4051, 0x781b, 0x0061, 0x007c, 0x6818, 0xd0fc, + 0x0040, 0x3034, 0x681b, 0x001d, 0x1078, 0x4051, 0x0078, 0x42ba, + 0x6818, 0xd0fc, 0x0040, 0x303e, 0x681b, 0x001d, 0x1078, 0x4051, + 0x781b, 0x00f5, 0x007c, 0x6818, 0xd0fc, 0x0040, 0x3049, 0x681b, + 0x001d, 0x1078, 0x4051, 0x781b, 0x00c5, 0x007c, 0xa584, 0x000f, + 0x00c0, 0x306b, 0x7000, 0x0079, 0x3055, 0x2966, 0x305d, 0x305f, + 0x3d04, 0x3d04, 0x3d04, 0x305d, 0x305d, 0x1078, 0x290c, 0x1078, + 0x3d73, 0x6008, 0xa084, 0xfbef, 0x600a, 0x1078, 0x3cf5, 0x0040, + 0x3d04, 0x0078, 0x2966, 0x78e4, 0xa005, 0x00d0, 0x3004, 0x3208, + 0x007e, 0x2001, 0x4d04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x307c, + 0xa18c, 0x0300, 0x0078, 0x307e, 0xa18c, 0x0400, 0x0040, 0x3084, + 0x0018, 0x3004, 0x0078, 0x3086, 0x0028, 0x3004, 0x2008, 0xa084, + 0x0030, 0x00c0, 0x308e, 0x781b, 0x005b, 0x007c, 0x78ec, 0xa084, + 0x0003, 0x0040, 0x308b, 0x2100, 0xa184, 0x0007, 0x0079, 0x3098, + 0x30a7, 0x30ab, 0x30a2, 0x30a0, 0x42de, 0x42de, 0x30a0, 0x42d8, + 0x1078, 0x290c, 0x1078, 0x4059, 0x781b, 0x0061, 0x007c, 0x1078, + 0x4059, 0x0078, 0x42ba, 0x1078, 0x4059, 0x781b, 0x00f5, 0x007c, + 0x1078, 0x4059, 0x781b, 0x00c5, 0x007c, 0x2300, 0x0079, 0x30b8, + 0x30bd, 0x30bb, 0x30bf, 0x1078, 0x290c, 0x0078, 0x38cf, 0x681b, + 0x0016, 0x78a3, 0x0000, 0x79e4, 0xa184, 0x0030, 0x0040, 0x38cf, + 0x78ec, 0xa084, 0x0003, 0x0040, 0x38cf, 0xa184, 0x0100, 0x0040, + 0x30c3, 0xa184, 0x0007, 0x0079, 0x30d5, 0x30dd, 0x30ab, 0x3023, + 0x4296, 0x42de, 0x42de, 0x4296, 0x42d8, 0x1078, 0x42a2, 0x007c, + 0xa282, 0x0005, 0x0050, 0x30e6, 0x1078, 0x290c, 0x2300, 0x0079, + 0x30e9, 0x30ec, 0x330b, 0x3316, 0x2200, 0x0079, 0x30ef, 0x3109, + 0x30f6, 0x3109, 0x30f4, 0x32ee, 0x1078, 0x290c, 0x789b, 0x0018, + 0x78a8, 0xa084, 0x00ff, 0xa082, 0x0020, 0x0048, 0x4040, 0xa08a, + 0x0004, 0x00c8, 0x4040, 0x0079, 0x3105, 0x4040, 0x4040, 0x4040, + 0x3fea, 0x789b, 0x0018, 0x79a8, 0xa184, 0x0080, 0x0040, 0x311a, + 0x0078, 0x4040, 0x7000, 0xa005, 0x00c0, 0x3110, 0x2011, 0x0004, + 0x0078, 0x3aba, 0xa184, 0x00ff, 0xa08a, 0x0010, 0x00c8, 0x4040, + 0x0079, 0x3122, 0x3134, 0x3132, 0x3149, 0x314d, 0x320f, 0x4040, + 0x4040, 0x3211, 0x4040, 0x4040, 0x32ea, 0x32ea, 0x4040, 0x4040, + 0x4040, 0x32ec, 0x1078, 0x290c, 0xd6e4, 0x0040, 0x313f, 0x2001, + 0x0300, 0x8000, 0x8000, 0x783a, 0x781b, 0x00c0, 0x007c, 0x6818, + 0xd0fc, 0x0040, 0x3147, 0x681b, 0x001d, 0x0078, 0x3137, 0x0078, + 0x4296, 0x681b, 0x001d, 0x0078, 0x404a, 0x6920, 0x6922, 0xa684, + 0x1800, 0x00c0, 0x31a1, 0x6820, 0xd084, 0x00c0, 0x31a7, 0x6818, + 0xa086, 0x0008, 0x00c0, 0x315e, 0x681b, 0x0000, 0xd6d4, 0x0040, + 0x320c, 0xd6bc, 0x0040, 0x319e, 0x7087, 0x0000, 0x6818, 0xa084, + 0x003f, 0xa08a, 0x000d, 0x0050, 0x319e, 0xa08a, 0x000c, 0x7186, 0x2001, 0x000c, 0x800c, 0x718a, 0x789b, 0x0061, 0x78aa, 0x157e, - 0x137e, 0x147e, 0x017e, 0x3208, 0xa18c, 0x0300, 0x0040, 0x3110, - 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x310c, - 0x20a1, 0x012b, 0x0078, 0x3112, 0x20a1, 0x022b, 0x0078, 0x3112, + 0x137e, 0x147e, 0x017e, 0x3208, 0xa18c, 0x0300, 0x0040, 0x3190, + 0x007e, 0x2001, 0x4d04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x318c, + 0x20a1, 0x012b, 0x0078, 0x3192, 0x20a1, 0x022b, 0x0078, 0x3192, 0x20a1, 0x012b, 0x017f, 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, 0x781b, 0x0064, - 0x007c, 0xd6e4, 0x0040, 0x3127, 0x781b, 0x0076, 0x007c, 0xa684, - 0x0060, 0x0040, 0x3189, 0xd6dc, 0x0040, 0x3189, 0xd6fc, 0x00c0, - 0x3133, 0x0078, 0x314a, 0xc6fc, 0x7e5a, 0x6eb6, 0x7adc, 0x79d8, - 0x78d0, 0x801b, 0x00c8, 0x313d, 0x8000, 0xa084, 0x003f, 0xa108, + 0x007c, 0xd6e4, 0x0040, 0x31a7, 0x781b, 0x0076, 0x007c, 0xa684, + 0x0060, 0x0040, 0x3209, 0xd6dc, 0x0040, 0x3209, 0xd6fc, 0x00c0, + 0x31b3, 0x0078, 0x31ca, 0xc6fc, 0x7e5a, 0x6eb6, 0x7adc, 0x79d8, + 0x78d0, 0x801b, 0x00c8, 0x31bd, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, - 0xa303, 0x68ae, 0xd6f4, 0x0040, 0x3150, 0xc6f4, 0x7e5a, 0x6eb6, - 0x7000, 0xa086, 0x0003, 0x00c0, 0x315e, 0x007e, 0x1078, 0x4326, - 0x1078, 0x45f7, 0x007f, 0x781b, 0x0073, 0x007c, 0xa006, 0x1078, - 0x46e5, 0x6ab0, 0x69ac, 0x6c98, 0x6b94, 0x2200, 0xa105, 0x0040, - 0x316d, 0x2200, 0xa422, 0x2100, 0xa31b, 0x6caa, 0x7cd2, 0x7cda, - 0x6ba6, 0x7bd6, 0x7bde, 0x2300, 0xa405, 0x00c0, 0x317d, 0xc6f5, + 0xa303, 0x68ae, 0xd6f4, 0x0040, 0x31d0, 0xc6f4, 0x7e5a, 0x6eb6, + 0x7000, 0xa086, 0x0003, 0x00c0, 0x31de, 0x007e, 0x1078, 0x44fb, + 0x1078, 0x4834, 0x007f, 0x781b, 0x0073, 0x007c, 0xa006, 0x1078, + 0x493a, 0x6ab0, 0x69ac, 0x6c98, 0x6b94, 0x2200, 0xa105, 0x0040, + 0x31ed, 0x2200, 0xa422, 0x2100, 0xa31b, 0x6caa, 0x7cd2, 0x7cda, + 0x6ba6, 0x7bd6, 0x7bde, 0x2300, 0xa405, 0x00c0, 0x31fd, 0xc6f5, 0x7e5a, 0x6eb6, 0x781b, 0x0073, 0x007c, 0x781b, 0x0073, 0x2200, - 0xa115, 0x00c0, 0x3186, 0x1078, 0x45f7, 0x007c, 0x1078, 0x462d, + 0xa115, 0x00c0, 0x3206, 0x1078, 0x4834, 0x007c, 0x1078, 0x486c, 0x007c, 0x781b, 0x0076, 0x007c, 0x781b, 0x0064, 0x007c, 0x1078, - 0x28ec, 0x0078, 0x31dd, 0x6920, 0xd1c4, 0x0040, 0x31a6, 0xc1c4, + 0x290c, 0x0078, 0x325d, 0x6920, 0xd1c4, 0x0040, 0x3226, 0xc1c4, 0x6922, 0x0c7e, 0x7058, 0x2060, 0x6000, 0xc0e4, 0x6002, 0x6004, - 0xa084, 0xfff5, 0x6006, 0x0c7f, 0x0078, 0x31d1, 0xd1cc, 0x0040, - 0x31d1, 0xc1cc, 0x6922, 0x0c7e, 0x7058, 0x2060, 0x6000, 0xc0ec, + 0xa084, 0xfff5, 0x6006, 0x0c7f, 0x0078, 0x3251, 0xd1cc, 0x0040, + 0x3251, 0xc1cc, 0x6922, 0x0c7e, 0x7058, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x6004, 0xc0a4, 0x6006, 0x2008, 0x2c48, 0x0c7f, 0xd19c, - 0x0040, 0x31d1, 0x1078, 0x3fdd, 0x1078, 0x3cda, 0x88ff, 0x0040, - 0x31d1, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a, - 0xd6d4, 0x00c0, 0x31ce, 0x781b, 0x0061, 0x007c, 0x781b, 0x0075, - 0x007c, 0x7e58, 0xd6d4, 0x00c0, 0x31d8, 0x781b, 0x0064, 0x007c, - 0x781b, 0x0076, 0x007c, 0x0078, 0x3ea2, 0x2019, 0x0000, 0x7990, - 0xa18c, 0x0007, 0x00c0, 0x31eb, 0x6820, 0xa084, 0x0100, 0x0040, - 0x31db, 0x2009, 0x0008, 0x789b, 0x0010, 0x78a8, 0xa094, 0x00ff, - 0xa286, 0x0001, 0x00c0, 0x3207, 0x2300, 0x7ca8, 0xa400, 0x2018, - 0xa102, 0x0040, 0x31ff, 0x0048, 0x31ff, 0x0078, 0x3201, 0x0078, - 0x3193, 0x24a8, 0x7aa8, 0x00f0, 0x3201, 0x0078, 0x31ed, 0xa284, - 0x00f0, 0xa086, 0x0020, 0x00c0, 0x325b, 0x8318, 0x8318, 0x2300, - 0xa102, 0x0040, 0x3217, 0x0048, 0x3217, 0x0078, 0x3258, 0xa286, - 0x0023, 0x0040, 0x31db, 0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58, + 0x0040, 0x3251, 0x1078, 0x4183, 0x1078, 0x3e7c, 0x88ff, 0x0040, + 0x3251, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a, + 0xd6d4, 0x00c0, 0x324e, 0x781b, 0x0061, 0x007c, 0x781b, 0x0075, + 0x007c, 0x7e58, 0xd6d4, 0x00c0, 0x3258, 0x781b, 0x0064, 0x007c, + 0x781b, 0x0076, 0x007c, 0x0078, 0x4045, 0x2019, 0x0000, 0x7990, + 0xa18c, 0x0007, 0x00c0, 0x326b, 0x6820, 0xa084, 0x0100, 0x0040, + 0x325b, 0x2009, 0x0008, 0x789b, 0x0010, 0x78a8, 0xa094, 0x00ff, + 0xa286, 0x0001, 0x00c0, 0x3287, 0x2300, 0x7ca8, 0xa400, 0x2018, + 0xa102, 0x0040, 0x327f, 0x0048, 0x327f, 0x0078, 0x3281, 0x0078, + 0x3213, 0x24a8, 0x7aa8, 0x00f0, 0x3281, 0x0078, 0x326d, 0xa284, + 0x00f0, 0xa086, 0x0020, 0x00c0, 0x32db, 0x8318, 0x8318, 0x2300, + 0xa102, 0x0040, 0x3297, 0x0048, 0x3297, 0x0078, 0x32d8, 0xa286, + 0x0023, 0x0040, 0x325b, 0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58, 0xa684, 0xfff1, 0xc0a5, 0x2030, 0x7e5a, 0x6008, 0xc0a5, 0x600a, 0x0c7e, 0x7058, 0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xd1a4, - 0x0040, 0x3238, 0x1078, 0x3fdd, 0x1078, 0x3df6, 0x0078, 0x3246, + 0x0040, 0x32b8, 0x1078, 0x4183, 0x1078, 0x3f99, 0x0078, 0x32c6, 0x0c7e, 0x7058, 0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xd19c, - 0x0040, 0x31d1, 0x1078, 0x3fdd, 0x1078, 0x3cda, 0x88ff, 0x0040, - 0x31d1, 0x789b, 0x0060, 0x2800, 0x78aa, 0xc695, 0x7e5a, 0xd6d4, - 0x00c0, 0x3255, 0x781b, 0x0061, 0x007c, 0x781b, 0x0075, 0x007c, - 0x7aa8, 0x0078, 0x31ed, 0x8318, 0x2300, 0xa102, 0x0040, 0x3264, - 0x0048, 0x3264, 0x0078, 0x31ed, 0xa284, 0x0080, 0x00c0, 0x3ea7, - 0x0078, 0x3ea2, 0x0078, 0x3ea7, 0x0078, 0x3e9d, 0x7058, 0xa04d, + 0x0040, 0x3251, 0x1078, 0x4183, 0x1078, 0x3e7c, 0x88ff, 0x0040, + 0x3251, 0x789b, 0x0060, 0x2800, 0x78aa, 0xc695, 0x7e5a, 0xd6d4, + 0x00c0, 0x32d5, 0x781b, 0x0061, 0x007c, 0x781b, 0x0075, 0x007c, + 0x7aa8, 0x0078, 0x326d, 0x8318, 0x2300, 0xa102, 0x0040, 0x32e4, + 0x0048, 0x32e4, 0x0078, 0x326d, 0xa284, 0x0080, 0x00c0, 0x404a, + 0x0078, 0x4045, 0x0078, 0x404a, 0x0078, 0x4040, 0x7058, 0xa04d, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa08e, 0x0001, 0x0040, - 0x327b, 0x1078, 0x28ec, 0x7aa8, 0xa294, 0x00ff, 0x78a8, 0xa084, - 0x00ff, 0xa08a, 0x0004, 0x00c8, 0x3e9d, 0x0079, 0x3287, 0x3e9d, - 0x3c2c, 0x3e9d, 0x3d9e, 0xa282, 0x0000, 0x00c0, 0x3291, 0x1078, - 0x28ec, 0x1078, 0x3eae, 0x781b, 0x0075, 0x007c, 0xa282, 0x0003, - 0x00c0, 0x329c, 0x1078, 0x28ec, 0xd4fc, 0x00c0, 0x32bc, 0x7064, - 0xa005, 0x0040, 0x32a5, 0x1078, 0x28ec, 0x6f14, 0x7776, 0xa7bc, - 0x8f00, 0x1078, 0x3fe1, 0x6008, 0xa085, 0x0021, 0x600a, 0x8738, - 0xa784, 0x001f, 0x00c0, 0x32a9, 0x1078, 0x3eb2, 0x7067, 0x0002, - 0x701f, 0x0009, 0x0078, 0x32be, 0x1078, 0x3ebe, 0x781b, 0x0075, - 0x007c, 0xa282, 0x0004, 0x0050, 0x32c7, 0x1078, 0x28ec, 0x2300, - 0x0079, 0x32ca, 0x32cd, 0x346b, 0x34ae, 0xa286, 0x0003, 0x0040, - 0x3304, 0x7200, 0x7cd8, 0x7ddc, 0x7fd0, 0x71d4, 0xd1b4, 0x0078, - 0x32fc, 0x0040, 0x32fc, 0x7868, 0xa084, 0x00ff, 0x00c0, 0x32fc, - 0xa282, 0x0002, 0x00c8, 0x32fc, 0x0d7e, 0x783b, 0x8300, 0x781b, - 0x004c, 0x70bc, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, - 0x6898, 0x78d2, 0x78da, 0xc1b4, 0x71d6, 0x7003, 0x0030, 0x0d7f, - 0x2001, 0x0000, 0x0078, 0x3308, 0x783b, 0x1300, 0x781b, 0x004a, - 0x2001, 0x0000, 0x0078, 0x3308, 0x7200, 0x7cd8, 0x7ddc, 0x7fd0, - 0x704a, 0x68a0, 0xd0ec, 0x0040, 0x3310, 0x6008, 0xc08d, 0x600a, - 0xa284, 0x000f, 0x0079, 0x3314, 0x344b, 0x3321, 0x331e, 0x35ae, - 0x35f2, 0x2946, 0x331c, 0x331c, 0x1078, 0x28ec, 0x6008, 0xc0d4, - 0x600a, 0xd6e4, 0x00c0, 0x3328, 0x1078, 0x4326, 0x0040, 0x3404, - 0x7868, 0xa08c, 0x00ff, 0x0040, 0x3369, 0xa186, 0x0008, 0x00c0, - 0x333e, 0x1078, 0x3bd2, 0x6008, 0xc0a4, 0x600a, 0x1078, 0x3b6b, - 0x0040, 0x3369, 0x1078, 0x4326, 0x0078, 0x3353, 0xa186, 0x0028, - 0x00c0, 0x3369, 0x1078, 0x4326, 0x6008, 0xc0a4, 0x600a, 0x6018, - 0xa005, 0x0040, 0x3353, 0x8001, 0x601a, 0x0040, 0x3353, 0x8001, - 0x0040, 0x3353, 0x601e, 0x6820, 0xd084, 0x0040, 0x2946, 0xc084, - 0x6822, 0x705c, 0x0c7e, 0x2060, 0x6800, 0x6002, 0x0c7f, 0x6004, - 0x6802, 0xa005, 0x2d00, 0x00c0, 0x3366, 0x6002, 0x6006, 0x0078, - 0x2946, 0x017e, 0x81ff, 0x00c0, 0x33b0, 0x7000, 0xa086, 0x0030, - 0x0040, 0x33b0, 0x71d4, 0xd1b4, 0x00c0, 0x3397, 0x7060, 0xa005, - 0x00c0, 0x33b0, 0x70a4, 0xa086, 0x0001, 0x0040, 0x33b0, 0x7003, - 0x0000, 0x047e, 0x057e, 0x077e, 0x067e, 0x0c7e, 0x0d7e, 0x1078, - 0x296c, 0x0d7f, 0x0c7f, 0x067f, 0x077f, 0x057f, 0x047f, 0x71d4, - 0xd1b4, 0x00c0, 0x33b0, 0x7003, 0x0040, 0x0078, 0x33b0, 0x1078, - 0x411c, 0x00c0, 0x33b0, 0x781b, 0x005b, 0x0d7e, 0x70bc, 0xa06d, - 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, - 0xc1b4, 0x71d6, 0x7003, 0x0030, 0x7808, 0xc08d, 0x780a, 0x0d7f, - 0x1078, 0x34e8, 0x017f, 0x81ff, 0x0040, 0x3403, 0xa684, 0xdf00, - 0x681e, 0x682b, 0x0000, 0x6f14, 0xa186, 0x0002, 0x00c0, 0x3404, - 0x70d4, 0xd0b4, 0x0040, 0x33d1, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8, - 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, - 0x0c7f, 0x6820, 0xd0dc, 0x00c0, 0x3404, 0x8717, 0xa294, 0x000f, - 0x8213, 0x8213, 0x8213, 0xb284, 0x0300, 0x0040, 0x33e3, 0xa290, - 0x4ec0, 0x0078, 0x33e5, 0xa290, 0x4f40, 0xa290, 0x0000, 0x221c, - 0xd3c4, 0x00c0, 0x33ed, 0x0078, 0x33f3, 0x8210, 0x2204, 0xa085, - 0x0018, 0x2012, 0x8211, 0xd3d4, 0x0040, 0x33fe, 0x68a0, 0xd0c4, - 0x00c0, 0x33fe, 0x1078, 0x3562, 0x0078, 0x2946, 0x6008, 0xc08d, - 0x600a, 0x0078, 0x3404, 0x692a, 0x6916, 0x6818, 0xd0fc, 0x0040, - 0x340b, 0x7048, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x6410, 0x84ff, - 0x0040, 0x3420, 0x2009, 0x4a02, 0x2104, 0x8001, 0x200a, 0x8421, - 0x6412, 0x00c0, 0x3420, 0x2021, 0x4a04, 0x2404, 0xc0a5, 0x2022, - 0x6018, 0xa005, 0x0040, 0x3428, 0x8001, 0x601a, 0x00c0, 0x342b, - 0x6008, 0xc0a4, 0x600a, 0x6820, 0xd084, 0x00c0, 0x3437, 0x6800, - 0xa005, 0x00c0, 0x3434, 0x6002, 0x6006, 0x0078, 0x343b, 0x705c, - 0x2060, 0x6800, 0x6002, 0x2061, 0x4a00, 0x6887, 0x0103, 0x2d08, - 0x206b, 0x0000, 0x6068, 0xa005, 0x616a, 0x0040, 0x344a, 0x2d02, - 0x0078, 0x344b, 0x616e, 0x7200, 0xa286, 0x0030, 0x0040, 0x345b, - 0xa286, 0x0040, 0x00c0, 0x2946, 0x7003, 0x0002, 0x704c, 0x2068, - 0x68c4, 0x2060, 0x007c, 0x7003, 0x0002, 0x70bc, 0xa06d, 0x68bc, - 0x7042, 0x70b8, 0xa065, 0x68c0, 0x705a, 0x2d00, 0x704e, 0xad80, - 0x0009, 0x7046, 0x007c, 0xa282, 0x0004, 0x0048, 0x3471, 0x1078, - 0x28ec, 0x2200, 0x0079, 0x3474, 0x3478, 0x3489, 0x3496, 0x3489, - 0xa586, 0x1300, 0x0040, 0x3489, 0xa586, 0x8300, 0x00c0, 0x346f, - 0x7003, 0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084, 0xfbef, - 0x600a, 0x7000, 0xa086, 0x0005, 0x0040, 0x3493, 0x1078, 0x3eae, - 0x781b, 0x0075, 0x007c, 0x781b, 0x0076, 0x007c, 0x7890, 0x8007, - 0x8001, 0xa084, 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c, - 0x00ff, 0xa186, 0x0003, 0x0040, 0x34ab, 0xa186, 0x0000, 0x0040, - 0x34ab, 0x0078, 0x3e9d, 0x781b, 0x0076, 0x007c, 0x6820, 0xc095, - 0x6822, 0x82ff, 0x00c0, 0x34b8, 0x1078, 0x3eae, 0x0078, 0x34bf, - 0x8211, 0x0040, 0x34bd, 0x1078, 0x28ec, 0x1078, 0x3ebe, 0x781b, - 0x0075, 0x007c, 0x1078, 0x4131, 0x7830, 0xa084, 0x00c0, 0x00c0, - 0x34e5, 0x017e, 0x3208, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, - 0x007f, 0x0040, 0x34d7, 0xa18c, 0x0300, 0x0078, 0x34d9, 0xa18c, - 0x0400, 0x017f, 0x0040, 0x34e0, 0x0018, 0x34e5, 0x0078, 0x34e2, - 0x0028, 0x34e5, 0x791a, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c, - 0xa684, 0x0060, 0x00c0, 0x34f2, 0x682f, 0x0000, 0x6833, 0x0000, - 0x0078, 0x3561, 0xd6dc, 0x00c0, 0x350a, 0x68b4, 0xd0dc, 0x00c0, - 0x350a, 0x6998, 0x6a94, 0x692e, 0x6a32, 0x7048, 0xa005, 0x00c0, - 0x3507, 0x2200, 0xa105, 0x0040, 0x4326, 0x704b, 0x0015, 0x0078, - 0x4326, 0x007c, 0xd6ac, 0x0040, 0x3530, 0xd6f4, 0x0040, 0x3516, - 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x4326, 0x68b4, 0xa084, - 0x4000, 0xa635, 0xd6f4, 0x00c0, 0x3510, 0x7048, 0xa005, 0x00c0, - 0x3523, 0x704b, 0x0015, 0xd6dc, 0x00c0, 0x352c, 0x68b4, 0xd0dc, - 0x0040, 0x352c, 0x6ca8, 0x6da4, 0x6c2e, 0x6d32, 0x0078, 0x4326, - 0xd6f4, 0x0040, 0x3539, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, - 0x4326, 0x68b4, 0xa084, 0x4800, 0xa635, 0xd6f4, 0x00c0, 0x3533, - 0x7048, 0xa005, 0x00c0, 0x3546, 0x704b, 0x0015, 0x2408, 0x2510, - 0x2700, 0x80fb, 0x00c8, 0x354d, 0x8000, 0xa084, 0x003f, 0xa108, - 0xa291, 0x0000, 0x692e, 0x6a32, 0x2100, 0xa205, 0x00c0, 0x355a, - 0x0078, 0x4326, 0x7000, 0xa086, 0x0006, 0x0040, 0x3561, 0x0078, - 0x4326, 0x007c, 0x6008, 0xc0cd, 0xd3cc, 0x0040, 0x3568, 0xc08d, - 0x600a, 0x681b, 0x0006, 0x688f, 0x0000, 0x6893, 0x0000, 0x6a30, - 0x692c, 0x6a3e, 0x6942, 0x682f, 0x0003, 0x6833, 0x0000, 0x6837, - 0x0020, 0x6897, 0x0000, 0x689b, 0x0020, 0x7000, 0x0079, 0x3580, - 0x2946, 0x3592, 0x358a, 0x3588, 0x3588, 0x3588, 0x3588, 0x3588, - 0x1078, 0x28ec, 0x6820, 0xd084, 0x00c0, 0x3592, 0x1078, 0x3bb5, - 0x0078, 0x3598, 0x705c, 0x2c50, 0x2060, 0x6800, 0x6002, 0x2a60, - 0x3208, 0xa18c, 0x0300, 0x0040, 0x35a1, 0x2021, 0x4a58, 0x0078, - 0x35a3, 0x2021, 0x4a98, 0x2404, 0xa005, 0x0040, 0x35aa, 0x2020, - 0x0078, 0x35a3, 0x2d22, 0x206b, 0x0000, 0x007c, 0x1078, 0x3bbc, - 0x1078, 0x3bd2, 0x6008, 0xc0cc, 0x600a, 0x682b, 0x0000, 0x789b, - 0x000e, 0x6f14, 0x6817, 0x0002, 0x3208, 0xa18c, 0x0300, 0x0040, - 0x35c5, 0x2009, 0x0000, 0x0078, 0x35c7, 0x2009, 0x0001, 0x1078, - 0x471a, 0xd6dc, 0x0040, 0x35cf, 0x691c, 0xc1ed, 0x691e, 0x6818, - 0xd0fc, 0x0040, 0x35de, 0x7868, 0xa08c, 0x00ff, 0x0040, 0x35dc, - 0x681b, 0x001e, 0x0078, 0x35de, 0x681b, 0x0000, 0xb284, 0x0300, - 0x00c0, 0x35e6, 0x2021, 0x4a98, 0x0078, 0x35e8, 0x2021, 0x4a58, - 0x6800, 0x2022, 0x6a3c, 0x6940, 0x6a32, 0x692e, 0x1078, 0x202a, - 0x0078, 0x2946, 0x7cd8, 0x7ddc, 0x7fd0, 0x1078, 0x34e8, 0x682b, - 0x0000, 0x789b, 0x000e, 0x6f14, 0x1078, 0x4135, 0xa08c, 0x00ff, - 0x6916, 0x6818, 0xd0fc, 0x0040, 0x3607, 0x7048, 0x681a, 0xa68c, - 0xdf00, 0x691e, 0x7067, 0x0000, 0x0078, 0x2946, 0x7000, 0xa005, - 0x00c0, 0x3614, 0x0078, 0x2946, 0xa006, 0x1078, 0x4326, 0x6817, - 0x0000, 0x681b, 0x0014, 0xa68c, 0xdf00, 0x691e, 0x682b, 0x0000, - 0x6820, 0xa084, 0x00ff, 0x6822, 0x7000, 0x0079, 0x3627, 0x2946, - 0x3634, 0x3631, 0x3636, 0x3636, 0x3636, 0x362f, 0x362f, 0x1078, - 0x28ec, 0x6008, 0xc0d4, 0x600a, 0x1078, 0x3bd2, 0x6008, 0xc0a4, - 0x600a, 0x0078, 0x3b85, 0x2300, 0x0079, 0x363e, 0x3641, 0x3643, - 0x369f, 0x1078, 0x28ec, 0xd6fc, 0x00c0, 0x3686, 0x7000, 0xa00d, - 0x0079, 0x364a, 0x2946, 0x3654, 0x3654, 0x3678, 0x3654, 0x3683, - 0x3652, 0x3652, 0x1078, 0x28ec, 0xa684, 0x0060, 0xa086, 0x0060, - 0x00c0, 0x3675, 0xc6ac, 0xc6f4, 0xc6ed, 0x7e5a, 0x681c, 0xc0ac, - 0x681e, 0xa186, 0x0002, 0x0040, 0x3667, 0x1078, 0x4326, 0x1078, - 0x45f7, 0x781b, 0x0076, 0x71d4, 0xd1b4, 0x00c0, 0x2942, 0x70a4, - 0xa086, 0x0001, 0x00c0, 0x2989, 0x007c, 0xd6ec, 0x0040, 0x365c, - 0x6818, 0xd0fc, 0x0040, 0x3683, 0x681b, 0x0015, 0xd6f4, 0x0040, - 0x3683, 0x681b, 0x0007, 0x1078, 0x40d5, 0x007c, 0xc6fc, 0x7e5a, - 0x7adc, 0x79d8, 0x78d0, 0x801b, 0x00c8, 0x368f, 0x8000, 0xa084, - 0x003f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2, - 0x6b94, 0x2200, 0xa303, 0x68ae, 0x781b, 0x0076, 0x007c, 0x1078, - 0x28ec, 0x2300, 0x0079, 0x36a4, 0x36a9, 0x36c5, 0x3719, 0x1078, - 0x28ec, 0x7000, 0x0079, 0x36ac, 0x36b4, 0x36b6, 0x36b6, 0x36b4, - 0x36b4, 0x36b4, 0x36b4, 0x36b4, 0x1078, 0x28ec, 0x1078, 0x45f7, - 0x681c, 0xc0b4, 0x681e, 0x70d4, 0xd0b4, 0x00c0, 0x2942, 0x70a4, - 0xa086, 0x0001, 0x00c0, 0x2989, 0x007c, 0xd6fc, 0x00c0, 0x3709, - 0x7000, 0xa00d, 0x0079, 0x36cc, 0x2946, 0x36dc, 0x36d6, 0x3700, - 0x36dc, 0x3706, 0x36d4, 0x36d4, 0x1078, 0x28ec, 0x6894, 0x78d6, - 0x78de, 0x6898, 0x78d2, 0x78da, 0xa684, 0x0060, 0xa086, 0x0060, - 0x00c0, 0x36fd, 0xa6b4, 0xbfbf, 0xc6ed, 0x7e5a, 0xa186, 0x0002, - 0x0040, 0x36ec, 0x1078, 0x4326, 0x1078, 0x45f7, 0x781b, 0x0076, - 0x681c, 0xc0b4, 0x681e, 0x71d4, 0xd1b4, 0x00c0, 0x2942, 0x70a4, - 0xa086, 0x0001, 0x00c0, 0x2989, 0x007c, 0xd6ec, 0x0040, 0x36e4, - 0x6818, 0xd0fc, 0x0040, 0x3706, 0x681b, 0x0007, 0x781b, 0x00f0, - 0x007c, 0xc6fc, 0x7e5a, 0x7adc, 0x79d8, 0x6b98, 0x2100, 0xa302, - 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x79d2, 0x781b, 0x0076, - 0x007c, 0xd6dc, 0x0040, 0x3722, 0x782b, 0x3009, 0x781b, 0x0076, - 0x0078, 0x2942, 0x7884, 0xc0ac, 0x7886, 0x78e4, 0xa084, 0x0008, - 0x00c0, 0x3735, 0xa484, 0x0200, 0x0040, 0x372f, 0xc6f5, 0xc6dd, - 0x7e5a, 0x781b, 0x0076, 0x0078, 0x2942, 0x6820, 0xc095, 0x6822, - 0x1078, 0x4062, 0xc6dd, 0x1078, 0x3eae, 0x781b, 0x0075, 0x0078, - 0x2942, 0x2300, 0x0079, 0x3744, 0x3747, 0x3749, 0x374b, 0x1078, - 0x28ec, 0x0078, 0x3ea7, 0xd6d4, 0x00c0, 0x3771, 0x79e4, 0xd1ac, - 0x0040, 0x3759, 0x78ec, 0xa084, 0x0003, 0x0040, 0x3759, 0x782b, - 0x3009, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, - 0x79e4, 0xd1ac, 0x0040, 0x3769, 0x78ec, 0xa084, 0x0003, 0x00c0, - 0x376d, 0x2001, 0x0014, 0x0078, 0x3304, 0xa184, 0x0007, 0x0079, - 0x37a7, 0x7a90, 0xa294, 0x0007, 0x789b, 0x0060, 0x79a8, 0x81ff, - 0x0040, 0x37a5, 0x789b, 0x0010, 0x7ba8, 0xa384, 0x0001, 0x00c0, - 0x3798, 0x7ba8, 0x7ba8, 0xa386, 0x0001, 0x00c0, 0x378b, 0x2009, - 0xfff7, 0x0078, 0x3791, 0xa386, 0x0003, 0x00c0, 0x3798, 0x2009, - 0xffef, 0x0c7e, 0x7058, 0x2060, 0x6004, 0xa104, 0x6006, 0x0c7f, - 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, 0x782b, - 0x3009, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0078, 0x40c9, 0x2fae, - 0x2fb8, 0x37b1, 0x37b7, 0x37af, 0x37af, 0x40c9, 0x40c9, 0x1078, - 0x28ec, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0078, 0x40cf, 0x6920, - 0xa18c, 0xfcff, 0x6922, 0x0078, 0x40c9, 0x79e4, 0xa184, 0x0030, - 0x0040, 0x37c7, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x37f1, 0x7000, - 0xa086, 0x0004, 0x00c0, 0x37e1, 0x7064, 0xa086, 0x0002, 0x00c0, - 0x37d7, 0x2011, 0x0002, 0x2019, 0x0000, 0x0078, 0x2e43, 0x7064, - 0xa086, 0x0006, 0x0040, 0x37d1, 0x7064, 0xa086, 0x0004, 0x0040, - 0x37d1, 0x7000, 0xa086, 0x0000, 0x0040, 0x2942, 0x6820, 0xd0ac, - 0x00c0, 0x37ed, 0x6818, 0xc0fd, 0x681a, 0x2001, 0x0014, 0x0078, - 0x3304, 0xa184, 0x0007, 0x0079, 0x37f5, 0x40c9, 0x40c9, 0x37fd, - 0x40c9, 0x4111, 0x4111, 0x40c9, 0x40c9, 0xd6bc, 0x0040, 0x383f, - 0x7184, 0x81ff, 0x0040, 0x383f, 0xa182, 0x000d, 0x00d0, 0x380c, - 0x7087, 0x0000, 0x0078, 0x3811, 0xa182, 0x000c, 0x7086, 0x2009, - 0x000c, 0x789b, 0x0061, 0x79aa, 0x157e, 0x137e, 0x147e, 0x7088, - 0x8114, 0xa210, 0x728a, 0xa080, 0x000b, 0xad00, 0x2098, 0xb284, - 0x0300, 0x0040, 0x3833, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, - 0x007f, 0x0040, 0x382f, 0x20a1, 0x012b, 0x0078, 0x3835, 0x20a1, - 0x022b, 0x0078, 0x3835, 0x20a1, 0x012b, 0x789b, 0x0000, 0x8108, - 0x81ac, 0x53a6, 0x147f, 0x137f, 0x157f, 0x0078, 0x40cf, 0xd6d4, - 0x00c0, 0x3893, 0x6820, 0xd084, 0x0040, 0x40cf, 0xa68c, 0x0060, - 0xa684, 0x0060, 0x0040, 0x3851, 0xa086, 0x0060, 0x00c0, 0x3851, - 0xc1f5, 0xc194, 0x795a, 0x69b6, 0x789b, 0x0060, 0x78ab, 0x0000, - 0x789b, 0x0061, 0x6818, 0xc0fd, 0x681a, 0x78aa, 0x8008, 0x810c, - 0x0040, 0x3beb, 0xa18c, 0x00f8, 0x00c0, 0x3beb, 0x157e, 0x137e, - 0x147e, 0x017e, 0x3208, 0xa18c, 0x0300, 0x0040, 0x387f, 0x007e, - 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x387b, 0x20a1, - 0x012b, 0x0078, 0x3881, 0x20a1, 0x022b, 0x0078, 0x3881, 0x20a1, - 0x012b, 0x017f, 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, - 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, 0x6814, 0xc0fc, 0x8007, - 0x7882, 0x0078, 0x40cf, 0x6818, 0xd0fc, 0x0040, 0x3899, 0x681b, - 0x0008, 0x6820, 0xc0ad, 0x6822, 0x1078, 0x3eb6, 0x781b, 0x00e1, - 0x007c, 0x2300, 0x0079, 0x38a4, 0x38a9, 0x397b, 0x38a7, 0x1078, - 0x28ec, 0x7cd8, 0x7ddc, 0x7fd0, 0x82ff, 0x00c0, 0x38d1, 0x7200, - 0xa286, 0x0003, 0x0040, 0x32d2, 0x71d4, 0xd1b4, 0x0078, 0x38d4, - 0x0040, 0x38d4, 0x0d7e, 0x783b, 0x8800, 0x781b, 0x004c, 0x70bc, - 0xa06d, 0x68b4, 0xc0a5, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, - 0x78d2, 0x78da, 0xc1b4, 0x71d6, 0x7003, 0x0030, 0x0d7f, 0x0078, - 0x38d8, 0x7200, 0x0078, 0x38d8, 0x783b, 0x1800, 0x781b, 0x004a, - 0xa284, 0x000f, 0x0079, 0x38dc, 0x3966, 0x391a, 0x38e6, 0x3300, - 0x38e4, 0x3966, 0x38e4, 0x38e4, 0x1078, 0x28ec, 0x681c, 0xd0ec, - 0x0040, 0x38ed, 0x6008, 0xc08d, 0x600a, 0x6920, 0xc185, 0x6922, - 0x6800, 0x6006, 0xa005, 0x00c0, 0x38f6, 0x6002, 0x6008, 0xc0d4, - 0x600a, 0x681c, 0xa084, 0x000e, 0x00c0, 0x390a, 0xb284, 0x0300, - 0x0040, 0x3906, 0x2009, 0x90c0, 0x0078, 0x390f, 0x2009, 0x91d0, - 0x0078, 0x390f, 0x7030, 0x68ba, 0x7140, 0x70cc, 0xa108, 0x2104, - 0x6802, 0x2d0a, 0x715e, 0xd6dc, 0x00c0, 0x391a, 0xc6fc, 0x6eb6, - 0x0078, 0x3966, 0x6eb6, 0xa684, 0x0060, 0x0040, 0x3966, 0xd6dc, - 0x00c0, 0x392d, 0xa684, 0x7fff, 0x68b6, 0x6894, 0x68a6, 0x6898, - 0x68aa, 0x1078, 0x4326, 0x0078, 0x3966, 0xd6ac, 0x0040, 0x3939, - 0xa006, 0x1078, 0x4326, 0x2408, 0x2510, 0x69aa, 0x6aa6, 0x0078, - 0x3949, 0x2408, 0x2510, 0x2700, 0x801b, 0x00c8, 0x3940, 0x8000, - 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x69aa, 0x6aa6, 0x1078, - 0x4326, 0xd6fc, 0x0040, 0x3966, 0xa684, 0x7fff, 0x68b6, 0x2510, - 0x2408, 0xd6ac, 0x00c0, 0x395e, 0x2700, 0x801b, 0x00c8, 0x3959, - 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, - 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x7000, 0xa086, - 0x0030, 0x00c0, 0x2946, 0x7003, 0x0002, 0x70bc, 0xa06d, 0x68bc, - 0x7042, 0x70b8, 0xa065, 0x68c0, 0x705a, 0x2d00, 0x704e, 0xad80, - 0x0009, 0x7046, 0x007c, 0xa586, 0x8800, 0x00c0, 0x3988, 0x7003, - 0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084, 0xfbef, 0x600a, - 0x0078, 0x3ea7, 0x7047, 0x0000, 0xa282, 0x0006, 0x0050, 0x3992, - 0x1078, 0x28ec, 0x2300, 0x0079, 0x3995, 0x3998, 0x39cf, 0x3a01, - 0x2200, 0x0079, 0x399b, 0x39a1, 0x3ea7, 0x39a3, 0x39a1, 0x3a38, - 0x3a9b, 0x1078, 0x28ec, 0x7003, 0x0005, 0xb284, 0x0300, 0x0040, - 0x39ad, 0x2001, 0x91e0, 0x0078, 0x39af, 0x2001, 0x9212, 0x2068, + 0x32fb, 0x1078, 0x290c, 0x7aa8, 0xa294, 0x00ff, 0x78a8, 0xa084, + 0x00ff, 0xa08a, 0x0004, 0x00c8, 0x4040, 0x0079, 0x3307, 0x4040, + 0x3dce, 0x4040, 0x3f41, 0xa282, 0x0000, 0x00c0, 0x3311, 0x1078, + 0x290c, 0x1078, 0x4051, 0x781b, 0x0075, 0x007c, 0xa282, 0x0003, + 0x00c0, 0x331c, 0x1078, 0x290c, 0xd4fc, 0x00c0, 0x333c, 0x7064, + 0xa005, 0x0040, 0x3325, 0x1078, 0x290c, 0x6f14, 0x7776, 0xa7bc, + 0x8f00, 0x1078, 0x4187, 0x6008, 0xa085, 0x0021, 0x600a, 0x8738, + 0xa784, 0x001f, 0x00c0, 0x3329, 0x1078, 0x4055, 0x7067, 0x0002, + 0x701f, 0x0009, 0x0078, 0x333e, 0x1078, 0x4064, 0x781b, 0x0075, + 0x007c, 0xa282, 0x0004, 0x0050, 0x3347, 0x1078, 0x290c, 0x2300, + 0x0079, 0x334a, 0x334d, 0x350d, 0x3550, 0xa286, 0x0003, 0x0040, + 0x3385, 0x7200, 0x7cd8, 0x7ddc, 0x7fd0, 0x71d4, 0xd1bc, 0x00c0, + 0x337d, 0xd1b4, 0x0040, 0x337d, 0x7868, 0xa084, 0x00ff, 0x00c0, + 0x337d, 0xa282, 0x0002, 0x00c8, 0x337d, 0x0d7e, 0x783b, 0x8300, + 0x781b, 0x004c, 0x70bc, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, + 0x78de, 0x6898, 0x78d2, 0x78da, 0xc1b4, 0x71d6, 0x7003, 0x0030, + 0x0d7f, 0x2001, 0x0000, 0x0078, 0x3389, 0x783b, 0x1300, 0x781b, + 0x004a, 0x2001, 0x0000, 0x0078, 0x3389, 0x7200, 0x7cd8, 0x7ddc, + 0x7fd0, 0x704a, 0x68a0, 0xd0ec, 0x0040, 0x3391, 0x6008, 0xc08d, + 0x600a, 0xa284, 0x000f, 0x0079, 0x3395, 0x34ed, 0x33a2, 0x339f, + 0x3653, 0x36df, 0x2966, 0x339d, 0x339d, 0x1078, 0x290c, 0x6008, + 0xc0d4, 0x600a, 0xd6e4, 0x0040, 0x33aa, 0x7048, 0xa086, 0x0014, + 0x00c0, 0x33ca, 0x1078, 0x44fb, 0x2009, 0x0000, 0x6818, 0xd0fc, + 0x0040, 0x33b3, 0x7048, 0xa086, 0x0014, 0x0040, 0x33c4, 0x6818, + 0xa086, 0x0008, 0x00c0, 0x34a5, 0x7858, 0xd09c, 0x0040, 0x34a5, + 0x6820, 0xd0ac, 0x0040, 0x34a5, 0x681b, 0x0014, 0x2009, 0x0002, + 0x0078, 0x3409, 0x7868, 0xa08c, 0x00ff, 0x0040, 0x3409, 0xa186, + 0x0008, 0x00c0, 0x33e0, 0x6008, 0xc0a4, 0x600a, 0x1078, 0x3cf5, + 0x0040, 0x3409, 0x1078, 0x3d73, 0x1078, 0x44fb, 0x0078, 0x33f1, + 0xa186, 0x0028, 0x00c0, 0x3409, 0x6018, 0xa005, 0x0040, 0x33d3, + 0x8001, 0x0040, 0x33d3, 0x8001, 0x0040, 0x33d3, 0x601e, 0x0078, + 0x33d3, 0x6820, 0xd084, 0x0040, 0x2966, 0xc084, 0x6822, 0x1078, + 0x2a6d, 0x705c, 0x0c7e, 0x2060, 0x6800, 0x6002, 0x0c7f, 0x6004, + 0x6802, 0xa005, 0x2d00, 0x00c0, 0x3406, 0x6002, 0x6006, 0x0078, + 0x2966, 0x017e, 0x81ff, 0x00c0, 0x3453, 0x7000, 0xa086, 0x0030, + 0x0040, 0x3453, 0x71d4, 0xd1bc, 0x00c0, 0x3453, 0xd1b4, 0x00c0, + 0x343a, 0x7060, 0xa005, 0x00c0, 0x3453, 0x70a4, 0xa086, 0x0001, + 0x0040, 0x3453, 0x7003, 0x0000, 0x047e, 0x057e, 0x077e, 0x067e, + 0x0c7e, 0x0d7e, 0x1078, 0x298f, 0x0d7f, 0x0c7f, 0x067f, 0x077f, + 0x057f, 0x047f, 0x71d4, 0xd1b4, 0x00c0, 0x3453, 0x7003, 0x0040, + 0x0078, 0x3453, 0x1078, 0x42e9, 0x00c0, 0x3453, 0x781b, 0x005b, + 0x0d7e, 0x70bc, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, + 0x6898, 0x78d2, 0x78da, 0xc1b4, 0x71d6, 0x7003, 0x0030, 0x7808, + 0xc08d, 0x780a, 0x0d7f, 0x1078, 0x358a, 0x017f, 0x81ff, 0x0040, + 0x34a5, 0xa684, 0xdf00, 0x681e, 0x682b, 0x0000, 0x6f14, 0xa186, + 0x0002, 0x00c0, 0x34a6, 0x6818, 0xa086, 0x0014, 0x00c0, 0x346f, + 0x2008, 0xd6e4, 0x0040, 0x346f, 0x7868, 0xa08c, 0x00ff, 0x1078, + 0x2a5b, 0x1078, 0x2a7c, 0x6820, 0xd0dc, 0x00c0, 0x34a6, 0x8717, + 0xa294, 0x000f, 0x8213, 0x8213, 0x8213, 0xb284, 0x0300, 0x0040, + 0x3485, 0xa290, 0x51c0, 0x0078, 0x3487, 0xa290, 0x5240, 0xa290, + 0x0000, 0x221c, 0xd3c4, 0x00c0, 0x348f, 0x0078, 0x3495, 0x8210, + 0x2204, 0xa085, 0x0018, 0x2012, 0x8211, 0xd3d4, 0x0040, 0x34a0, + 0x68a0, 0xd0c4, 0x00c0, 0x34a0, 0x1078, 0x3604, 0x0078, 0x2966, + 0x6008, 0xc08d, 0x600a, 0x0078, 0x34a6, 0x692a, 0x6916, 0x6818, + 0xd0fc, 0x0040, 0x34ad, 0x7048, 0x681a, 0xa68c, 0xdf00, 0x691e, + 0x6410, 0x84ff, 0x0040, 0x34c2, 0x2009, 0x4d02, 0x2104, 0x8001, + 0x200a, 0x8421, 0x6412, 0x00c0, 0x34c2, 0x2021, 0x4d04, 0x2404, + 0xc0a5, 0x2022, 0x6018, 0xa005, 0x0040, 0x34ca, 0x8001, 0x601a, + 0x00c0, 0x34cd, 0x6008, 0xc0a4, 0x600a, 0x6820, 0xd084, 0x00c0, + 0x34d9, 0x6800, 0xa005, 0x00c0, 0x34d6, 0x6002, 0x6006, 0x0078, + 0x34dd, 0x705c, 0x2060, 0x6800, 0x6002, 0x2061, 0x4d00, 0x6887, + 0x0103, 0x2d08, 0x206b, 0x0000, 0x6068, 0xa005, 0x616a, 0x0040, + 0x34ec, 0x2d02, 0x0078, 0x34ed, 0x616e, 0x7200, 0xa286, 0x0030, + 0x0040, 0x34fd, 0xa286, 0x0040, 0x00c0, 0x2966, 0x7003, 0x0002, + 0x704c, 0x2068, 0x68c4, 0x2060, 0x007c, 0x7003, 0x0002, 0x70bc, + 0xa06d, 0x68bc, 0x7042, 0x70b8, 0xa065, 0x68c0, 0x705a, 0x2d00, + 0x704e, 0xad80, 0x0009, 0x7046, 0x007c, 0xa282, 0x0004, 0x0048, + 0x3513, 0x1078, 0x290c, 0x2200, 0x0079, 0x3516, 0x351a, 0x352b, + 0x3538, 0x352b, 0xa586, 0x1300, 0x0040, 0x352b, 0xa586, 0x8300, + 0x00c0, 0x3511, 0x7003, 0x0000, 0x6018, 0x8001, 0x601a, 0x6008, + 0xa084, 0xfbef, 0x600a, 0x7000, 0xa086, 0x0005, 0x0040, 0x3535, + 0x1078, 0x4051, 0x781b, 0x0075, 0x007c, 0x781b, 0x0076, 0x007c, + 0x7890, 0x8007, 0x8001, 0xa084, 0x0007, 0xa080, 0x0018, 0x789a, + 0x79a8, 0xa18c, 0x00ff, 0xa186, 0x0003, 0x0040, 0x354d, 0xa186, + 0x0000, 0x0040, 0x354d, 0x0078, 0x4040, 0x781b, 0x0076, 0x007c, + 0x6820, 0xc095, 0x6822, 0x82ff, 0x00c0, 0x355a, 0x1078, 0x4051, + 0x0078, 0x3561, 0x8211, 0x0040, 0x355f, 0x1078, 0x290c, 0x1078, + 0x4064, 0x781b, 0x0075, 0x007c, 0x1078, 0x42fe, 0x7830, 0xa084, + 0x00c0, 0x00c0, 0x3587, 0x017e, 0x3208, 0x007e, 0x2001, 0x4d04, + 0x2004, 0xd0ec, 0x007f, 0x0040, 0x3579, 0xa18c, 0x0300, 0x0078, + 0x357b, 0xa18c, 0x0400, 0x017f, 0x0040, 0x3582, 0x0018, 0x3587, + 0x0078, 0x3584, 0x0028, 0x3587, 0x791a, 0xa006, 0x007c, 0xa085, + 0x0001, 0x007c, 0xa684, 0x0060, 0x00c0, 0x3594, 0x682f, 0x0000, + 0x6833, 0x0000, 0x0078, 0x3603, 0xd6dc, 0x00c0, 0x35ac, 0x68b4, + 0xd0dc, 0x00c0, 0x35ac, 0x6998, 0x6a94, 0x692e, 0x6a32, 0x7048, + 0xa005, 0x00c0, 0x35a9, 0x2200, 0xa105, 0x0040, 0x44fb, 0x704b, + 0x0015, 0x0078, 0x44fb, 0x007c, 0xd6ac, 0x0040, 0x35d2, 0xd6f4, + 0x0040, 0x35b8, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x44fb, + 0x68b4, 0xa084, 0x4000, 0xa635, 0xd6f4, 0x00c0, 0x35b2, 0x7048, + 0xa005, 0x00c0, 0x35c5, 0x704b, 0x0015, 0xd6dc, 0x00c0, 0x35ce, + 0x68b4, 0xd0dc, 0x0040, 0x35ce, 0x6ca8, 0x6da4, 0x6c2e, 0x6d32, + 0x0078, 0x44fb, 0xd6f4, 0x0040, 0x35db, 0x682f, 0x0000, 0x6833, + 0x0000, 0x0078, 0x44fb, 0x68b4, 0xa084, 0x4800, 0xa635, 0xd6f4, + 0x00c0, 0x35d5, 0x7048, 0xa005, 0x00c0, 0x35e8, 0x704b, 0x0015, + 0x2408, 0x2510, 0x2700, 0x80fb, 0x00c8, 0x35ef, 0x8000, 0xa084, + 0x003f, 0xa108, 0xa291, 0x0000, 0x692e, 0x6a32, 0x2100, 0xa205, + 0x00c0, 0x35fc, 0x0078, 0x44fb, 0x7000, 0xa086, 0x0006, 0x0040, + 0x3603, 0x0078, 0x44fb, 0x007c, 0x6946, 0x6008, 0xc0cd, 0xd3cc, + 0x0040, 0x360b, 0xc08d, 0x600a, 0x6818, 0x683a, 0x681b, 0x0006, + 0x688f, 0x0000, 0x6893, 0x0000, 0x6a30, 0x692c, 0x6a3e, 0x6942, + 0x682f, 0x0003, 0x6833, 0x0000, 0x6837, 0x0020, 0x6897, 0x0000, + 0x689b, 0x0020, 0x7000, 0x0079, 0x3625, 0x2966, 0x3637, 0x362f, + 0x362d, 0x362d, 0x362d, 0x362d, 0x362d, 0x1078, 0x290c, 0x6820, + 0xd084, 0x00c0, 0x3637, 0x1078, 0x3d56, 0x0078, 0x363d, 0x705c, + 0x2c50, 0x2060, 0x6800, 0x6002, 0x2a60, 0x3208, 0xa18c, 0x0300, + 0x0040, 0x3646, 0x2021, 0x4d58, 0x0078, 0x3648, 0x2021, 0x4d98, + 0x2404, 0xa005, 0x0040, 0x364f, 0x2020, 0x0078, 0x3648, 0x2d22, + 0x206b, 0x0000, 0x007c, 0x1078, 0x3d5d, 0x1078, 0x3d73, 0x6008, + 0xc0cc, 0x600a, 0x682b, 0x0000, 0x789b, 0x000e, 0x6f14, 0x6938, + 0x691a, 0x6944, 0x6916, 0x3208, 0xa18c, 0x0300, 0x0040, 0x366c, + 0x2009, 0x0000, 0x0078, 0x366e, 0x2009, 0x0001, 0x1078, 0x496f, + 0xd6dc, 0x0040, 0x3676, 0x691c, 0xc1ed, 0x691e, 0x6818, 0xd0fc, + 0x0040, 0x3685, 0x7868, 0xa08c, 0x00ff, 0x0040, 0x3683, 0x681b, + 0x001e, 0x0078, 0x3685, 0x681b, 0x0000, 0xb284, 0x0300, 0x00c0, + 0x368d, 0x2021, 0x4d98, 0x0078, 0x368f, 0x2021, 0x4d58, 0x6800, + 0x2022, 0x6a3c, 0x6940, 0x6a32, 0x692e, 0x68c0, 0x2060, 0x6000, + 0xd0a4, 0x0040, 0x36cf, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, + 0x0020, 0x0d7e, 0x0f7e, 0x157e, 0x147e, 0x2079, 0x4d00, 0x1078, + 0x1de6, 0x147f, 0x157f, 0x0f7f, 0x70cc, 0x2010, 0x2009, 0x0101, + 0x027e, 0x2204, 0xa06d, 0x0040, 0x36bf, 0x6814, 0xa706, 0x0040, + 0x36bc, 0x6800, 0x0078, 0x36b2, 0x6820, 0xc0d5, 0x6822, 0x027f, + 0x8210, 0x8109, 0x00c0, 0x36b0, 0x0d7f, 0x7067, 0x0003, 0x707f, + 0x0000, 0x7776, 0x7083, 0x000f, 0x71d4, 0xc1dc, 0x71d6, 0x6818, + 0xa086, 0x0002, 0x00c0, 0x36db, 0x6817, 0x0000, 0x682b, 0x0000, + 0x681c, 0xc0ec, 0x681e, 0x1078, 0x2013, 0x0078, 0x2966, 0x7cd8, + 0x7ddc, 0x7fd0, 0x1078, 0x358a, 0x682b, 0x0000, 0x789b, 0x000e, + 0x6f14, 0x1078, 0x4302, 0xa08c, 0x00ff, 0x6916, 0x6818, 0xd0fc, + 0x0040, 0x36f4, 0x7048, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x7067, + 0x0000, 0x0078, 0x2966, 0x7000, 0xa005, 0x00c0, 0x3701, 0x0078, + 0x2966, 0xa006, 0x1078, 0x44fb, 0x6920, 0xd1ac, 0x00c0, 0x370a, + 0x681b, 0x0014, 0xa68c, 0xdf00, 0x691e, 0x682b, 0x0000, 0x6820, + 0xa084, 0x00ff, 0x6822, 0x7000, 0x0079, 0x3716, 0x2966, 0x3720, + 0x3720, 0x3723, 0x3723, 0x3723, 0x371e, 0x371e, 0x1078, 0x290c, + 0x6818, 0x0078, 0x3385, 0x6008, 0xc0a4, 0x600a, 0x6817, 0x0000, + 0x0078, 0x3d1b, 0x2300, 0x0079, 0x372d, 0x3730, 0x3732, 0x379d, + 0x1078, 0x290c, 0xd6fc, 0x00c0, 0x3784, 0x7000, 0xa00d, 0x0079, + 0x3739, 0x2966, 0x3743, 0x3743, 0x3772, 0x3743, 0x3781, 0x3741, + 0x3741, 0x1078, 0x290c, 0xa684, 0x0060, 0x0040, 0x3772, 0xa086, + 0x0060, 0x00c0, 0x376f, 0xc6ac, 0xc6f4, 0xc6ed, 0x7e5a, 0x681c, + 0xc0ac, 0x681e, 0xa186, 0x0002, 0x0040, 0x3761, 0x1078, 0x44fb, + 0x69ac, 0x68b0, 0xa115, 0x0040, 0x3761, 0x1078, 0x486c, 0x0078, + 0x3763, 0x1078, 0x4834, 0x781b, 0x0076, 0x71d4, 0xd1b4, 0x00c0, + 0x2962, 0x70a4, 0xa086, 0x0001, 0x00c0, 0x29ac, 0x007c, 0xd6ec, + 0x0040, 0x374d, 0x6818, 0xd0fc, 0x0040, 0x3781, 0xd6f4, 0x00c0, + 0x377f, 0x681b, 0x0015, 0x781b, 0x0076, 0x0078, 0x2962, 0x681b, + 0x0007, 0x1078, 0x42a2, 0x007c, 0xc6fc, 0x7e5a, 0x7adc, 0x79d8, + 0x78d0, 0x801b, 0x00c8, 0x378d, 0x8000, 0xa084, 0x003f, 0xa108, + 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, + 0xa303, 0x68ae, 0x781b, 0x0076, 0x007c, 0x1078, 0x290c, 0x2300, + 0x0079, 0x37a2, 0x37a7, 0x37cc, 0x382b, 0x1078, 0x290c, 0x7000, + 0x0079, 0x37aa, 0x37b2, 0x37b4, 0x37bd, 0x37b2, 0x37b2, 0x37b2, + 0x37b2, 0x37b2, 0x1078, 0x290c, 0x69ac, 0x68b0, 0xa115, 0x0040, + 0x37bd, 0x1078, 0x486c, 0x0078, 0x37bf, 0x1078, 0x4834, 0x681c, + 0xc0b4, 0x681e, 0x70d4, 0xd0b4, 0x00c0, 0x2962, 0x70a4, 0xa086, + 0x0001, 0x00c0, 0x29ac, 0x007c, 0xd6fc, 0x00c0, 0x381b, 0x7000, + 0xa00d, 0x0079, 0x37d3, 0x2966, 0x37e3, 0x37dd, 0x3812, 0x37e3, + 0x3818, 0x37db, 0x37db, 0x1078, 0x290c, 0x6894, 0x78d6, 0x78de, + 0x6898, 0x78d2, 0x78da, 0xa684, 0x0060, 0x0040, 0x3812, 0xa086, + 0x0060, 0x00c0, 0x380f, 0xa6b4, 0xbfbf, 0xc6ed, 0x7e5a, 0xa186, + 0x0002, 0x0040, 0x37fe, 0x1078, 0x44fb, 0x69ac, 0x68b0, 0xa115, + 0x0040, 0x37fe, 0x1078, 0x486c, 0x0078, 0x3800, 0x1078, 0x4834, + 0x781b, 0x0076, 0x681c, 0xc0b4, 0x681e, 0x71d4, 0xd1b4, 0x00c0, + 0x2962, 0x70a4, 0xa086, 0x0001, 0x00c0, 0x29ac, 0x007c, 0xd6ec, + 0x0040, 0x37ed, 0x6818, 0xd0fc, 0x0040, 0x3818, 0x681b, 0x0007, + 0x781b, 0x00f6, 0x007c, 0xc6fc, 0x7e5a, 0x7adc, 0x79d8, 0x6b98, + 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x79d2, + 0x781b, 0x0076, 0x007c, 0xd6dc, 0x0040, 0x3834, 0x782b, 0x3009, + 0x781b, 0x0076, 0x0078, 0x2962, 0x7884, 0xc0ac, 0x7886, 0x78e4, + 0xa084, 0x0008, 0x00c0, 0x3847, 0xa484, 0x0200, 0x0040, 0x3841, + 0xc6f5, 0xc6dd, 0x7e5a, 0x781b, 0x0076, 0x0078, 0x2962, 0x6820, + 0xc095, 0x6822, 0x1078, 0x421b, 0xc6dd, 0x1078, 0x4051, 0x781b, + 0x0075, 0x0078, 0x2962, 0x2300, 0x0079, 0x3856, 0x3859, 0x385b, + 0x385d, 0x1078, 0x290c, 0x0078, 0x404a, 0xd6d4, 0x00c0, 0x3883, + 0x79e4, 0xd1ac, 0x0040, 0x386b, 0x78ec, 0xa084, 0x0003, 0x0040, + 0x386b, 0x782b, 0x3009, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, + 0xfffb, 0x785a, 0x79e4, 0xd1ac, 0x0040, 0x387b, 0x78ec, 0xa084, + 0x0003, 0x00c0, 0x387f, 0x2001, 0x0014, 0x0078, 0x3385, 0xa184, + 0x0007, 0x0079, 0x38b9, 0x7a90, 0xa294, 0x0007, 0x789b, 0x0060, + 0x79a8, 0x81ff, 0x0040, 0x38b7, 0x789b, 0x0010, 0x7ba8, 0xa384, + 0x0001, 0x00c0, 0x38aa, 0x7ba8, 0x7ba8, 0xa386, 0x0001, 0x00c0, + 0x389d, 0x2009, 0xfff7, 0x0078, 0x38a3, 0xa386, 0x0003, 0x00c0, + 0x38aa, 0x2009, 0xffef, 0x0c7e, 0x7058, 0x2060, 0x6004, 0xa104, + 0x6006, 0x0c7f, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, + 0x785a, 0x782b, 0x3009, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0078, + 0x4296, 0x302e, 0x3038, 0x38c3, 0x38c9, 0x38c1, 0x38c1, 0x4296, + 0x4296, 0x1078, 0x290c, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0078, + 0x429c, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0078, 0x4296, 0x79e4, + 0xa184, 0x0030, 0x0040, 0x38d9, 0x78ec, 0xa084, 0x0003, 0x00c0, + 0x390d, 0x7000, 0xa086, 0x0004, 0x00c0, 0x38f3, 0x7064, 0xa086, + 0x0002, 0x00c0, 0x38e9, 0x2011, 0x0002, 0x2019, 0x0000, 0x0078, + 0x2eba, 0x7064, 0xa086, 0x0006, 0x0040, 0x38e3, 0x7064, 0xa086, + 0x0004, 0x0040, 0x38e3, 0x7000, 0xa086, 0x0000, 0x0040, 0x2962, + 0x6920, 0xa184, 0x0420, 0x0040, 0x3902, 0xc1d4, 0x6922, 0x6818, + 0x0078, 0x3385, 0x6818, 0xa08e, 0x0002, 0x0040, 0x390b, 0xc0fd, + 0x681a, 0x2001, 0x0014, 0x0078, 0x3385, 0xa184, 0x0007, 0x0079, + 0x3911, 0x4296, 0x4296, 0x3919, 0x4296, 0x42de, 0x42de, 0x4296, + 0x4296, 0xd6bc, 0x0040, 0x395b, 0x7184, 0x81ff, 0x0040, 0x395b, + 0xa182, 0x000d, 0x00d0, 0x3928, 0x7087, 0x0000, 0x0078, 0x392d, + 0xa182, 0x000c, 0x7086, 0x2009, 0x000c, 0x789b, 0x0061, 0x79aa, + 0x157e, 0x137e, 0x147e, 0x7088, 0x8114, 0xa210, 0x728a, 0xa080, + 0x000b, 0xad00, 0x2098, 0xb284, 0x0300, 0x0040, 0x394f, 0x007e, + 0x2001, 0x4d04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x394b, 0x20a1, + 0x012b, 0x0078, 0x3951, 0x20a1, 0x022b, 0x0078, 0x3951, 0x20a1, + 0x012b, 0x789b, 0x0000, 0x8108, 0x81ac, 0x53a6, 0x147f, 0x137f, + 0x157f, 0x0078, 0x429c, 0xd6d4, 0x00c0, 0x39af, 0x6820, 0xd084, + 0x0040, 0x429c, 0xa68c, 0x0060, 0xa684, 0x0060, 0x0040, 0x396d, + 0xa086, 0x0060, 0x00c0, 0x396d, 0xc1f5, 0xc194, 0x795a, 0x69b6, + 0x789b, 0x0060, 0x78ab, 0x0000, 0x789b, 0x0061, 0x6818, 0xc0fd, + 0x681a, 0x78aa, 0x8008, 0x810c, 0x0040, 0x3d8c, 0xa18c, 0x00f8, + 0x00c0, 0x3d8c, 0x157e, 0x137e, 0x147e, 0x017e, 0x3208, 0xa18c, + 0x0300, 0x0040, 0x399b, 0x007e, 0x2001, 0x4d04, 0x2004, 0xd0ec, + 0x007f, 0x0040, 0x3997, 0x20a1, 0x012b, 0x0078, 0x399d, 0x20a1, + 0x022b, 0x0078, 0x399d, 0x20a1, 0x012b, 0x017f, 0x789b, 0x0000, + 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f, + 0x157f, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x0078, 0x429c, 0x6818, + 0xd0fc, 0x0040, 0x39b5, 0x681b, 0x0008, 0x6820, 0xc0ad, 0x6822, + 0x1078, 0x4059, 0x781b, 0x00e7, 0x007c, 0x2300, 0x0079, 0x39c0, + 0x39c5, 0x3a9d, 0x39c3, 0x1078, 0x290c, 0x7cd8, 0x7ddc, 0x7fd0, + 0x82ff, 0x00c0, 0x39ee, 0x7200, 0xa286, 0x0003, 0x0040, 0x3352, + 0x71d4, 0xd1bc, 0x00c0, 0x39f1, 0xd1b4, 0x0040, 0x39f1, 0x0d7e, + 0x783b, 0x8800, 0x781b, 0x004c, 0x70bc, 0xa06d, 0x68b4, 0xc0a5, + 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0xc1b4, + 0x71d6, 0x7003, 0x0030, 0x0d7f, 0x0078, 0x39f5, 0x7200, 0x0078, + 0x39f5, 0x783b, 0x1800, 0x781b, 0x004a, 0xa284, 0x000f, 0x0079, + 0x39f9, 0x3a88, 0x3a37, 0x3a03, 0x3381, 0x3a01, 0x3a88, 0x3a01, + 0x3a01, 0x1078, 0x290c, 0x681c, 0xd0ec, 0x0040, 0x3a0a, 0x6008, + 0xc08d, 0x600a, 0x6920, 0xc185, 0x6922, 0x6800, 0x6006, 0xa005, + 0x00c0, 0x3a13, 0x6002, 0x6008, 0xc0d4, 0x600a, 0x681c, 0xa084, + 0x000e, 0x00c0, 0x3a27, 0xb284, 0x0300, 0x0040, 0x3a23, 0x2009, + 0x93c0, 0x0078, 0x3a2c, 0x2009, 0x94d0, 0x0078, 0x3a2c, 0x7030, + 0x68ba, 0x7140, 0x70cc, 0xa108, 0x2104, 0x6802, 0x2d0a, 0x715e, + 0xd6dc, 0x00c0, 0x3a37, 0xc6fc, 0x6eb6, 0x0078, 0x3a88, 0x6eb6, + 0xa684, 0x0060, 0x00c0, 0x3a41, 0xa684, 0x7fff, 0x68b6, 0x0078, + 0x3a88, 0xd6dc, 0x00c0, 0x3a4f, 0xa684, 0x7fff, 0x68b6, 0x6894, + 0x68a6, 0x6898, 0x68aa, 0x1078, 0x44fb, 0x0078, 0x3a88, 0xd6ac, + 0x0040, 0x3a5b, 0xa006, 0x1078, 0x44fb, 0x2408, 0x2510, 0x69aa, + 0x6aa6, 0x0078, 0x3a6b, 0x2408, 0x2510, 0x2700, 0x801b, 0x00c8, + 0x3a62, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x69aa, + 0x6aa6, 0x1078, 0x44fb, 0xd6fc, 0x0040, 0x3a88, 0xa684, 0x7fff, + 0x68b6, 0x2510, 0x2408, 0xd6ac, 0x00c0, 0x3a80, 0x2700, 0x801b, + 0x00c8, 0x3a7b, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, + 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, + 0x7000, 0xa086, 0x0030, 0x00c0, 0x2966, 0x7003, 0x0002, 0x70bc, + 0xa06d, 0x68bc, 0x7042, 0x70b8, 0xa065, 0x68c0, 0x705a, 0x2d00, + 0x704e, 0xad80, 0x0009, 0x7046, 0x007c, 0xa586, 0x8800, 0x00c0, + 0x3aaa, 0x7003, 0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084, + 0xfbef, 0x600a, 0x0078, 0x404a, 0x7047, 0x0000, 0xa282, 0x0006, + 0x0050, 0x3ab4, 0x1078, 0x290c, 0x2300, 0x0079, 0x3ab7, 0x3aba, + 0x3af1, 0x3b23, 0x2200, 0x0079, 0x3abd, 0x3ac3, 0x404a, 0x3ac5, + 0x3ac3, 0x3b5a, 0x3bc2, 0x1078, 0x290c, 0x7003, 0x0005, 0xb284, + 0x0300, 0x0040, 0x3acf, 0x2001, 0x94e0, 0x0078, 0x3ad1, 0x2001, + 0x9512, 0x2068, 0x704e, 0x157e, 0x20a9, 0x0032, 0x2003, 0x0000, + 0x8000, 0x00f0, 0x3ad6, 0x157f, 0xb284, 0x0300, 0x0040, 0x3ae4, + 0x6817, 0x0000, 0x0078, 0x3ae6, 0x6817, 0x8000, 0xad80, 0x0009, + 0x7046, 0x68b7, 0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x0078, + 0x4040, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3b02, 0x1078, 0x3d73, + 0x0078, 0x3afc, 0x1078, 0x44fb, 0x6008, 0xa084, 0xfbef, 0x600a, + 0x0078, 0x3b07, 0x7000, 0xa086, 0x0003, 0x0040, 0x3afa, 0x7003, + 0x0005, 0xb284, 0x0300, 0x0040, 0x3b11, 0x2001, 0x94e0, 0x0078, + 0x3b13, 0x2001, 0x9512, 0x2068, 0x704e, 0xad80, 0x0009, 0x7046, + 0x2200, 0x0079, 0x3b1b, 0x404a, 0x3b21, 0x3b21, 0x3b5a, 0x3b21, + 0x404a, 0x1078, 0x290c, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3b34, + 0x1078, 0x3d73, 0x0078, 0x3b2e, 0x1078, 0x44fb, 0x6008, 0xa084, + 0xfbef, 0x600a, 0x0078, 0x3b39, 0x7000, 0xa086, 0x0003, 0x0040, + 0x3b2c, 0x7003, 0x0005, 0xb284, 0x0300, 0x0040, 0x3b43, 0x2001, + 0x94e0, 0x0078, 0x3b45, 0x2001, 0x9512, 0x2068, 0x704e, 0xad80, + 0x0009, 0x7046, 0x2200, 0x0079, 0x3b4d, 0x3b55, 0x3b53, 0x3b53, + 0x3b55, 0x3b53, 0x3b55, 0x1078, 0x290c, 0x1078, 0x4064, 0x781b, + 0x0075, 0x007c, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3b6c, 0x70d4, + 0xc0b5, 0x70d6, 0x2c00, 0x70ba, 0x2d00, 0x70be, 0x0078, 0x3b71, + 0x1078, 0x44fb, 0x0078, 0x3b71, 0x7000, 0xa086, 0x0003, 0x0040, + 0x3b68, 0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, + 0x7ca8, 0xa484, 0x001f, 0xa215, 0x2069, 0x93c0, 0xb284, 0x0300, + 0x00c0, 0x3b85, 0xc2fd, 0x2069, 0x94d0, 0x2d04, 0x2d08, 0x715e, + 0xa06d, 0x0040, 0x3b92, 0x6814, 0xa206, 0x0040, 0x3bb2, 0x6800, + 0x0078, 0x3b86, 0x7003, 0x0005, 0xd2fc, 0x00c0, 0x3b9b, 0x2001, + 0x94e0, 0x0078, 0x3b9d, 0x2001, 0x9512, 0x2068, 0x704e, 0x157e, + 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x00f0, 0x3ba2, 0x157f, + 0xad80, 0x0009, 0x7046, 0x6a16, 0x68b7, 0x0700, 0x6823, 0x0800, + 0x6827, 0x0003, 0x6eb4, 0x7e5a, 0x6920, 0xa184, 0x0c00, 0x0040, + 0x3c3c, 0x681b, 0x0005, 0xc1ad, 0xc1d4, 0x6922, 0x1078, 0x4059, + 0x0078, 0x3c3c, 0x7200, 0xa286, 0x0002, 0x00c0, 0x3bd4, 0x70d4, + 0xc0b5, 0x70d6, 0x2c00, 0x70ba, 0x2d00, 0x70be, 0x0078, 0x3bd8, + 0x1078, 0x44fb, 0x0078, 0x3bd8, 0xa286, 0x0003, 0x0040, 0x3bd0, + 0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, + 0xa484, 0x001f, 0xa215, 0xb284, 0x0300, 0x00c0, 0x3be8, 0xc2fd, + 0x79a8, 0x79a8, 0xa18c, 0x00ff, 0x70cc, 0xa168, 0x2d04, 0x2d08, + 0x715e, 0xa06d, 0x0040, 0x3bfb, 0x6814, 0xa206, 0x0040, 0x3c24, + 0x6800, 0x0078, 0x3bef, 0x7003, 0x0005, 0xb284, 0x0300, 0x0040, + 0x3c05, 0x2001, 0x94e0, 0x0078, 0x3c07, 0x2001, 0x9512, 0x2068, 0x704e, 0x157e, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x00f0, - 0x39b4, 0x157f, 0xb284, 0x0300, 0x0040, 0x39c2, 0x6817, 0x0000, - 0x0078, 0x39c4, 0x6817, 0x8000, 0xad80, 0x0009, 0x7046, 0x68b7, - 0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x0078, 0x3e9d, 0x7000, - 0xa086, 0x0002, 0x00c0, 0x39e0, 0x1078, 0x3bd2, 0x0078, 0x39da, - 0x1078, 0x4326, 0x6008, 0xa084, 0xfbef, 0x600a, 0x0078, 0x39e5, - 0x7000, 0xa086, 0x0003, 0x0040, 0x39d8, 0x7003, 0x0005, 0xb284, - 0x0300, 0x0040, 0x39ef, 0x2001, 0x91e0, 0x0078, 0x39f1, 0x2001, - 0x9212, 0x2068, 0x704e, 0xad80, 0x0009, 0x7046, 0x2200, 0x0079, - 0x39f9, 0x3ea7, 0x39ff, 0x39ff, 0x3a38, 0x39ff, 0x3ea7, 0x1078, - 0x28ec, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3a12, 0x1078, 0x3bd2, - 0x0078, 0x3a0c, 0x1078, 0x4326, 0x6008, 0xa084, 0xfbef, 0x600a, - 0x0078, 0x3a17, 0x7000, 0xa086, 0x0003, 0x0040, 0x3a0a, 0x7003, - 0x0005, 0xb284, 0x0300, 0x0040, 0x3a21, 0x2001, 0x91e0, 0x0078, - 0x3a23, 0x2001, 0x9212, 0x2068, 0x704e, 0xad80, 0x0009, 0x7046, - 0x2200, 0x0079, 0x3a2b, 0x3a33, 0x3a31, 0x3a31, 0x3a33, 0x3a31, - 0x3a33, 0x1078, 0x28ec, 0x1078, 0x3ebe, 0x781b, 0x0075, 0x007c, - 0x7000, 0xa086, 0x0002, 0x00c0, 0x3a4a, 0x70d4, 0xc0b5, 0x70d6, - 0x2c00, 0x70ba, 0x2d00, 0x70be, 0x0078, 0x3a4f, 0x1078, 0x4326, - 0x0078, 0x3a4f, 0x7000, 0xa086, 0x0003, 0x0040, 0x3a46, 0x7003, - 0x0001, 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, - 0x001f, 0xa215, 0x2069, 0x90c0, 0xb284, 0x0300, 0x00c0, 0x3a63, - 0xc2fd, 0x2069, 0x91d0, 0x2d04, 0x2d08, 0x715e, 0xa06d, 0x0040, - 0x3a70, 0x6814, 0xa206, 0x0040, 0x3a90, 0x6800, 0x0078, 0x3a64, - 0x7003, 0x0005, 0xd2fc, 0x00c0, 0x3a79, 0x2001, 0x91e0, 0x0078, - 0x3a7b, 0x2001, 0x9212, 0x2068, 0x704e, 0x157e, 0x20a9, 0x0032, - 0x2003, 0x0000, 0x8000, 0x00f0, 0x3a80, 0x157f, 0xad80, 0x0009, - 0x7046, 0x6a16, 0x68b7, 0x0700, 0x6823, 0x0800, 0x6827, 0x0003, - 0x6eb4, 0x7e5a, 0x6820, 0xa084, 0x0c00, 0x0040, 0x3b10, 0x1078, - 0x3eb6, 0x0078, 0x3b10, 0x7200, 0xa286, 0x0002, 0x00c0, 0x3aad, - 0x70d4, 0xc0b5, 0x70d6, 0x2c00, 0x70ba, 0x2d00, 0x70be, 0x0078, - 0x3ab1, 0x1078, 0x4326, 0x0078, 0x3ab1, 0xa286, 0x0003, 0x0040, - 0x3aa9, 0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, - 0x7ca8, 0xa484, 0x001f, 0xa215, 0xb284, 0x0300, 0x00c0, 0x3ac1, - 0xc2fd, 0x79a8, 0x79a8, 0xa18c, 0x00ff, 0x70cc, 0xa168, 0x2d04, - 0x2d08, 0x715e, 0xa06d, 0x0040, 0x3ad4, 0x6814, 0xa206, 0x0040, - 0x3afd, 0x6800, 0x0078, 0x3ac8, 0x7003, 0x0005, 0xb284, 0x0300, - 0x0040, 0x3ade, 0x2001, 0x91e0, 0x0078, 0x3ae0, 0x2001, 0x9212, - 0x2068, 0x704e, 0x157e, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, - 0x00f0, 0x3ae5, 0x157f, 0xb284, 0x0300, 0x0040, 0x3af2, 0xc2fc, - 0x0078, 0x3af3, 0xc2fd, 0x6a16, 0xad80, 0x0009, 0x7046, 0x68b7, - 0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x6eb4, 0x6820, 0xa084, - 0x0c00, 0x0040, 0x3b10, 0xd0dc, 0x0040, 0x3b0a, 0x1078, 0x3eba, - 0x0078, 0x3b10, 0x1078, 0x3eb6, 0x707f, 0x0000, 0x0078, 0x3b10, - 0xa6ac, 0x0060, 0x0040, 0x3b4e, 0x6b98, 0x6c94, 0x69ac, 0x68b0, - 0xa105, 0x00c0, 0x3b33, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0xa6b4, - 0xb7ff, 0xa586, 0x0060, 0x0040, 0x3b4e, 0xc6ed, 0x7e5a, 0x2009, - 0x0076, 0xd69c, 0x0040, 0x3b2e, 0x2009, 0x0075, 0x791a, 0x1078, - 0x45f7, 0x0078, 0x3b57, 0x68b0, 0xa31a, 0x2100, 0xa423, 0x2400, - 0xa305, 0x0040, 0x3b4e, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0x68b0, - 0xc6f4, 0x7e5a, 0x2011, 0x0076, 0xd69c, 0x0040, 0x3b49, 0x2011, - 0x0075, 0x7a1a, 0x1078, 0x462d, 0x0078, 0x3b57, 0x7e5a, 0x2009, - 0x0076, 0xd69c, 0x0040, 0x3b56, 0x2009, 0x0075, 0x791a, 0x68c0, - 0x705a, 0x2d00, 0x704e, 0x68c4, 0x2060, 0x71d4, 0xd1b4, 0x00c0, - 0x2942, 0x2300, 0xa405, 0x0040, 0x2942, 0x70a4, 0xa086, 0x0001, - 0x00c0, 0x2989, 0x007c, 0x6020, 0xa005, 0x0040, 0x3b79, 0x8001, - 0x6022, 0x6008, 0xa085, 0x0008, 0x600a, 0x700f, 0x0100, 0x702c, - 0x6026, 0x007c, 0xa006, 0x1078, 0x4326, 0x6817, 0x0000, 0x681b, - 0x0001, 0x6823, 0x0040, 0x681f, 0x0100, 0x7000, 0xa084, 0x000f, - 0x0079, 0x3b8a, 0x2946, 0x3b94, 0x3b94, 0x3bb1, 0x3b9c, 0x2946, - 0x3b92, 0x3b92, 0x1078, 0x28ec, 0x1078, 0x3bbc, 0x1078, 0x3bb5, - 0x1078, 0x202a, 0x0078, 0x2946, 0x7064, 0x7067, 0x0000, 0x7083, - 0x0000, 0x0079, 0x3ba3, 0x3bad, 0x3bad, 0x3bab, 0x3bab, 0x3bab, - 0x3bad, 0x3bab, 0x3bad, 0x0079, 0x2e5c, 0x7067, 0x0000, 0x0078, - 0x2946, 0x681b, 0x0000, 0x0078, 0x35ae, 0x6800, 0xa005, 0x00c0, - 0x3bba, 0x6002, 0x6006, 0x007c, 0x6410, 0x84ff, 0x0040, 0x3bce, - 0x2009, 0x4a02, 0x2104, 0x8001, 0x200a, 0x8421, 0x6412, 0x00c0, - 0x3bce, 0x2021, 0x4a04, 0x2404, 0xc0a5, 0x2022, 0x6008, 0xc0a4, - 0x600a, 0x007c, 0x6018, 0xa005, 0x0040, 0x3bd8, 0x8001, 0x601a, - 0x007c, 0x1078, 0x4131, 0x681b, 0x0018, 0x0078, 0x3c1a, 0x1078, - 0x4131, 0x681b, 0x0019, 0x0078, 0x3c1a, 0x1078, 0x4131, 0x681b, - 0x001a, 0x0078, 0x3c1a, 0x1078, 0x4131, 0x681b, 0x0003, 0x0078, - 0x3c1a, 0x7774, 0x1078, 0x3fe1, 0x7178, 0xa18c, 0x00ff, 0x3210, - 0xa294, 0x0300, 0x0040, 0x3c00, 0xa1e8, 0x8fc0, 0x0078, 0x3c02, - 0xa1e8, 0x90d0, 0x2d04, 0x2d08, 0x2068, 0xa005, 0x00c0, 0x3c0a, - 0x0078, 0x2946, 0x6814, 0xc0fc, 0x7274, 0xc2fc, 0xa206, 0x0040, - 0x3c14, 0x6800, 0x0078, 0x3c03, 0x6800, 0x200a, 0x681b, 0x0005, - 0x707f, 0x0000, 0x1078, 0x3bbc, 0x6820, 0xd084, 0x00c0, 0x3c22, - 0x1078, 0x3bb5, 0x1078, 0x3bd2, 0x681f, 0x0000, 0x6823, 0x0020, - 0x1078, 0x202a, 0x0078, 0x2946, 0xa282, 0x0003, 0x00c0, 0x3e9d, - 0x7da8, 0xa5ac, 0x00ff, 0x7ea8, 0xa6b4, 0x00ff, 0x6920, 0xc1bd, - 0x6922, 0xd1c4, 0x0040, 0x3c86, 0xc1c4, 0x6922, 0xa6b4, 0x00ff, - 0x0040, 0x3c73, 0xa682, 0x000c, 0x0048, 0x3c4a, 0x0040, 0x3c4a, - 0x2031, 0x000c, 0x2500, 0xa086, 0x000a, 0x0040, 0x3c51, 0x852b, - 0x852b, 0x1078, 0x3f73, 0x0040, 0x3c59, 0x1078, 0x3d55, 0x0078, - 0x3c7c, 0x1078, 0x3f2e, 0x0c7e, 0x2960, 0x6004, 0xa084, 0xfff5, - 0x6006, 0x1078, 0x3d8a, 0x0c7f, 0x6920, 0xc1c5, 0x6922, 0x7e58, - 0xc695, 0x7e5a, 0xd6d4, 0x00c0, 0x3c70, 0x781b, 0x0061, 0x007c, - 0x781b, 0x0075, 0x007c, 0x0c7e, 0x2960, 0x6004, 0xa084, 0xfff5, - 0x6006, 0x1078, 0x3d8a, 0x0c7f, 0x7e58, 0xd6d4, 0x00c0, 0x3c83, - 0x781b, 0x0064, 0x007c, 0x781b, 0x0076, 0x007c, 0x0c7e, 0x7058, - 0x2060, 0x6100, 0xd1e4, 0x0040, 0x3ccf, 0x6208, 0x8217, 0xa294, - 0x00ff, 0xa282, 0x000c, 0x0048, 0x3c99, 0x0040, 0x3c99, 0x2011, - 0x000c, 0x2600, 0xa202, 0x00c8, 0x3c9e, 0x2230, 0x6208, 0xa294, - 0x00ff, 0x2001, 0x4a05, 0x2004, 0xd0e4, 0x00c0, 0x3cb3, 0x78ec, - 0xd0e4, 0x0040, 0x3cb3, 0xa282, 0x000a, 0x00c8, 0x3cb9, 0x2011, - 0x000a, 0x0078, 0x3cb9, 0xa282, 0x000c, 0x00c8, 0x3cb9, 0x2011, - 0x000c, 0x2200, 0xa502, 0x00c8, 0x3cbe, 0x2228, 0x1078, 0x3f32, - 0x2500, 0xa086, 0x000a, 0x0040, 0x3cc7, 0x852b, 0x852b, 0x1078, - 0x3f73, 0x0040, 0x3ccf, 0x1078, 0x3d55, 0x0078, 0x3cd3, 0x1078, - 0x3f2e, 0x1078, 0x3d8a, 0x7858, 0xc095, 0x785a, 0x0c7f, 0x781b, - 0x0075, 0x007c, 0x0c7e, 0x2960, 0x6000, 0xd0e4, 0x00c0, 0x3cf1, - 0x6010, 0xa084, 0x000f, 0x00c0, 0x3ceb, 0x6104, 0xa18c, 0xfff5, - 0x6106, 0x0c7f, 0x007c, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078, - 0x3d1c, 0x68a0, 0xd0cc, 0x00c0, 0x3ceb, 0x6208, 0xa294, 0x00ff, - 0x2001, 0x4a05, 0x2004, 0xd0e4, 0x00c0, 0x3d0a, 0x78ec, 0xd0e4, - 0x0040, 0x3d0a, 0xa282, 0x000a, 0x00c0, 0x3d0a, 0x2011, 0x000a, - 0x0078, 0x3d10, 0xa282, 0x000c, 0x00c8, 0x3d10, 0x2011, 0x000c, - 0x6308, 0x831f, 0xa39c, 0x00ff, 0xa382, 0x000c, 0x0048, 0x3d1c, - 0x0040, 0x3d1c, 0x2019, 0x000c, 0x78ab, 0x0001, 0x78ab, 0x0003, - 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xc0c5, - 0x6822, 0x70d4, 0xd0b4, 0x0040, 0x3d38, 0xc0b4, 0x70d6, 0x70b8, - 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, - 0x0c7f, 0x007c, 0x0c7e, 0x2960, 0x6104, 0xa18c, 0xfff5, 0x6106, - 0x2011, 0x0032, 0x2019, 0x0000, 0x0078, 0x3d46, 0x78ab, 0x0001, + 0x3c0c, 0x157f, 0xb284, 0x0300, 0x0040, 0x3c19, 0xc2fc, 0x0078, + 0x3c1a, 0xc2fd, 0x6a16, 0xad80, 0x0009, 0x7046, 0x68b7, 0x0700, + 0x6823, 0x0800, 0x6827, 0x0003, 0x6eb4, 0x6920, 0xa184, 0x0c00, + 0x0040, 0x3c3c, 0xd0dc, 0x0040, 0x3c31, 0x1078, 0x4060, 0x0078, + 0x3c3c, 0x681b, 0x0005, 0xc1ad, 0xc1d4, 0x6922, 0x1078, 0x4059, + 0x707f, 0x0000, 0x0078, 0x3c3c, 0xc6ec, 0xa6ac, 0x0060, 0x0040, + 0x3c90, 0x6b98, 0x6c94, 0x69ac, 0x68b0, 0xa105, 0x00c0, 0x3c69, + 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0xa586, 0x0060, 0x0040, 0x3c8e, + 0xd6f4, 0x00c0, 0x3c54, 0xc6ed, 0xa6b4, 0xb7ff, 0x7e5a, 0x2009, + 0x0076, 0xd69c, 0x0040, 0x3c61, 0x2009, 0x0075, 0x2019, 0x0000, + 0x2320, 0x791a, 0xd6ec, 0x0040, 0x3c99, 0x1078, 0x4834, 0x0078, + 0x3c99, 0x68b0, 0xa31a, 0x2100, 0xa423, 0x2400, 0xa305, 0x0040, + 0x3c90, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0x68b0, 0xd6f4, 0x00c0, + 0x3c7a, 0xc6ed, 0xc6f4, 0x7e5a, 0x2011, 0x0076, 0xd69c, 0x0040, + 0x3c86, 0x2011, 0x0075, 0x2019, 0x0000, 0x2320, 0x7a1a, 0xd6ec, + 0x0040, 0x3c99, 0x1078, 0x486c, 0x0078, 0x3c99, 0xa6b4, 0xb7ff, + 0x7e5a, 0x2009, 0x0076, 0xd69c, 0x0040, 0x3c98, 0x2009, 0x0075, + 0x791a, 0x68c0, 0x705a, 0x2d00, 0x704e, 0x68c4, 0x2060, 0x71d4, + 0x70d8, 0xa02d, 0x0040, 0x3cc1, 0xd1bc, 0x0040, 0x3cdb, 0x7a80, + 0xa294, 0x0f00, 0x70dc, 0xa206, 0x0040, 0x3cb2, 0x78e0, 0xa504, + 0x00c0, 0x3ce8, 0x70da, 0xc1bc, 0x71d6, 0x0078, 0x3ce8, 0x2031, + 0x0001, 0x852c, 0x0048, 0x3cc0, 0x8633, 0x8210, 0x0078, 0x3cb9, + 0x007c, 0x7de0, 0xa594, 0xff00, 0x0040, 0x3cce, 0x2011, 0x0008, + 0x852f, 0x1078, 0x3cb7, 0x8637, 0x0078, 0x3cd0, 0x1078, 0x3cb7, + 0x8217, 0x7880, 0xa084, 0x0f00, 0xa206, 0x0040, 0x3ce8, 0x72de, + 0x76da, 0x0078, 0x3ce8, 0x7a80, 0xa294, 0x0f00, 0x70dc, 0xa236, + 0x0040, 0x3cd8, 0x78e0, 0xa534, 0x0040, 0x3cd8, 0xc1bd, 0x71d6, + 0xd1b4, 0x00c0, 0x2962, 0x2300, 0xa405, 0x0040, 0x2962, 0x70a4, + 0xa086, 0x0001, 0x00c0, 0x29ac, 0x007c, 0x6020, 0xa005, 0x0040, + 0x3d03, 0x8001, 0x6022, 0x6008, 0xa085, 0x0008, 0x600a, 0x700f, + 0x0100, 0x702c, 0x6026, 0x007c, 0xa006, 0x1078, 0x44fb, 0x7000, + 0xa086, 0x0002, 0x0040, 0x3d11, 0x7064, 0xa086, 0x0005, 0x00c0, + 0x3d1b, 0x682b, 0x0000, 0x6817, 0x0000, 0x681b, 0x0001, 0x6823, + 0x0040, 0x681f, 0x0100, 0x7000, 0xa084, 0x000f, 0x0079, 0x3d20, + 0x2966, 0x3d30, 0x3d2a, 0x3d52, 0x3d3a, 0x2966, 0x3d28, 0x3d28, + 0x1078, 0x290c, 0x1078, 0x3d5d, 0x1078, 0x3d56, 0x0078, 0x3d36, + 0x1078, 0x3d5d, 0x705c, 0x2060, 0x6800, 0x6002, 0x1078, 0x2013, + 0x0078, 0x2966, 0x7064, 0x7067, 0x0000, 0x7083, 0x0000, 0x0079, + 0x3d41, 0x3d4e, 0x3d4e, 0x3d49, 0x3d49, 0x3d49, 0x3d4e, 0x3d49, + 0x3d4e, 0x77d4, 0xc7dd, 0x77d6, 0x0079, 0x2ed3, 0x7067, 0x0000, + 0x0078, 0x2966, 0x681b, 0x0000, 0x0078, 0x3653, 0x6800, 0xa005, + 0x00c0, 0x3d5b, 0x6002, 0x6006, 0x007c, 0x6410, 0x84ff, 0x0040, + 0x3d6f, 0x2009, 0x4d02, 0x2104, 0x8001, 0x200a, 0x8421, 0x6412, + 0x00c0, 0x3d6f, 0x2021, 0x4d04, 0x2404, 0xc0a5, 0x2022, 0x6008, + 0xc0a4, 0x600a, 0x007c, 0x6018, 0xa005, 0x0040, 0x3d79, 0x8001, + 0x601a, 0x007c, 0x1078, 0x42fe, 0x681b, 0x0018, 0x0078, 0x3dbc, + 0x1078, 0x42fe, 0x681b, 0x0019, 0x0078, 0x3dbc, 0x1078, 0x42fe, + 0x681b, 0x001a, 0x0078, 0x3dbc, 0x1078, 0x42fe, 0x681b, 0x0003, + 0x0078, 0x3dbc, 0x7774, 0x1078, 0x4187, 0x7178, 0xa18c, 0x00ff, + 0x3210, 0xa294, 0x0300, 0x0040, 0x3da1, 0xa1e8, 0x92c0, 0x0078, + 0x3da3, 0xa1e8, 0x93d0, 0x2d04, 0x2d08, 0x2068, 0xa005, 0x00c0, + 0x3dac, 0x707e, 0x0078, 0x2966, 0x6814, 0xc0fc, 0x7274, 0xc2fc, + 0xa206, 0x0040, 0x3db6, 0x6800, 0x0078, 0x3da4, 0x6800, 0x200a, + 0x681b, 0x0005, 0x707f, 0x0000, 0x1078, 0x3d5d, 0x6820, 0xd084, + 0x00c0, 0x3dc4, 0x1078, 0x3d56, 0x1078, 0x3d73, 0x681f, 0x0000, + 0x6823, 0x0020, 0x1078, 0x2013, 0x0078, 0x2966, 0xa282, 0x0003, + 0x00c0, 0x4040, 0x7da8, 0xa5ac, 0x00ff, 0x7ea8, 0xa6b4, 0x00ff, + 0x6920, 0xc1bd, 0x6922, 0xd1c4, 0x0040, 0x3e28, 0xc1c4, 0x6922, + 0xa6b4, 0x00ff, 0x0040, 0x3e15, 0xa682, 0x000c, 0x0048, 0x3dec, + 0x0040, 0x3dec, 0x2031, 0x000c, 0x2500, 0xa086, 0x000a, 0x0040, + 0x3df3, 0x852b, 0x852b, 0x1078, 0x4119, 0x0040, 0x3dfb, 0x1078, + 0x3ef7, 0x0078, 0x3e1e, 0x1078, 0x40d4, 0x0c7e, 0x2960, 0x6004, + 0xa084, 0xfff5, 0x6006, 0x1078, 0x3f2d, 0x0c7f, 0x6920, 0xc1c5, + 0x6922, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x00c0, 0x3e12, 0x781b, + 0x0061, 0x007c, 0x781b, 0x0075, 0x007c, 0x0c7e, 0x2960, 0x6004, + 0xa084, 0xfff5, 0x6006, 0x1078, 0x3f2d, 0x0c7f, 0x7e58, 0xd6d4, + 0x00c0, 0x3e25, 0x781b, 0x0064, 0x007c, 0x781b, 0x0076, 0x007c, + 0x0c7e, 0x7058, 0x2060, 0x6100, 0xd1e4, 0x0040, 0x3e71, 0x6208, + 0x8217, 0xa294, 0x00ff, 0xa282, 0x000c, 0x0048, 0x3e3b, 0x0040, + 0x3e3b, 0x2011, 0x000c, 0x2600, 0xa202, 0x00c8, 0x3e40, 0x2230, + 0x6208, 0xa294, 0x00ff, 0x2001, 0x4d05, 0x2004, 0xd0e4, 0x00c0, + 0x3e55, 0x78ec, 0xd0e4, 0x0040, 0x3e55, 0xa282, 0x000a, 0x00c8, + 0x3e5b, 0x2011, 0x000a, 0x0078, 0x3e5b, 0xa282, 0x000c, 0x00c8, + 0x3e5b, 0x2011, 0x000c, 0x2200, 0xa502, 0x00c8, 0x3e60, 0x2228, + 0x1078, 0x40d8, 0x2500, 0xa086, 0x000a, 0x0040, 0x3e69, 0x852b, + 0x852b, 0x1078, 0x4119, 0x0040, 0x3e71, 0x1078, 0x3ef7, 0x0078, + 0x3e75, 0x1078, 0x40d4, 0x1078, 0x3f2d, 0x7858, 0xc095, 0x785a, + 0x0c7f, 0x781b, 0x0075, 0x007c, 0x0c7e, 0x2960, 0x6000, 0xd0e4, + 0x00c0, 0x3e93, 0x6010, 0xa084, 0x000f, 0x00c0, 0x3e8d, 0x6104, + 0xa18c, 0xfff5, 0x6106, 0x0c7f, 0x007c, 0x2011, 0x0032, 0x2019, + 0x0000, 0x0078, 0x3ebe, 0x68a0, 0xd0cc, 0x00c0, 0x3e8d, 0x6208, + 0xa294, 0x00ff, 0x2001, 0x4d05, 0x2004, 0xd0e4, 0x00c0, 0x3eac, + 0x78ec, 0xd0e4, 0x0040, 0x3eac, 0xa282, 0x000b, 0x00c8, 0x3eac, + 0x2011, 0x000a, 0x0078, 0x3eb2, 0xa282, 0x000c, 0x00c8, 0x3eb2, + 0x2011, 0x000c, 0x6308, 0x831f, 0xa39c, 0x00ff, 0xa382, 0x000c, + 0x0048, 0x3ebe, 0x0040, 0x3ebe, 0x2019, 0x000c, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, - 0x6820, 0xc0c5, 0x6822, 0x0c7f, 0x007c, 0x0c7e, 0x7158, 0x2160, - 0x2018, 0xa08c, 0x0020, 0x0040, 0x3d5e, 0xc0ac, 0x2008, 0xa084, - 0xfff0, 0xa635, 0x7e86, 0x6018, 0x789a, 0x7eae, 0x6612, 0x78a4, - 0xa084, 0xfff0, 0xa18c, 0x000f, 0xa105, 0xa39c, 0x0020, 0x0040, - 0x3d73, 0xa085, 0x4000, 0xc0fc, 0xd0b4, 0x00c0, 0x3d78, 0xc0fd, - 0x78a6, 0x6016, 0x788a, 0xa6b4, 0x000f, 0x8637, 0x8204, 0x8004, - 0xa084, 0x00ff, 0xa605, 0x600e, 0x6004, 0xa084, 0xfff5, 0x6006, - 0x0c7f, 0x007c, 0x0c7e, 0x7058, 0x2060, 0x6018, 0x789a, 0x78a4, - 0xa084, 0xfff0, 0x78a6, 0x6012, 0x7884, 0xa084, 0xfff0, 0x7886, - 0x600c, 0xa084, 0x00ff, 0x600e, 0x0c7f, 0x007c, 0xa282, 0x0002, - 0x00c0, 0x3e9d, 0x7aa8, 0x6920, 0xc1bd, 0x6922, 0xd1cc, 0x0040, - 0x3dd9, 0xc1cc, 0x6922, 0xa294, 0x00ff, 0xa282, 0x0002, 0x00c8, - 0x3e9d, 0x1078, 0x3e2a, 0x1078, 0x3d8a, 0xa980, 0x0001, 0x200c, - 0x1078, 0x3fdd, 0x1078, 0x3cda, 0x88ff, 0x0040, 0x3dcf, 0x789b, - 0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x00c0, - 0x3dcc, 0x781b, 0x0061, 0x007c, 0x781b, 0x0075, 0x007c, 0x7e58, - 0xd6d4, 0x00c0, 0x3dd6, 0x781b, 0x0064, 0x007c, 0x781b, 0x0076, - 0x007c, 0xa282, 0x0002, 0x00c8, 0x3de1, 0xa284, 0x0001, 0x0040, - 0x3dea, 0x7158, 0xa188, 0x0000, 0x210c, 0xd1ec, 0x00c0, 0x3dea, - 0x2011, 0x0000, 0x1078, 0x3f0f, 0x1078, 0x3e2a, 0x1078, 0x3d8a, - 0x7858, 0xc095, 0x785a, 0x781b, 0x0075, 0x007c, 0x0c7e, 0x027e, - 0x2960, 0x6000, 0x2011, 0x0001, 0xd0ec, 0x00c0, 0x3e0b, 0x6014, - 0xa084, 0x0040, 0x00c0, 0x3e09, 0xc1a4, 0x6106, 0xa006, 0x0078, - 0x3e27, 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, - 0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x70d4, 0xd0b4, 0x0040, 0x3e23, - 0xc0b4, 0x70d6, 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, - 0x6018, 0x8001, 0x601a, 0x6820, 0xa085, 0x0200, 0x6822, 0x027f, - 0x0c7f, 0x007c, 0x0c7e, 0x7058, 0x2060, 0x82ff, 0x0040, 0x3e32, - 0x2011, 0x0040, 0x6018, 0xa080, 0x0002, 0x789a, 0x78a4, 0xa084, - 0xffbf, 0xa205, 0xc0fc, 0xd0b4, 0x00c0, 0x3e3f, 0xc0fd, 0x78a6, - 0x6016, 0x788a, 0x6004, 0xc0a4, 0x6006, 0x0c7f, 0x007c, 0x007e, - 0x7000, 0xa086, 0x0003, 0x0040, 0x3e50, 0x007f, 0x0078, 0x3e53, - 0x007f, 0x0078, 0x3e9a, 0xd6ac, 0x0040, 0x3e9a, 0x7888, 0xa084, - 0x0040, 0x0040, 0x3e9a, 0x7bb8, 0xa384, 0x003f, 0x831b, 0x00c8, - 0x3e62, 0x8000, 0xa005, 0x0040, 0x3e77, 0x831b, 0x00c8, 0x3e6b, - 0x8001, 0x0040, 0x3e97, 0xd6f4, 0x0040, 0x3e77, 0x78b8, 0x801b, - 0x00c8, 0x3e73, 0x8000, 0xa084, 0x003f, 0x00c0, 0x3e97, 0xc6f4, - 0x7e5a, 0x79d8, 0x7adc, 0x2001, 0x0001, 0xa108, 0x00c8, 0x3e82, - 0xa291, 0x0000, 0x79d2, 0x79da, 0x7ad6, 0x7ade, 0x1078, 0x46e5, - 0x781b, 0x0073, 0xb284, 0x0300, 0x0040, 0x3e92, 0x2001, 0x0000, - 0x0078, 0x3e94, 0x2001, 0x0001, 0x1078, 0x4585, 0x007c, 0x781b, - 0x0073, 0x007c, 0x781b, 0x0076, 0x007c, 0x1078, 0x3ec2, 0x781b, - 0x0075, 0x007c, 0x1078, 0x3eae, 0x781b, 0x0075, 0x007c, 0x6827, - 0x0002, 0x1078, 0x3eb6, 0x781b, 0x0075, 0x007c, 0x2001, 0x0005, - 0x0078, 0x3ec4, 0x2001, 0x000c, 0x0078, 0x3ec4, 0x2001, 0x0006, - 0x0078, 0x3ec4, 0x2001, 0x000d, 0x0078, 0x3ec4, 0x2001, 0x0009, - 0x0078, 0x3ec4, 0x2001, 0x0007, 0x789b, 0x007e, 0x78aa, 0xc69d, - 0x7e5a, 0x70d4, 0xd0b4, 0x0040, 0x3eda, 0xc0b4, 0x70d6, 0x0c7e, - 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, - 0x601a, 0x0c7f, 0x007c, 0x077e, 0x873f, 0xa7bc, 0x000f, 0x873b, - 0x873b, 0x8703, 0x017e, 0xb28c, 0x0300, 0x0040, 0x3eeb, 0xa0e0, - 0x4ec0, 0x0078, 0x3eed, 0xa0e0, 0x4f40, 0x017f, 0xa7b8, 0x0020, - 0x7f9a, 0x79a4, 0xa184, 0x000f, 0x0040, 0x3efd, 0xa184, 0xfff0, - 0x78a6, 0x6012, 0x6004, 0xc09d, 0x6006, 0x8738, 0x8738, 0x7f9a, - 0x79a4, 0xa184, 0x0040, 0x0040, 0x3f0d, 0xa184, 0xffbf, 0xc0fd, - 0x78a6, 0x6016, 0x6004, 0xc0a5, 0x6006, 0x077f, 0x007c, 0x789b, - 0x0010, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, - 0x789b, 0x0060, 0x78ab, 0x0004, 0x70d4, 0xd0b4, 0x0040, 0x3f2d, - 0xc0b4, 0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, - 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f, 0x007c, 0x2031, 0x0000, - 0x2029, 0x0032, 0x789b, 0x0010, 0x78ab, 0x0001, 0x78ab, 0x0003, - 0x78ab, 0x0001, 0x7daa, 0x7eaa, 0x789b, 0x0060, 0x78ab, 0x0005, - 0x70d4, 0xd0b4, 0x0040, 0x3f51, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8, - 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, - 0x0c7f, 0x007c, 0x157e, 0x8007, 0xa084, 0x00ff, 0x8003, 0x8003, - 0xa080, 0x0020, 0x789a, 0x79a4, 0xa18c, 0xfff0, 0x2021, 0x3fc6, - 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011, 0x0032, 0x2404, 0xa084, - 0xfff0, 0xa106, 0x0040, 0x3f71, 0x8420, 0x2300, 0xa210, 0x00f0, - 0x3f66, 0x157f, 0x007c, 0x157e, 0x2001, 0x4a05, 0x2004, 0xd0e4, - 0x00c0, 0x3fa4, 0x2021, 0x3fd4, 0x20a9, 0x0009, 0x2011, 0x0028, - 0xa582, 0x0019, 0x0040, 0x3fba, 0x0048, 0x3fba, 0x8420, 0x95a9, - 0x2011, 0x0032, 0xa582, 0x0032, 0x0040, 0x3fba, 0x0048, 0x3fba, - 0x8420, 0x95a9, 0x2019, 0x000a, 0x2011, 0x0064, 0x2200, 0xa502, - 0x0040, 0x3fba, 0x0048, 0x3fba, 0x8420, 0x2300, 0xa210, 0x00f0, - 0x3f96, 0x157f, 0x0078, 0x3fb8, 0x2021, 0x3fc6, 0x2019, 0x0011, - 0x20a9, 0x000e, 0x2011, 0x0032, 0x2200, 0xa502, 0x0040, 0x3fba, - 0x0048, 0x3fba, 0x8420, 0x2300, 0xa210, 0x00f0, 0x3fac, 0x157f, - 0xa006, 0x007c, 0x157f, 0xa582, 0x0064, 0x00c8, 0x3fc3, 0x7808, - 0xa085, 0x0070, 0x780a, 0x2404, 0xa005, 0x007c, 0x1209, 0x3002, - 0x3202, 0x4203, 0x4403, 0x5404, 0x5604, 0x6605, 0x6805, 0x7806, - 0x7a06, 0x0c07, 0x0c07, 0x0e07, 0x10e1, 0x330a, 0x5805, 0x5a05, - 0x6a06, 0x6c06, 0x7c07, 0x7e07, 0x0e00, 0x789b, 0x0010, 0xa046, - 0x007c, 0xa784, 0x0f00, 0x800b, 0xa784, 0x001f, 0x8003, 0x8003, - 0x8003, 0x8003, 0xa105, 0xd7fc, 0x0040, 0x3ff2, 0xa0e0, 0x6fc0, - 0x0078, 0x3ff4, 0xa0e0, 0x4fc0, 0x007c, 0x0e7e, 0x0f7e, 0xd084, - 0x0040, 0x4002, 0x2079, 0x0100, 0x2009, 0x4a80, 0x2071, 0x4a80, - 0x0078, 0x4014, 0x2009, 0x4a40, 0x007e, 0x2001, 0x4a04, 0x2004, - 0xd0ec, 0x007f, 0x0040, 0x4010, 0x2079, 0x0100, 0x0078, 0x4014, - 0x2079, 0x0200, 0x2071, 0x4a40, 0x2091, 0x8000, 0x2104, 0xa084, - 0x000f, 0x0079, 0x401b, 0x405d, 0x4025, 0x4025, 0x4025, 0x4025, - 0x4025, 0x4023, 0x4023, 0x1078, 0x28ec, 0x784b, 0x0004, 0x7848, - 0xa084, 0x0004, 0x00c0, 0x4027, 0x784b, 0x0008, 0x7848, 0xa084, - 0x0008, 0x00c0, 0x402e, 0x68b4, 0xc0f5, 0x68b6, 0x7858, 0xc0f5, - 0x785a, 0x7830, 0xd0bc, 0x00c0, 0x405d, 0x007e, 0x2001, 0x4a04, - 0x2004, 0xd0ec, 0x007f, 0x0040, 0x4049, 0xb284, 0x0300, 0x0078, - 0x404b, 0xb284, 0x0400, 0x0040, 0x4051, 0x0018, 0x405d, 0x0078, - 0x4053, 0x0028, 0x405d, 0x681c, 0xd0ac, 0x00c0, 0x405b, 0x1078, - 0x40d5, 0x0078, 0x405d, 0x781b, 0x00f0, 0x2091, 0x8001, 0x0f7f, - 0x0e7f, 0x007c, 0x0c7e, 0x2001, 0x4a01, 0x2004, 0xd0ac, 0x00c0, - 0x40c7, 0x6814, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, - 0xb28c, 0x0300, 0x0040, 0x4078, 0xa0e0, 0x4ec0, 0x0078, 0x407a, - 0xa0e0, 0x4f40, 0x6004, 0xa084, 0x000a, 0x00c0, 0x40c7, 0x6108, - 0xa194, 0xff00, 0x0040, 0x40c7, 0xa18c, 0x00ff, 0x2001, 0x000a, - 0xa106, 0x0040, 0x40a6, 0x2001, 0x000c, 0xa106, 0x0040, 0x40aa, - 0x2001, 0x0012, 0xa106, 0x0040, 0x40ae, 0x2001, 0x0014, 0xa106, - 0x0040, 0x40b2, 0x2001, 0x0019, 0xa106, 0x0040, 0x40b6, 0x2001, - 0x0032, 0xa106, 0x0040, 0x40ba, 0x0078, 0x40be, 0x2009, 0x000c, - 0x0078, 0x40c0, 0x2009, 0x0012, 0x0078, 0x40c0, 0x2009, 0x0014, - 0x0078, 0x40c0, 0x2009, 0x0019, 0x0078, 0x40c0, 0x2009, 0x0020, - 0x0078, 0x40c0, 0x2009, 0x003f, 0x0078, 0x40c0, 0x2011, 0x0000, - 0x2100, 0xa205, 0x600a, 0x6004, 0xa085, 0x0002, 0x6006, 0x0c7f, - 0x007c, 0x781b, 0x0076, 0x007c, 0x781b, 0x0075, 0x007c, 0x781b, - 0x0064, 0x007c, 0x781b, 0x0061, 0x007c, 0x2009, 0x4a19, 0x210c, - 0xa186, 0x0000, 0x0040, 0x40e7, 0xa186, 0x0001, 0x0040, 0x40ea, - 0x701f, 0x000b, 0x7067, 0x0001, 0x781b, 0x0047, 0x007c, 0x781b, - 0x00e7, 0x007c, 0x701f, 0x000a, 0x007c, 0x2009, 0x4a19, 0x210c, - 0xa186, 0x0000, 0x0040, 0x4102, 0xa186, 0x0001, 0x0040, 0x40ff, - 0x701f, 0x000b, 0x7067, 0x0001, 0x781b, 0x0047, 0x007c, 0x701f, - 0x000a, 0x007c, 0x781b, 0x00e6, 0x007c, 0x781b, 0x00f0, 0x007c, - 0x781b, 0x00ef, 0x007c, 0x781b, 0x00c0, 0x007c, 0x781b, 0x00bf, - 0x007c, 0x6818, 0xd0fc, 0x0040, 0x4117, 0x681b, 0x001d, 0x7067, - 0x0001, 0x781b, 0x0047, 0x007c, 0x7830, 0xa084, 0x00c0, 0x00c0, - 0x4130, 0x7808, 0xc08c, 0x780a, 0x0005, 0x0005, 0x0005, 0x0005, - 0x78ec, 0xa084, 0x0021, 0x0040, 0x4130, 0x7808, 0xc08d, 0x780a, - 0x007c, 0x7808, 0xc08d, 0x780a, 0x007c, 0x7830, 0xa084, 0x0040, - 0x00c0, 0x4135, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x0040, 0x4144, - 0xb284, 0x0300, 0x0078, 0x4146, 0xb284, 0x0400, 0x0040, 0x414c, - 0x0098, 0x4150, 0x0078, 0x414e, 0x00a8, 0x4150, 0x78ac, 0x007c, - 0x7808, 0xa084, 0xfffd, 0x780a, 0x0005, 0x0005, 0x0005, 0x0005, - 0x78ec, 0xa084, 0x0021, 0x0040, 0x4173, 0x007e, 0x2001, 0x4a04, - 0x2004, 0xd0ec, 0x007f, 0x0040, 0x4169, 0xb284, 0x0300, 0x0078, - 0x416b, 0xb284, 0x0400, 0x0040, 0x4171, 0x0098, 0x416d, 0x0078, - 0x4173, 0x00a8, 0x4171, 0x78ac, 0x007e, 0x7808, 0xa085, 0x0002, - 0x780a, 0x007f, 0x007c, 0xa784, 0x0001, 0x00c0, 0x360e, 0xa784, - 0x0070, 0x0040, 0x418b, 0x0c7e, 0x2d60, 0x2f68, 0x1078, 0x2881, - 0x2d78, 0x2c68, 0x0c7f, 0xa784, 0x0008, 0x0040, 0x4198, 0x784b, - 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x2946, 0x0078, 0x40c9, - 0xa784, 0x0004, 0x0040, 0x41c7, 0x78b8, 0xa084, 0x4001, 0x0040, - 0x41c7, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x2946, - 0x78e4, 0xa084, 0x0007, 0xa086, 0x0001, 0x00c0, 0x41c7, 0x78c0, - 0xa685, 0x4800, 0x2030, 0x7e5a, 0x781b, 0x00f0, 0x007c, 0x784b, - 0x0008, 0x6818, 0xd0fc, 0x0040, 0x41c4, 0x681b, 0x0015, 0xd6f4, - 0x0040, 0x41c4, 0x681b, 0x0007, 0x1078, 0x40d5, 0x007c, 0x681b, - 0x0003, 0x7858, 0xa084, 0x3f00, 0x681e, 0x682f, 0x0000, 0x6833, - 0x0000, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x2f84, - 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x41e4, - 0xb284, 0x0300, 0x0078, 0x41e6, 0xb284, 0x0400, 0x0040, 0x41ec, - 0x0018, 0x2942, 0x0078, 0x41ee, 0x0028, 0x2942, 0x0078, 0x3ea2, - 0x6b14, 0x8307, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xd3fc, - 0x0040, 0x41fe, 0xa080, 0x4f40, 0x0078, 0x4200, 0xa080, 0x4ec0, - 0x2060, 0x2048, 0x705a, 0x2a60, 0x007c, 0x0020, 0x0020, 0x0000, - 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, - 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, - 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, - 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0062, - 0x0009, 0x0014, 0x0014, 0x9848, 0x0014, 0x0014, 0x9906, 0x98f4, - 0x0014, 0x0014, 0x0080, 0x00f1, 0x0100, 0x0402, 0x2008, 0xf880, - 0x0018, 0xa20a, 0x0014, 0x300b, 0xa20c, 0x0014, 0x2500, 0x0013, - 0x2500, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, - 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0xa200, - 0x3806, 0x8839, 0x20c4, 0x0864, 0xa850, 0x3008, 0x28c1, 0x9d0d, - 0xa201, 0x300c, 0x2847, 0x8161, 0x846a, 0x8000, 0x84a4, 0x1856, - 0x883a, 0xa808, 0x28e2, 0x9cc2, 0xa8f3, 0x0864, 0xa83e, 0x300c, - 0xa801, 0x3008, 0x28e1, 0x9cc2, 0x2021, 0xa81b, 0xa205, 0x870c, - 0xd8de, 0x64a0, 0x6de0, 0x6fc0, 0x63a4, 0x6c80, 0x0212, 0xa205, - 0x883d, 0x9d25, 0x882b, 0x1814, 0x883b, 0x9d2b, 0x883b, 0x7027, - 0x85f2, 0xa737, 0xa532, 0xf003, 0x8576, 0x8677, 0xa812, 0x883e, - 0xa810, 0x280c, 0xa204, 0x64c0, 0x6de0, 0x67a0, 0x6fc0, 0x9d25, - 0x1814, 0x9d2b, 0x883b, 0x7023, 0x8576, 0x8677, 0xa802, 0x7861, - 0x883e, 0x206b, 0x28c1, 0x9d0d, 0x2044, 0x2103, 0x20a2, 0x2081, - 0xa8c9, 0xa207, 0x2901, 0xa80a, 0x0014, 0xa203, 0x8000, 0x85a4, - 0x1872, 0x879a, 0x883c, 0x1fe2, 0xf601, 0xa208, 0x856e, 0x866f, - 0x7161, 0x0014, 0x0704, 0x3008, 0x9cc2, 0x0014, 0xa202, 0x8000, - 0x85a4, 0x3009, 0x84a8, 0x19e2, 0xf844, 0x856e, 0x883f, 0x08e6, - 0xa8f5, 0xf861, 0xa8ea, 0xf801, 0x0014, 0xf881, 0x0016, 0x85b2, - 0x80f0, 0x9532, 0xfaa2, 0x1de2, 0x0014, 0x8532, 0xf221, 0x0014, - 0x1de2, 0x84a8, 0xd6e0, 0x1fe6, 0x0014, 0x3008, 0x8000, 0x284a, - 0x1011, 0xa8fc, 0x3008, 0x9d25, 0x8000, 0xa000, 0x2802, 0x1011, - 0xa8fd, 0x9d2b, 0xa887, 0x3008, 0x9d25, 0x283b, 0x1011, 0xa8fd, - 0xa209, 0x0017, 0x300c, 0x8000, 0x85a4, 0x1de2, 0xdac1, 0x0014, - 0x0210, 0xa801, 0x0014, 0x26e0, 0x873a, 0xfaa3, 0x19f2, 0x26e0, - 0x18f2, 0x0014, 0xa20b, 0x0014, 0xa20d, 0x3806, 0x0210, 0x9d17, - 0x0704, 0xa206, 0x6865, 0x817e, 0x842a, 0x1dc1, 0x8823, 0x0016, - 0x6042, 0x8008, 0xa8fa, 0x8000, 0x84a4, 0x8160, 0x842a, 0xf021, - 0x3008, 0x84a8, 0x11d6, 0x7042, 0x20dd, 0x0011, 0x20d4, 0x8822, - 0x0016, 0x7944, 0x8421, 0xa020, 0xa532, 0x84a1, 0x0016, 0x7944, - 0x8421, 0xa0df, 0x9532, 0x84a1, 0x0016, 0x0000, 0x127e, 0x70d4, - 0xa084, 0x4600, 0x8004, 0x2090, 0x7204, 0x7008, 0xc09c, 0xa205, - 0x00c0, 0x4342, 0x720c, 0x82ff, 0x0040, 0x433d, 0x8aff, 0x00c0, - 0x4342, 0x7200, 0xd284, 0x00c0, 0x4342, 0x7003, 0x0008, 0x127f, - 0x2000, 0x007c, 0x7000, 0xa084, 0x0003, 0x7002, 0xc69c, 0xd084, - 0x0040, 0x4374, 0x2001, 0x4a05, 0x2004, 0xd0ec, 0x00c0, 0x43a5, - 0xd0e4, 0x00c0, 0x435a, 0x2001, 0x04fd, 0x2004, 0xa086, 0x0003, - 0x0040, 0x43a5, 0x0e7e, 0x2071, 0x0010, 0x2009, 0x0007, 0x7008, - 0xa084, 0x3000, 0x00c0, 0x435d, 0x8109, 0x00c0, 0x435f, 0x0e7f, - 0x2009, 0x0007, 0x7008, 0xa084, 0x3000, 0x00c0, 0x435a, 0x8109, - 0x00c0, 0x436a, 0x0078, 0x43a5, 0x7108, 0xd1fc, 0x0040, 0x437f, - 0x1078, 0x44ba, 0x8aff, 0x0040, 0x432c, 0x0078, 0x4374, 0x700c, - 0xa08c, 0x03ff, 0x0040, 0x43aa, 0x7004, 0xd084, 0x0040, 0x439c, - 0x7014, 0xa005, 0x00c0, 0x4398, 0x7010, 0x7310, 0xa306, 0x00c0, - 0x438c, 0x2300, 0xa005, 0x0040, 0x439c, 0xa102, 0x00c8, 0x4374, - 0x7007, 0x0010, 0x0078, 0x43a5, 0x8aff, 0x0040, 0x43aa, 0x1078, - 0x46a3, 0x00c0, 0x439f, 0x0040, 0x4374, 0x1078, 0x4443, 0x127f, - 0x2000, 0x007c, 0x7204, 0x7108, 0xc19c, 0x8103, 0x00c8, 0x43b9, - 0x1078, 0x44ba, 0x0078, 0x43aa, 0x7003, 0x0008, 0x127f, 0x2000, - 0x007c, 0xa205, 0x00c0, 0x43a5, 0x7003, 0x0008, 0x127f, 0x2000, - 0x007c, 0x6428, 0x84ff, 0x0040, 0x43ed, 0x2c70, 0x7004, 0xa0bc, - 0x000f, 0xa7b8, 0x43fd, 0x273c, 0x87fb, 0x00c0, 0x43db, 0x0048, - 0x43d3, 0x1078, 0x28ec, 0x609c, 0xa075, 0x0040, 0x43ed, 0x0078, - 0x43c6, 0x2039, 0x43f2, 0x2704, 0xae68, 0x6808, 0xa630, 0x680c, - 0xa529, 0x8421, 0x0040, 0x43ed, 0x8738, 0x2704, 0xa005, 0x00c0, - 0x43dc, 0x709c, 0xa075, 0x00c0, 0x43c6, 0x007c, 0x0000, 0x0005, - 0x0009, 0x000d, 0x0011, 0x0015, 0x0019, 0x001d, 0x0000, 0x0003, - 0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0000, 0x43f2, 0x43ef, - 0x0000, 0x0000, 0x8000, 0x0000, 0x43f2, 0x0000, 0x43fa, 0x43f7, - 0x0000, 0x0000, 0x0000, 0x0000, 0x43fa, 0x0000, 0x43f5, 0x43f5, - 0x0000, 0x0000, 0x8000, 0x0000, 0x43f5, 0x0000, 0x43fb, 0x43fb, - 0x0000, 0x0000, 0x0000, 0x0000, 0x43fb, 0x2079, 0x4a00, 0x2071, - 0x0010, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0001, 0x7810, - 0xd0ec, 0x0040, 0x4431, 0x2009, 0x0001, 0x2071, 0x0020, 0x0078, - 0x4435, 0x2009, 0x0002, 0x2071, 0x0050, 0x7007, 0x000a, 0x7007, - 0x0002, 0x7003, 0x0000, 0x8109, 0x0040, 0x4442, 0x2071, 0x0020, - 0x0078, 0x4435, 0x007c, 0x7004, 0x8004, 0x00c8, 0x44a6, 0x7007, - 0x0012, 0x2019, 0x0000, 0x7108, 0x7008, 0xa106, 0x00c0, 0x444b, - 0xa184, 0x01e0, 0x0040, 0x4456, 0x1078, 0x28ec, 0x7810, 0xd0ec, - 0x0040, 0x4470, 0x2001, 0x04fd, 0x2004, 0xa086, 0x0003, 0x00c0, - 0x4474, 0xa184, 0x4000, 0x0040, 0x4478, 0xa382, 0x0003, 0x00c8, - 0x4478, 0xa184, 0x0004, 0x0040, 0x444b, 0x8318, 0x0078, 0x444b, - 0x7814, 0xd0ec, 0x00c0, 0x4478, 0xa184, 0x4000, 0x00c0, 0x444b, - 0xa19c, 0x300c, 0xa386, 0x2004, 0x0040, 0x4486, 0xa386, 0x0008, - 0x0040, 0x4491, 0xa386, 0x200c, 0x00c0, 0x444b, 0x7200, 0x8204, - 0x0048, 0x4491, 0x730c, 0xa384, 0x03ff, 0x0040, 0x4491, 0x1078, - 0x28ec, 0x7007, 0x0012, 0x7000, 0xd084, 0x00c0, 0x44a6, 0x7008, - 0xa084, 0x01e0, 0x00c0, 0x44a6, 0x7310, 0x7014, 0xa305, 0x0040, - 0x44a6, 0x710c, 0xa184, 0x03ff, 0x00c0, 0x4443, 0x7007, 0x0012, - 0x7007, 0x0008, 0x7004, 0xd09c, 0x00c0, 0x44aa, 0x7007, 0x0012, - 0x7108, 0x8103, 0x0048, 0x44ae, 0x7003, 0x0008, 0x007c, 0x7108, - 0x0078, 0x44ba, 0xa184, 0x01e0, 0x00c0, 0x44ee, 0x7108, 0xa184, - 0x01e0, 0x00c0, 0x44ee, 0xa184, 0x0007, 0x0079, 0x44c7, 0x44d1, - 0x44e1, 0x44cf, 0x44e1, 0x44cf, 0x4533, 0x44cf, 0x4531, 0x1078, - 0x28ec, 0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x8aff, 0x00c0, - 0x44dc, 0x2049, 0x0000, 0x007c, 0x1078, 0x46a3, 0x00c0, 0x44dc, - 0x007c, 0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x8aff, 0x0040, - 0x44ed, 0x1078, 0x46a3, 0x00c0, 0x44e9, 0x007c, 0x7007, 0x0012, - 0x7108, 0x00e0, 0x44f1, 0x2091, 0x6000, 0x00e0, 0x44f5, 0x2091, - 0x6000, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xd09c, 0x00c0, - 0x44fd, 0x7007, 0x0012, 0x7108, 0xd1fc, 0x00c0, 0x4501, 0x7003, - 0x0000, 0x7000, 0xa005, 0x00c0, 0x4515, 0x7004, 0xa005, 0x00c0, - 0x4515, 0x700c, 0xa005, 0x0040, 0x4517, 0x0078, 0x44f9, 0x2049, - 0x0000, 0xb284, 0x0100, 0x0040, 0x4521, 0x2001, 0x0000, 0x0078, - 0x4523, 0x2001, 0x0001, 0x1078, 0x3ff5, 0x6818, 0xa084, 0x8000, - 0x0040, 0x452c, 0x681b, 0x0002, 0x007c, 0x1078, 0x28ec, 0x1078, - 0x28ec, 0x1078, 0x4570, 0x7210, 0x7114, 0x700c, 0xa09c, 0x03ff, - 0x2800, 0xa300, 0xa211, 0xa189, 0x0000, 0x1078, 0x4570, 0x2704, - 0x2c58, 0xac60, 0x6308, 0x2200, 0xa322, 0x630c, 0x2100, 0xa31b, - 0x2400, 0xa305, 0x0040, 0x4556, 0x00c8, 0x4556, 0x8412, 0x8210, - 0x830a, 0xa189, 0x0000, 0x2b60, 0x0078, 0x453d, 0x2b60, 0x8a07, - 0x007e, 0x6004, 0xa084, 0x0008, 0x0040, 0x4562, 0xa7ba, 0x43f7, - 0x0078, 0x4564, 0xa7ba, 0x43ef, 0x007f, 0xa73d, 0x2c00, 0x6886, - 0x6f8a, 0x6c92, 0x6b8e, 0x7007, 0x0012, 0x1078, 0x4443, 0x007c, - 0x8a50, 0x8739, 0x2704, 0xa004, 0x00c0, 0x4584, 0x6000, 0xa064, - 0x00c0, 0x457b, 0x2d60, 0x6004, 0xa084, 0x000f, 0xa080, 0x440d, - 0x203c, 0x87fb, 0x1040, 0x28ec, 0x007c, 0x127e, 0x0d7e, 0x70d4, - 0xa084, 0x4600, 0x8004, 0x2090, 0x0d7f, 0x6884, 0x2060, 0x6888, - 0x6b8c, 0x6c90, 0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff, 0x007e, - 0x6804, 0xa084, 0x0008, 0x007f, 0x0040, 0x45a2, 0xa0b8, 0x43f7, - 0x0078, 0x45a4, 0xa0b8, 0x43ef, 0xb284, 0x0100, 0x0040, 0x45ab, - 0x7e20, 0x0078, 0x45ac, 0x7e24, 0xa6b5, 0x000c, 0x681c, 0xd0b4, - 0x0040, 0x45b3, 0xc685, 0x2400, 0xa305, 0x0040, 0x45dd, 0x2c58, - 0x2704, 0x6104, 0xac60, 0x6000, 0xa400, 0x701a, 0x6004, 0xa301, - 0x701e, 0xa184, 0x0008, 0x0040, 0x45cd, 0x6010, 0xa081, 0x0000, - 0x7022, 0x6014, 0xa081, 0x0000, 0x7026, 0x6208, 0x2400, 0xa202, - 0x7012, 0x620c, 0x2300, 0xa203, 0x7016, 0x7602, 0x7007, 0x0001, - 0x2b60, 0x1078, 0x46c6, 0x0078, 0x45df, 0x1078, 0x46a3, 0x00c0, - 0x45dd, 0x127f, 0x2000, 0x007c, 0x127e, 0x0d7e, 0x70d4, 0xa084, - 0x4600, 0x8004, 0x2090, 0x0d7f, 0x7007, 0x0004, 0x7004, 0xd094, - 0x00c0, 0x45ee, 0x7003, 0x0008, 0x127f, 0x2000, 0x007c, 0x127e, - 0x0d7e, 0x70d4, 0xa084, 0x4600, 0x8004, 0x2090, 0x0d7f, 0x7e20, - 0xb284, 0x0100, 0x00c0, 0x4605, 0x7e24, 0xa6b5, 0x000c, 0x681c, - 0xd0ac, 0x00c0, 0x4610, 0xc685, 0x7003, 0x0000, 0x7007, 0x0004, - 0x6828, 0x2050, 0x2d60, 0x6004, 0xa0bc, 0x000f, 0xa7b8, 0x43fd, - 0x273c, 0x87fb, 0x00c0, 0x4626, 0x0048, 0x4620, 0x1078, 0x28ec, - 0x689c, 0xa065, 0x0040, 0x462a, 0x0078, 0x4613, 0x1078, 0x46a3, - 0x00c0, 0x4626, 0x127f, 0x2000, 0x007c, 0x127e, 0x007e, 0x017e, - 0x0d7e, 0x70d4, 0xa084, 0x4600, 0x8004, 0x2090, 0x7e20, 0xb284, - 0x0100, 0x00c0, 0x463c, 0x7e24, 0x0d7f, 0x037f, 0x047f, 0xa6b5, - 0x000c, 0x681c, 0xd0b4, 0x0040, 0x464a, 0xc685, 0x7003, 0x0000, - 0x7007, 0x0004, 0x2049, 0x462d, 0x6828, 0xa055, 0x0040, 0x46a0, - 0x2d70, 0x2e60, 0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x43fd, 0x273c, - 0x87fb, 0x00c0, 0x4666, 0x0048, 0x465f, 0x1078, 0x28ec, 0x709c, - 0xa075, 0x2060, 0x0040, 0x46a0, 0x0078, 0x4652, 0x2704, 0xae68, - 0x6808, 0xa422, 0x680c, 0xa31b, 0x0048, 0x467f, 0x8a51, 0x00c0, - 0x4673, 0x1078, 0x28ec, 0x8738, 0x2704, 0xa005, 0x00c0, 0x4667, - 0x709c, 0xa075, 0x2060, 0x0040, 0x46a0, 0x0078, 0x4652, 0x8422, - 0x8420, 0x831a, 0xa399, 0x0000, 0x6908, 0x2400, 0xa122, 0x690c, - 0x2300, 0xa11b, 0x00c8, 0x468e, 0x1078, 0x28ec, 0xb284, 0x0100, - 0x0040, 0x469c, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x00c0, 0x469c, - 0x2071, 0x0050, 0x0078, 0x469e, 0x2071, 0x0020, 0x0078, 0x45b3, - 0x127f, 0x2000, 0x007c, 0x7008, 0xa084, 0x0003, 0xa086, 0x0003, - 0x00c0, 0x46ab, 0x007c, 0x2704, 0xac78, 0x7800, 0x701a, 0x7804, - 0x701e, 0x7808, 0x7012, 0x780c, 0x7016, 0x6004, 0xa084, 0x0008, - 0x0040, 0x46be, 0x7810, 0x7022, 0x7814, 0x7026, 0x7602, 0x7004, - 0xa084, 0x0010, 0xc085, 0x7006, 0x2079, 0x4a00, 0x8a51, 0x0040, - 0x46e1, 0x8738, 0x2704, 0xa005, 0x00c0, 0x46dc, 0x609c, 0xa005, - 0x0040, 0x46e2, 0x2060, 0x6004, 0xa084, 0x000f, 0xa080, 0x43fd, - 0x203c, 0x87fb, 0x1040, 0x28ec, 0x7008, 0xa084, 0x0003, 0xa086, - 0x0003, 0x007c, 0x2051, 0x0000, 0x007c, 0x127e, 0x007e, 0x0d7e, - 0x70d4, 0xa084, 0x4600, 0x8004, 0x2090, 0x0d7f, 0x087f, 0x7108, - 0xa184, 0x0003, 0x00c0, 0x46fa, 0x6828, 0xa005, 0x0040, 0x470a, - 0x0078, 0x4342, 0x7108, 0xd1fc, 0x0040, 0x4702, 0x1078, 0x44ba, - 0x0078, 0x46ef, 0x7007, 0x0010, 0x7108, 0xd1fc, 0x0040, 0x4704, - 0x1078, 0x44ba, 0x7008, 0xa086, 0x0008, 0x00c0, 0x46ef, 0x7000, - 0xa005, 0x00c0, 0x46ef, 0x7003, 0x0000, 0x2049, 0x0000, 0x127f, - 0x2000, 0x007c, 0x127e, 0x147e, 0x137e, 0x157e, 0x0c7e, 0x0d7e, - 0x70d4, 0xa084, 0x4600, 0x8004, 0x2090, 0x0d7f, 0x2049, 0x471a, - 0xad80, 0x0011, 0x20a0, 0xb284, 0x0100, 0x0040, 0x473d, 0x2001, - 0x4a04, 0x2004, 0xd0ec, 0x0040, 0x4739, 0x2099, 0x0031, 0x0078, - 0x473f, 0x2099, 0x0032, 0x0078, 0x473f, 0x2099, 0x0031, 0x700c, - 0xa084, 0x03ff, 0x682a, 0x7007, 0x0008, 0x7007, 0x0002, 0x7003, - 0x0001, 0x0040, 0x474e, 0x8000, 0x80ac, 0x53a5, 0x700c, 0xa084, - 0x03ff, 0x0040, 0x475a, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, - 0x00c0, 0x4755, 0x0c7f, 0x2049, 0x0000, 0x7003, 0x0000, 0x157f, - 0x137f, 0x147f, 0x127f, 0x2000, 0x007c, 0x2091, 0x8000, 0x2091, - 0x6000, 0x78ac, 0xa005, 0x00c0, 0x477c, 0x7974, 0x70d0, 0xa106, - 0x00c0, 0x477c, 0x781c, 0xa005, 0x0040, 0x477c, 0x781f, 0x0000, - 0x0068, 0x477c, 0x2091, 0x4080, 0x7830, 0x8001, 0x7832, 0x00c0, - 0x4804, 0x7834, 0x7832, 0x7810, 0xd0ec, 0x00c0, 0x47fd, 0x2061, - 0x6fc0, 0x2069, 0x4a80, 0xc7fd, 0x68d0, 0xa005, 0x0040, 0x4796, - 0x8001, 0x68d2, 0x00c0, 0x4796, 0x1078, 0x4998, 0x6800, 0xa084, - 0x000f, 0x0040, 0x47ab, 0xa086, 0x0001, 0x0040, 0x47ab, 0x6844, - 0xa00d, 0x0040, 0x47ab, 0x2104, 0xa005, 0x0040, 0x47ab, 0x8001, - 0x200a, 0x0040, 0x4909, 0x6814, 0xa005, 0x0040, 0x47d0, 0x8001, - 0x6816, 0x00c0, 0x47d0, 0x68a7, 0x0001, 0x0f7e, 0xd7fc, 0x00c0, - 0x47c5, 0x7810, 0xd0ec, 0x0040, 0x47c1, 0x2079, 0x0100, 0x0078, - 0x47c7, 0x2079, 0x0200, 0x0078, 0x47c7, 0x2079, 0x0100, 0x1078, - 0x4131, 0x0f7f, 0x6864, 0xa005, 0x0040, 0x47d0, 0x1078, 0x25de, - 0x6880, 0xa005, 0x0040, 0x47dd, 0x8001, 0x6882, 0x00c0, 0x47dd, - 0x6867, 0x0000, 0x68d4, 0xc0dd, 0x68d6, 0x68d4, 0xd0fc, 0x0040, - 0x47fa, 0xc0fc, 0x68d6, 0x20a9, 0x0200, 0x603c, 0xa005, 0x0040, - 0x47f6, 0x8001, 0x603e, 0x68d4, 0xc0fd, 0x68d6, 0x00c0, 0x47f6, - 0x6010, 0xa005, 0x0040, 0x47f6, 0x1078, 0x25de, 0xace0, 0x0010, - 0x00f0, 0x47e5, 0xd7fc, 0x0040, 0x4804, 0x2061, 0x4fc0, 0x2069, - 0x4a40, 0xc7fc, 0x0078, 0x478c, 0x1078, 0x4840, 0x7838, 0x8001, - 0x783a, 0x00c0, 0x4826, 0x783c, 0x783a, 0x2061, 0x4fc0, 0x2069, - 0x4a40, 0xc7fc, 0x680c, 0xa005, 0x0040, 0x4818, 0x1078, 0x487f, - 0xd7fc, 0x00c0, 0x4826, 0x7810, 0xd0ec, 0x00c0, 0x4826, 0x2061, - 0x6fc0, 0x2069, 0x4a80, 0xc7fd, 0x0078, 0x4812, 0x7814, 0xd0e4, - 0x00c0, 0x482a, 0x7810, 0xd0cc, 0x0040, 0x483d, 0xd0ac, 0x00c0, - 0x4836, 0xd0a4, 0x0040, 0x483d, 0xc0ad, 0x7812, 0x2091, 0x8001, - 0x0068, 0x483c, 0x1078, 0x2368, 0x007c, 0x2091, 0x8001, 0x007c, - 0x7840, 0x8001, 0x7842, 0x00c0, 0x487e, 0x7844, 0x7842, 0x2091, - 0x8000, 0x2061, 0x4fc0, 0x2069, 0x4a40, 0xc7fc, 0x6810, 0xa005, - 0x00c0, 0x4854, 0x2001, 0x0101, 0x8001, 0x6812, 0xd7fc, 0x0040, - 0x485d, 0xa080, 0x90d0, 0x0078, 0x485f, 0xa080, 0x8fc0, 0x2040, - 0x2004, 0xa065, 0x0040, 0x4870, 0x6024, 0xa005, 0x0040, 0x486c, - 0x8001, 0x6026, 0x0040, 0x48ad, 0x6000, 0x2c40, 0x0078, 0x4861, - 0xd7fc, 0x00c0, 0x487e, 0x7810, 0xd0ec, 0x00c0, 0x487e, 0x2061, - 0x6fc0, 0x2069, 0x4a80, 0xc7fd, 0x0078, 0x484e, 0x007c, 0x2009, - 0x0000, 0x20a9, 0x0200, 0x6008, 0xd09c, 0x0040, 0x4899, 0x6024, - 0xa005, 0x0040, 0x488f, 0x8001, 0x6026, 0x0078, 0x4897, 0x6008, - 0xc09c, 0xc0bd, 0x600a, 0xa18d, 0x0001, 0x0078, 0x4899, 0xa18d, - 0x0100, 0xace0, 0x0010, 0x00f0, 0x4883, 0xa184, 0x0001, 0x0040, - 0x48a8, 0xa18c, 0xfffe, 0x690e, 0x1078, 0x25de, 0x0078, 0x48a9, - 0x690e, 0x007c, 0x00c0, 0x48a9, 0x786c, 0x6800, 0xa005, 0x0040, - 0x48b5, 0x684c, 0xac06, 0x0040, 0x4909, 0x6864, 0xa005, 0x0040, - 0x48bd, 0x6027, 0x0001, 0x0078, 0x4906, 0x2c00, 0x687e, 0x601b, + 0x6820, 0xc0c5, 0x6822, 0x70d4, 0xd0b4, 0x0040, 0x3eda, 0xc0b4, + 0x70d6, 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, + 0x8001, 0x601a, 0x0c7f, 0x007c, 0x0c7e, 0x2960, 0x6104, 0xa18c, + 0xfff5, 0x6106, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078, 0x3ee8, + 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa, + 0xa8c0, 0x0005, 0x6820, 0xc0c5, 0x6822, 0x0c7f, 0x007c, 0x0c7e, + 0x7158, 0x2160, 0x2018, 0xa08c, 0x0020, 0x0040, 0x3f00, 0xc0ac, + 0x2008, 0xa084, 0xfff0, 0xa635, 0x7e86, 0x6018, 0x789a, 0x7eae, + 0x6612, 0x78a4, 0xa084, 0xfff0, 0xa18c, 0x000f, 0xa105, 0xc0f4, + 0xa39c, 0x0020, 0x0040, 0x3f16, 0xa085, 0x4000, 0xc0fc, 0xd0b4, + 0x00c0, 0x3f1b, 0xc0fd, 0x78a6, 0x6016, 0x788a, 0xa6b4, 0x000f, + 0x8637, 0x8204, 0x8004, 0xa084, 0x00ff, 0xa605, 0x600e, 0x6004, + 0xa084, 0xfff5, 0x6006, 0x0c7f, 0x007c, 0x0c7e, 0x7058, 0x2060, + 0x6018, 0x789a, 0x78a4, 0xa084, 0xfff0, 0x78a6, 0x6012, 0x7884, + 0xa084, 0xfff0, 0x7886, 0x600c, 0xa084, 0x00ff, 0x600e, 0x0c7f, + 0x007c, 0xa282, 0x0002, 0x00c0, 0x4040, 0x7aa8, 0x6920, 0xc1bd, + 0x6922, 0xd1cc, 0x0040, 0x3f7c, 0xc1cc, 0x6922, 0xa294, 0x00ff, + 0xa282, 0x0002, 0x00c8, 0x4040, 0x1078, 0x3fcd, 0x1078, 0x3f2d, + 0xa980, 0x0001, 0x200c, 0x1078, 0x4183, 0x1078, 0x3e7c, 0x88ff, + 0x0040, 0x3f72, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695, + 0x7e5a, 0xd6d4, 0x00c0, 0x3f6f, 0x781b, 0x0061, 0x007c, 0x781b, + 0x0075, 0x007c, 0x7e58, 0xd6d4, 0x00c0, 0x3f79, 0x781b, 0x0064, + 0x007c, 0x781b, 0x0076, 0x007c, 0xa282, 0x0002, 0x00c8, 0x3f84, + 0xa284, 0x0001, 0x0040, 0x3f8d, 0x7158, 0xa188, 0x0000, 0x210c, + 0xd1ec, 0x00c0, 0x3f8d, 0x2011, 0x0000, 0x1078, 0x40b5, 0x1078, + 0x3fcd, 0x1078, 0x3f2d, 0x7858, 0xc095, 0x785a, 0x781b, 0x0075, + 0x007c, 0x0c7e, 0x027e, 0x2960, 0x6000, 0x2011, 0x0001, 0xd0ec, + 0x00c0, 0x3fae, 0x6014, 0xa084, 0x0040, 0x00c0, 0x3fac, 0xc1a4, + 0x6106, 0xa006, 0x0078, 0x3fca, 0x2011, 0x0000, 0x78ab, 0x0001, + 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x70d4, + 0xd0b4, 0x0040, 0x3fc6, 0xc0b4, 0x70d6, 0x70b8, 0xa065, 0x6008, + 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x6820, 0xa085, + 0x0200, 0x6822, 0x027f, 0x0c7f, 0x007c, 0x0c7e, 0x7058, 0x2060, + 0x82ff, 0x0040, 0x3fd5, 0x2011, 0x0040, 0x6018, 0xa080, 0x0002, + 0x789a, 0x78a4, 0xa084, 0xffbf, 0xa205, 0xc0fc, 0xd0b4, 0x00c0, + 0x3fe2, 0xc0fd, 0x78a6, 0x6016, 0x788a, 0x6004, 0xc0a4, 0x6006, + 0x0c7f, 0x007c, 0x007e, 0x7000, 0xa086, 0x0003, 0x0040, 0x3ff3, + 0x007f, 0x0078, 0x3ff6, 0x007f, 0x0078, 0x403d, 0xd6ac, 0x0040, + 0x403d, 0x7888, 0xa084, 0x0040, 0x0040, 0x403d, 0x7bb8, 0xa384, + 0x003f, 0x831b, 0x00c8, 0x4005, 0x8000, 0xa005, 0x0040, 0x401a, + 0x831b, 0x00c8, 0x400e, 0x8001, 0x0040, 0x403a, 0xd6f4, 0x0040, + 0x401a, 0x78b8, 0x801b, 0x00c8, 0x4016, 0x8000, 0xa084, 0x003f, + 0x00c0, 0x403a, 0xc6f4, 0x7e5a, 0x79d8, 0x7adc, 0x2001, 0x0001, + 0xa108, 0x00c8, 0x4025, 0xa291, 0x0000, 0x79d2, 0x79da, 0x7ad6, + 0x7ade, 0x1078, 0x493a, 0x781b, 0x0073, 0xb284, 0x0300, 0x0040, + 0x4035, 0x2001, 0x0000, 0x0078, 0x4037, 0x2001, 0x0001, 0x1078, + 0x47c2, 0x007c, 0x781b, 0x0073, 0x007c, 0x781b, 0x0076, 0x007c, + 0x1078, 0x4068, 0x781b, 0x0075, 0x007c, 0x1078, 0x4051, 0x781b, + 0x0075, 0x007c, 0x6827, 0x0002, 0x1078, 0x4059, 0x781b, 0x0075, + 0x007c, 0x2001, 0x0005, 0x0078, 0x406a, 0x2001, 0x000c, 0x0078, + 0x406a, 0x6820, 0xc0d5, 0x6822, 0x2001, 0x0006, 0x0078, 0x406a, + 0x2001, 0x000d, 0x0078, 0x406a, 0x2001, 0x0009, 0x0078, 0x406a, + 0x2001, 0x0007, 0x789b, 0x007e, 0x78aa, 0xc69d, 0x7e5a, 0x70d4, + 0xd0b4, 0x0040, 0x4080, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8, 0xa065, + 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f, + 0x007c, 0x077e, 0x873f, 0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703, + 0x017e, 0xb28c, 0x0300, 0x0040, 0x4091, 0xa0e0, 0x51c0, 0x0078, + 0x4093, 0xa0e0, 0x5240, 0x017f, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, + 0xa184, 0x000f, 0x0040, 0x40a3, 0xa184, 0xfff0, 0x78a6, 0x6012, + 0x6004, 0xc09d, 0x6006, 0x8738, 0x8738, 0x7f9a, 0x79a4, 0xa184, + 0x0040, 0x0040, 0x40b3, 0xa184, 0xffbf, 0xc0fd, 0x78a6, 0x6016, + 0x6004, 0xc0a5, 0x6006, 0x077f, 0x007c, 0x789b, 0x0010, 0x78ab, + 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060, + 0x78ab, 0x0004, 0x70d4, 0xd0b4, 0x0040, 0x40d3, 0xc0b4, 0x70d6, + 0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, + 0x8001, 0x601a, 0x0c7f, 0x007c, 0x2031, 0x0000, 0x2029, 0x0032, + 0x789b, 0x0010, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, + 0x7daa, 0x7eaa, 0x789b, 0x0060, 0x78ab, 0x0005, 0x70d4, 0xd0b4, + 0x0040, 0x40f7, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008, + 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f, 0x007c, + 0x157e, 0x8007, 0xa084, 0x00ff, 0x8003, 0x8003, 0xa080, 0x0020, + 0x789a, 0x79a4, 0xa18c, 0xfff0, 0x2021, 0x416c, 0x2019, 0x0011, + 0x20a9, 0x000e, 0x2011, 0x0032, 0x2404, 0xa084, 0xfff0, 0xa106, + 0x0040, 0x4117, 0x8420, 0x2300, 0xa210, 0x00f0, 0x410c, 0x157f, + 0x007c, 0x157e, 0x2001, 0x4d05, 0x2004, 0xd0e4, 0x00c0, 0x414a, + 0x2021, 0x417a, 0x20a9, 0x0009, 0x2011, 0x0028, 0xa582, 0x0019, + 0x0040, 0x4160, 0x0048, 0x4160, 0x8420, 0x95a9, 0x2011, 0x0032, + 0xa582, 0x0032, 0x0040, 0x4160, 0x0048, 0x4160, 0x8420, 0x95a9, + 0x2019, 0x000a, 0x2011, 0x0064, 0x2200, 0xa502, 0x0040, 0x4160, + 0x0048, 0x4160, 0x8420, 0x2300, 0xa210, 0x00f0, 0x413c, 0x157f, + 0x0078, 0x415e, 0x2021, 0x416c, 0x2019, 0x0011, 0x20a9, 0x000e, + 0x2011, 0x0032, 0x2200, 0xa502, 0x0040, 0x4160, 0x0048, 0x4160, + 0x8420, 0x2300, 0xa210, 0x00f0, 0x4152, 0x157f, 0xa006, 0x007c, + 0x157f, 0xa582, 0x0064, 0x00c8, 0x4169, 0x7808, 0xa085, 0x0070, + 0x780a, 0x2404, 0xa005, 0x007c, 0x1209, 0x3002, 0x3202, 0x4203, + 0x4403, 0x5404, 0x5604, 0x6605, 0x6805, 0x7806, 0x7a06, 0x0c07, + 0x0c07, 0x0e07, 0x10e1, 0x330a, 0x5805, 0x5a05, 0x6a06, 0x6c06, + 0x7c07, 0x7e07, 0x0e00, 0x789b, 0x0010, 0xa046, 0x007c, 0xa784, + 0x0f00, 0x800b, 0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003, + 0xa105, 0xd7fc, 0x0040, 0x4198, 0xa0e0, 0x72c0, 0x0078, 0x419a, + 0xa0e0, 0x52c0, 0x007c, 0x0e7e, 0x0f7e, 0xd084, 0x0040, 0x41a8, + 0x2079, 0x0100, 0x2009, 0x4d80, 0x2071, 0x4d80, 0x0078, 0x41b8, + 0x2009, 0x4d40, 0x2071, 0x4d40, 0x2001, 0x4d04, 0x2004, 0xd0ec, + 0x0040, 0x41b6, 0x2079, 0x0100, 0x0078, 0x41b8, 0x2079, 0x0200, + 0x2091, 0x8000, 0x2104, 0xa084, 0x000f, 0x0079, 0x41bf, 0x41c9, + 0x41c9, 0x41c9, 0x41c9, 0x41c9, 0x41c9, 0x41c7, 0x41c7, 0x1078, + 0x290c, 0x69b4, 0xc1f5, 0xa18c, 0xff9f, 0x69b6, 0xa005, 0x0040, + 0x4218, 0x7858, 0xa084, 0xff9f, 0xa085, 0x6000, 0x785a, 0x7828, + 0xa086, 0x1814, 0x00c0, 0x4218, 0x784b, 0x0004, 0x7848, 0xa084, + 0x0004, 0x00c0, 0x41de, 0x784b, 0x0008, 0x7848, 0xa084, 0x0008, + 0x00c0, 0x41e5, 0x7830, 0xd0bc, 0x00c0, 0x4218, 0x007e, 0x2001, + 0x4d04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x41fa, 0xb284, 0x0300, + 0x0078, 0x41fc, 0xb284, 0x0400, 0x0040, 0x4202, 0x0018, 0x4218, + 0x0078, 0x4204, 0x0028, 0x4218, 0x79e4, 0xa184, 0x0030, 0x0040, + 0x4218, 0x78ec, 0xa084, 0x0003, 0x0040, 0x4218, 0x681c, 0xd0ac, + 0x00c0, 0x4216, 0x1078, 0x42a2, 0x0078, 0x4218, 0x781b, 0x00f6, + 0x0f7f, 0x0e7f, 0x007c, 0x0c7e, 0x2001, 0x4d01, 0x2004, 0xd0ac, + 0x00c0, 0x4294, 0x6814, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, + 0x8003, 0xb28c, 0x0300, 0x0040, 0x4231, 0xa0e0, 0x51c0, 0x0078, + 0x4233, 0xa0e0, 0x5240, 0x6004, 0xa084, 0x000a, 0x00c0, 0x4294, + 0x6108, 0xa194, 0xff00, 0x0040, 0x4294, 0xa18c, 0x00ff, 0x2001, + 0x000a, 0xa106, 0x0040, 0x425f, 0x2001, 0x000c, 0xa106, 0x0040, + 0x4263, 0x2001, 0x0012, 0xa106, 0x0040, 0x4267, 0x2001, 0x0014, + 0xa106, 0x0040, 0x426b, 0x2001, 0x0019, 0xa106, 0x0040, 0x426f, + 0x2001, 0x0032, 0xa106, 0x0040, 0x4273, 0x0078, 0x4277, 0x2009, + 0x000c, 0x0078, 0x4279, 0x2009, 0x0012, 0x0078, 0x4279, 0x2009, + 0x0014, 0x0078, 0x4279, 0x2009, 0x0019, 0x0078, 0x4279, 0x2009, + 0x0020, 0x0078, 0x4279, 0x2009, 0x003f, 0x0078, 0x4279, 0x2011, + 0x0000, 0x2100, 0xa205, 0x600a, 0x6004, 0xa085, 0x0002, 0x6006, + 0x2061, 0x4d00, 0x6004, 0xd0bc, 0x0040, 0x4294, 0x6814, 0xd0fc, + 0x00c0, 0x428f, 0x60ea, 0x2061, 0x4d40, 0x0078, 0x4292, 0x60ee, + 0x2061, 0x4d80, 0x601f, 0x800f, 0x0c7f, 0x007c, 0x781b, 0x0076, + 0x007c, 0x781b, 0x0075, 0x007c, 0x781b, 0x0064, 0x007c, 0x781b, + 0x0061, 0x007c, 0x2009, 0x4d19, 0x210c, 0xa186, 0x0000, 0x0040, + 0x42b4, 0xa186, 0x0001, 0x0040, 0x42b7, 0x701f, 0x000b, 0x7067, + 0x0001, 0x781b, 0x0047, 0x007c, 0x781b, 0x00ed, 0x007c, 0x701f, + 0x000a, 0x007c, 0x2009, 0x4d19, 0x210c, 0xa186, 0x0000, 0x0040, + 0x42cf, 0xa186, 0x0001, 0x0040, 0x42cc, 0x701f, 0x000b, 0x7067, + 0x0001, 0x781b, 0x0047, 0x007c, 0x701f, 0x000a, 0x007c, 0x781b, + 0x00ec, 0x007c, 0x781b, 0x00f6, 0x007c, 0x781b, 0x00f5, 0x007c, + 0x781b, 0x00c6, 0x007c, 0x781b, 0x00c5, 0x007c, 0x6818, 0xd0fc, + 0x0040, 0x42e4, 0x681b, 0x001d, 0x7067, 0x0001, 0x781b, 0x0047, + 0x007c, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x42fd, 0x7808, 0xc08c, + 0x780a, 0x0005, 0x0005, 0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, + 0x0040, 0x42fd, 0x7808, 0xc08d, 0x780a, 0x007c, 0x7808, 0xc08d, + 0x780a, 0x007c, 0x7830, 0xa084, 0x0040, 0x00c0, 0x4302, 0x2001, + 0x4d04, 0x2004, 0xd0ec, 0x0040, 0x4311, 0xb284, 0x0300, 0x0078, + 0x4313, 0xb284, 0x0400, 0x0040, 0x4319, 0x0098, 0x431d, 0x0078, + 0x431b, 0x00a8, 0x431d, 0x78ac, 0x007c, 0x7808, 0xa084, 0xfffd, + 0x780a, 0x0005, 0x0005, 0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, + 0x0040, 0x4340, 0x007e, 0x2001, 0x4d04, 0x2004, 0xd0ec, 0x007f, + 0x0040, 0x4336, 0xb284, 0x0300, 0x0078, 0x4338, 0xb284, 0x0400, + 0x0040, 0x433e, 0x0098, 0x433a, 0x0078, 0x4340, 0x00a8, 0x433e, + 0x78ac, 0x007e, 0x7808, 0xa085, 0x0002, 0x780a, 0x007f, 0x007c, + 0xa784, 0x0001, 0x00c0, 0x36fb, 0xa784, 0x0070, 0x0040, 0x4358, + 0x0c7e, 0x2d60, 0x2f68, 0x1078, 0x288d, 0x2d78, 0x2c68, 0x0c7f, + 0xa784, 0x0008, 0x0040, 0x4365, 0x784b, 0x0008, 0x78ec, 0xa084, + 0x0003, 0x0040, 0x2966, 0x0078, 0x4296, 0xa784, 0x0004, 0x0040, + 0x4394, 0x78b8, 0xa084, 0x4001, 0x0040, 0x4394, 0x784b, 0x0008, + 0x78ec, 0xa084, 0x0003, 0x0040, 0x2966, 0x78e4, 0xa084, 0x0007, + 0xa086, 0x0001, 0x00c0, 0x4394, 0x78c0, 0xa685, 0x4800, 0x2030, + 0x7e5a, 0x781b, 0x00f6, 0x007c, 0x784b, 0x0008, 0x6818, 0xd0fc, + 0x0040, 0x4391, 0x681b, 0x0015, 0xd6f4, 0x0040, 0x4391, 0x681b, + 0x0007, 0x1078, 0x42a2, 0x007c, 0x681b, 0x0003, 0x7858, 0xa084, + 0x3f00, 0x681e, 0x682f, 0x0000, 0x6833, 0x0000, 0x784b, 0x0008, + 0x78ec, 0xa084, 0x0003, 0x0040, 0x3004, 0x007e, 0x2001, 0x4d04, + 0x2004, 0xd0ec, 0x007f, 0x0040, 0x43b1, 0xb284, 0x0300, 0x0078, + 0x43b3, 0xb284, 0x0400, 0x0040, 0x43b9, 0x0018, 0x2962, 0x0078, + 0x43bb, 0x0028, 0x2962, 0x0078, 0x4045, 0x6b14, 0x8307, 0xa084, + 0x000f, 0x8003, 0x8003, 0x8003, 0xd3fc, 0x0040, 0x43cb, 0xa080, + 0x5240, 0x0078, 0x43cd, 0xa080, 0x51c0, 0x2060, 0x2048, 0x705a, + 0x2a60, 0x007c, 0x0020, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, + 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, + 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, + 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, + 0x0000, 0x0020, 0x0000, 0x0020, 0x0062, 0x0009, 0x0014, 0x0014, + 0x9848, 0x0014, 0x0014, 0x990e, 0x98fa, 0x0014, 0x0014, 0x0080, + 0x00f9, 0x0100, 0x0402, 0x2008, 0xf880, 0x0018, 0xa20a, 0x0014, + 0x300b, 0xa20c, 0x0014, 0x2500, 0x0013, 0x2500, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0xa200, 0x3806, 0x8839, 0x20c4, + 0x0864, 0xa856, 0x3008, 0x28c1, 0x9d15, 0xa201, 0x300c, 0x2847, + 0x8161, 0x846a, 0x8000, 0x84a4, 0x1856, 0x883a, 0xa808, 0x28e2, + 0x9cc8, 0xa8f3, 0x0864, 0xa844, 0x300c, 0xa801, 0x3008, 0x28e1, + 0x9cc8, 0x2021, 0xa81d, 0xa205, 0x870c, 0xd8de, 0x64a0, 0x6de0, + 0x6fc0, 0x63a4, 0x6c80, 0x0212, 0xa205, 0x883d, 0x7942, 0x8020, + 0xa4a1, 0x882b, 0x1814, 0x883b, 0x80df, 0x94a1, 0x7027, 0x85f2, + 0xa737, 0xa532, 0xf003, 0x8576, 0x8677, 0xa816, 0x883e, 0xa814, + 0x2001, 0xa812, 0xa204, 0x64c0, 0x6de0, 0x67a0, 0x6fc0, 0x7942, + 0x8020, 0xa4a1, 0x1814, 0x80df, 0x94a1, 0x883b, 0x7023, 0x8576, + 0x8677, 0xa802, 0x7861, 0x883e, 0x206b, 0x28c1, 0x9d15, 0x2044, + 0x2103, 0x20a2, 0x2081, 0xa8c3, 0xa207, 0x2901, 0xa80a, 0x0014, + 0xa203, 0x8000, 0x85a4, 0x1872, 0x879a, 0x883c, 0x1fe2, 0xf601, + 0xa208, 0x856e, 0x866f, 0x7161, 0x0014, 0x0704, 0x3008, 0x9cc8, + 0x0014, 0xa202, 0x8000, 0x85a4, 0x3009, 0x84a8, 0x19e2, 0xf844, + 0x856e, 0x883f, 0x08e6, 0xa8f5, 0xf861, 0xa8ea, 0xf801, 0x0014, + 0xf881, 0x0016, 0x85b2, 0x80f0, 0x9532, 0xfaa2, 0x1de2, 0x0014, + 0x8532, 0xf221, 0x0014, 0x1de2, 0x84a8, 0xd6e0, 0x1fe6, 0x0014, + 0x3008, 0x8000, 0x284a, 0x1011, 0xa8fc, 0x3008, 0x9d2d, 0x8000, + 0xa000, 0x2802, 0x1011, 0xa8fd, 0x9d33, 0xa8bd, 0x3008, 0x9d2d, + 0x283b, 0x1011, 0xa8fd, 0xa209, 0x0017, 0x300c, 0xa209, 0x8000, + 0x85a4, 0x1de2, 0xa209, 0xdac1, 0x0014, 0x0210, 0xa801, 0x0014, + 0x26e0, 0x873a, 0xfaa3, 0x19f2, 0x26e0, 0x18f2, 0x0014, 0xa20b, + 0x0014, 0xa20d, 0x3806, 0x0210, 0x9d1f, 0x0704, 0xa206, 0x6865, + 0x817e, 0x842a, 0x1dc1, 0x8823, 0x0016, 0x6042, 0x8008, 0xa8fa, + 0x8000, 0x84a4, 0x8160, 0x842a, 0xf021, 0x3008, 0x84a8, 0x11d6, + 0x7042, 0x20dd, 0x0011, 0x20d4, 0x8822, 0x0016, 0x7944, 0x8421, + 0xa020, 0xa532, 0x84a1, 0x0016, 0x7944, 0x8421, 0xa0df, 0x9532, + 0x84a1, 0x0016, 0x0000, 0x127e, 0x70d4, 0xa084, 0x4600, 0x8004, + 0x2090, 0x7204, 0x7008, 0xc09c, 0xa205, 0x00c0, 0x4517, 0x720c, + 0x82ff, 0x0040, 0x4512, 0x8aff, 0x00c0, 0x4517, 0x7200, 0xd284, + 0x00c0, 0x4517, 0x7003, 0x0008, 0x127f, 0x2000, 0x007c, 0x7000, + 0xa084, 0x0003, 0x7002, 0xc69c, 0xd084, 0x0040, 0x455a, 0x7108, + 0x0005, 0x7008, 0xa106, 0x00c0, 0x451f, 0xa184, 0x0003, 0x0040, + 0x458b, 0xa184, 0x01e0, 0x00c0, 0x458b, 0xd1f4, 0x00c0, 0x451f, + 0xa184, 0x3000, 0xa086, 0x1000, 0x0040, 0x451f, 0x2011, 0x0180, + 0x710c, 0x8211, 0x0040, 0x4544, 0x7008, 0xd0f4, 0x00c0, 0x451f, + 0x700c, 0xa106, 0x0040, 0x4539, 0x7007, 0x0012, 0x7108, 0x0005, + 0x7008, 0xa106, 0x00c0, 0x4546, 0xa184, 0x0003, 0x0040, 0x458b, + 0xd194, 0x0040, 0x4546, 0xd1f4, 0x0040, 0x458b, 0x7007, 0x0002, + 0x0078, 0x451f, 0x7108, 0xd1fc, 0x0040, 0x4565, 0x1078, 0x46e0, + 0x8aff, 0x0040, 0x4501, 0x0078, 0x455a, 0x700c, 0xa08c, 0x03ff, + 0x0040, 0x4590, 0x7004, 0xd084, 0x0040, 0x4582, 0x7014, 0xa005, + 0x00c0, 0x457e, 0x7010, 0x7310, 0xa306, 0x00c0, 0x4572, 0x2300, + 0xa005, 0x0040, 0x4582, 0xa102, 0x00c8, 0x455a, 0x7007, 0x0010, + 0x0078, 0x458b, 0x8aff, 0x0040, 0x4590, 0x1078, 0x48e7, 0x00c0, + 0x4585, 0x0040, 0x455a, 0x1078, 0x4629, 0x127f, 0x2000, 0x007c, + 0x7204, 0x7108, 0xc19c, 0x8103, 0x00c8, 0x459f, 0x1078, 0x46e0, + 0x0078, 0x4590, 0x7003, 0x0008, 0x127f, 0x2000, 0x007c, 0xa205, + 0x00c0, 0x458b, 0x7003, 0x0008, 0x127f, 0x2000, 0x007c, 0x6428, + 0x84ff, 0x0040, 0x45d3, 0x2c70, 0x7004, 0xa0bc, 0x000f, 0xa7b8, + 0x45e3, 0x273c, 0x87fb, 0x00c0, 0x45c1, 0x0048, 0x45b9, 0x1078, + 0x290c, 0x609c, 0xa075, 0x0040, 0x45d3, 0x0078, 0x45ac, 0x2039, + 0x45d8, 0x2704, 0xae68, 0x6808, 0xa630, 0x680c, 0xa529, 0x8421, + 0x0040, 0x45d3, 0x8738, 0x2704, 0xa005, 0x00c0, 0x45c2, 0x709c, + 0xa075, 0x00c0, 0x45ac, 0x007c, 0x0000, 0x0005, 0x0009, 0x000d, + 0x0011, 0x0015, 0x0019, 0x001d, 0x0000, 0x0003, 0x0009, 0x000f, + 0x0015, 0x001b, 0x0000, 0x0000, 0x45d8, 0x45d5, 0x0000, 0x0000, + 0x8000, 0x0000, 0x45d8, 0x0000, 0x45e0, 0x45dd, 0x0000, 0x0000, + 0x0000, 0x0000, 0x45e0, 0x0000, 0x45db, 0x45db, 0x0000, 0x0000, + 0x8000, 0x0000, 0x45db, 0x0000, 0x45e1, 0x45e1, 0x0000, 0x0000, + 0x0000, 0x0000, 0x45e1, 0x2079, 0x4d00, 0x2071, 0x0010, 0x7007, + 0x000a, 0x7007, 0x0002, 0x7003, 0x0001, 0x7810, 0xd0ec, 0x0040, + 0x4617, 0x2009, 0x0001, 0x2071, 0x0020, 0x0078, 0x461b, 0x2009, + 0x0002, 0x2071, 0x0050, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, + 0x0000, 0x8109, 0x0040, 0x4628, 0x2071, 0x0020, 0x0078, 0x461b, + 0x007c, 0x7004, 0x8004, 0x00c8, 0x46b2, 0x7108, 0x7008, 0xa106, + 0x00c0, 0x462d, 0xa184, 0x01e0, 0x0040, 0x463a, 0x1078, 0x4723, + 0x0078, 0x46da, 0x7007, 0x0012, 0x2019, 0x0000, 0x7108, 0x7008, + 0xa106, 0x00c0, 0x463e, 0xa184, 0x01e0, 0x0040, 0x464b, 0x1078, + 0x4723, 0x0078, 0x46da, 0x7810, 0xd0ec, 0x0040, 0x4665, 0x2001, + 0x04fd, 0x2004, 0xa086, 0x0003, 0x00c0, 0x4669, 0xa184, 0x4000, + 0x0040, 0x466d, 0xa382, 0x0003, 0x00c8, 0x466d, 0xa184, 0x0004, + 0x0040, 0x463e, 0x8318, 0x0078, 0x463e, 0x7814, 0xd0ec, 0x00c0, + 0x466d, 0xa184, 0x4000, 0x00c0, 0x463e, 0xa19c, 0x300c, 0xa386, + 0x2004, 0x0040, 0x468a, 0xa386, 0x0008, 0x0040, 0x4695, 0x7004, + 0xd084, 0x00c0, 0x4686, 0x7108, 0x7008, 0xa106, 0x00c0, 0x467b, + 0xa184, 0x0003, 0x0040, 0x4686, 0x0078, 0x4723, 0xa386, 0x200c, + 0x00c0, 0x463e, 0x7200, 0x8204, 0x0048, 0x4695, 0x730c, 0xa384, + 0x03ff, 0x0040, 0x4695, 0x1078, 0x290c, 0x7108, 0x7008, 0xa106, + 0x00c0, 0x4695, 0xa184, 0x01e0, 0x0040, 0x46a2, 0x1078, 0x4723, + 0x0078, 0x46da, 0x7007, 0x0012, 0x7000, 0xd084, 0x00c0, 0x46b2, + 0x7310, 0x7014, 0xa305, 0x0040, 0x46b2, 0x710c, 0xa184, 0x03ff, + 0x00c0, 0x4629, 0x7108, 0x7008, 0xa106, 0x00c0, 0x46b2, 0xa184, + 0x01e0, 0x0040, 0x46bf, 0x1078, 0x4723, 0x0078, 0x46da, 0x7007, + 0x0012, 0x7007, 0x0008, 0x7004, 0xd09c, 0x00c0, 0x46c3, 0x7108, + 0x7008, 0xa106, 0x00c0, 0x46c7, 0xa184, 0x01e0, 0x0040, 0x46d4, + 0x1078, 0x4723, 0x0078, 0x46da, 0x7007, 0x0012, 0x7108, 0x8103, + 0x0048, 0x46c7, 0x7003, 0x0008, 0x007c, 0x7108, 0x0078, 0x46e0, + 0xa184, 0x01e0, 0x00c0, 0x4723, 0x7108, 0xa184, 0x01e0, 0x00c0, + 0x4723, 0xa184, 0x0007, 0x0079, 0x46ed, 0x46f7, 0x4707, 0x46f5, + 0x4707, 0x46f5, 0x4765, 0x46f5, 0x4763, 0x1078, 0x290c, 0x7004, + 0xa084, 0x0010, 0xc08d, 0x7006, 0x8aff, 0x00c0, 0x4702, 0x2049, + 0x0000, 0x007c, 0x1078, 0x48e7, 0x00c0, 0x4702, 0x007c, 0x7004, + 0xa084, 0x0010, 0xc08d, 0x7006, 0x7004, 0xd084, 0x00c0, 0x471b, + 0x7108, 0x7008, 0xa106, 0x00c0, 0x4710, 0xa184, 0x0003, 0x0040, + 0x471b, 0x0078, 0x4723, 0x8aff, 0x0040, 0x4722, 0x1078, 0x48e7, + 0x00c0, 0x471e, 0x007c, 0x7007, 0x0012, 0x7108, 0x00e0, 0x4726, + 0x2091, 0x6000, 0x00e0, 0x472a, 0x2091, 0x6000, 0x7007, 0x0012, + 0x7007, 0x0008, 0x7004, 0xd09c, 0x00c0, 0x4732, 0x7007, 0x0012, + 0x7108, 0xd1fc, 0x00c0, 0x4736, 0x7003, 0x0000, 0x7000, 0xa005, + 0x00c0, 0x474a, 0x7004, 0xa005, 0x00c0, 0x474a, 0x700c, 0xa005, + 0x0040, 0x474c, 0x0078, 0x472e, 0x2049, 0x0000, 0xb284, 0x0100, + 0x0040, 0x4756, 0x2001, 0x0000, 0x0078, 0x4758, 0x2001, 0x0001, + 0x1078, 0x419b, 0x681b, 0x0002, 0x2051, 0x0000, 0x007c, 0x1078, + 0x290c, 0x1078, 0x290c, 0x1078, 0x47ad, 0x7210, 0x7114, 0x700c, + 0xa09c, 0x03ff, 0x2800, 0xa300, 0xa211, 0xa189, 0x0000, 0x1078, + 0x47ad, 0x2704, 0x2c58, 0xac60, 0x6308, 0x2200, 0xa322, 0x630c, + 0x2100, 0xa31b, 0x2400, 0xa305, 0x0040, 0x4788, 0x00c8, 0x4788, + 0x8412, 0x8210, 0x830a, 0xa189, 0x0000, 0x2b60, 0x0078, 0x476f, + 0x2b60, 0x8a07, 0x007e, 0x6004, 0xa084, 0x0008, 0x0040, 0x4794, + 0xa7ba, 0x45dd, 0x0078, 0x4796, 0xa7ba, 0x45d5, 0x007f, 0xa73d, + 0x2c00, 0x6886, 0x6f8a, 0x6c92, 0x6b8e, 0x7108, 0x7008, 0xa106, + 0x00c0, 0x479d, 0xa184, 0x01e0, 0x0040, 0x47a8, 0x1078, 0x4723, + 0x7007, 0x0012, 0x1078, 0x4629, 0x007c, 0x8a50, 0x8739, 0x2704, + 0xa004, 0x00c0, 0x47c1, 0x6000, 0xa064, 0x00c0, 0x47b8, 0x2d60, + 0x6004, 0xa084, 0x000f, 0xa080, 0x45f3, 0x203c, 0x87fb, 0x1040, + 0x290c, 0x007c, 0x127e, 0x0d7e, 0x70d4, 0xa084, 0x4600, 0x8004, + 0x2090, 0x0d7f, 0x6884, 0x2060, 0x6888, 0x6b8c, 0x6c90, 0x8057, + 0xaad4, 0x00ff, 0xa084, 0x00ff, 0x007e, 0x6804, 0xa084, 0x0008, + 0x007f, 0x0040, 0x47df, 0xa0b8, 0x45dd, 0x0078, 0x47e1, 0xa0b8, + 0x45d5, 0xb284, 0x0100, 0x0040, 0x47e8, 0x7e20, 0x0078, 0x47e9, + 0x7e24, 0xa6b5, 0x000c, 0x681c, 0xd0b4, 0x0040, 0x47f0, 0xc685, + 0x2400, 0xa305, 0x0040, 0x481a, 0x2c58, 0x2704, 0x6104, 0xac60, + 0x6000, 0xa400, 0x701a, 0x6004, 0xa301, 0x701e, 0xa184, 0x0008, + 0x0040, 0x480a, 0x6010, 0xa081, 0x0000, 0x7022, 0x6014, 0xa081, + 0x0000, 0x7026, 0x6208, 0x2400, 0xa202, 0x7012, 0x620c, 0x2300, + 0xa203, 0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x1078, 0x4912, + 0x0078, 0x481c, 0x1078, 0x48e7, 0x00c0, 0x481a, 0x127f, 0x2000, + 0x007c, 0x127e, 0x0d7e, 0x70d4, 0xa084, 0x4600, 0x8004, 0x2090, + 0x0d7f, 0x7007, 0x0004, 0x7004, 0xd094, 0x00c0, 0x482b, 0x7003, + 0x0008, 0x127f, 0x2000, 0x007c, 0x127e, 0x0d7e, 0x70d4, 0xa084, + 0x4600, 0x8004, 0x007e, 0x2090, 0x007f, 0x0d7f, 0x7e20, 0xb284, + 0x0100, 0x00c0, 0x4844, 0x7e24, 0xa6b5, 0x000c, 0x681c, 0xd0ac, + 0x00c0, 0x484f, 0xc685, 0x7003, 0x0000, 0x7007, 0x0004, 0x6828, + 0x2050, 0x2d60, 0x6004, 0xa0bc, 0x000f, 0xa7b8, 0x45e3, 0x273c, + 0x87fb, 0x00c0, 0x4865, 0x0048, 0x485f, 0x1078, 0x290c, 0x689c, + 0xa065, 0x0040, 0x4869, 0x0078, 0x4852, 0x1078, 0x48e7, 0x00c0, + 0x4865, 0x127f, 0x2000, 0x007c, 0x127e, 0x007e, 0x017e, 0x0d7e, + 0x70d4, 0xa084, 0x4600, 0x8004, 0x007e, 0x2090, 0x007f, 0x7e20, + 0xb284, 0x0100, 0x00c0, 0x487d, 0x7e24, 0x0d7f, 0x037f, 0x047f, + 0xa6b5, 0x000c, 0x681c, 0xd0b4, 0x0040, 0x488b, 0xc685, 0x7003, + 0x0000, 0x7007, 0x0004, 0x2049, 0x486c, 0x6828, 0xa055, 0x0d7e, + 0x0040, 0x48e3, 0x2d70, 0x2e60, 0x7004, 0xa0bc, 0x000f, 0xa7b8, + 0x45e3, 0x273c, 0x87fb, 0x00c0, 0x48a8, 0x0048, 0x48a1, 0x1078, + 0x290c, 0x709c, 0xa075, 0x2060, 0x0040, 0x48e3, 0x0078, 0x4894, + 0x2704, 0xae68, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0048, 0x48c1, + 0x8a51, 0x00c0, 0x48b5, 0x1078, 0x290c, 0x8738, 0x2704, 0xa005, + 0x00c0, 0x48a9, 0x709c, 0xa075, 0x2060, 0x0040, 0x48e3, 0x0078, + 0x4894, 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x6908, 0x2400, + 0xa122, 0x690c, 0x2300, 0xa11b, 0x00c8, 0x48d0, 0x1078, 0x290c, + 0xb284, 0x0100, 0x0040, 0x48de, 0x2001, 0x4d04, 0x2004, 0xd0ec, + 0x00c0, 0x48de, 0x2071, 0x0050, 0x0078, 0x48e0, 0x2071, 0x0020, + 0x0d7f, 0x0078, 0x47f0, 0x0d7f, 0x127f, 0x2000, 0x007c, 0x7008, + 0x007e, 0xa084, 0x01e0, 0x007f, 0x0040, 0x48f0, 0xa006, 0x007c, + 0xa084, 0x0003, 0xa086, 0x0003, 0x00c0, 0x48f7, 0x007c, 0x2704, + 0xac78, 0x7800, 0x701a, 0x7804, 0x701e, 0x7808, 0x7012, 0x780c, + 0x7016, 0x6004, 0xa084, 0x0008, 0x0040, 0x490a, 0x7810, 0x7022, + 0x7814, 0x7026, 0x7602, 0x7004, 0xa084, 0x0010, 0xc085, 0x7006, + 0x2079, 0x4d00, 0x8a51, 0x0040, 0x4936, 0x8738, 0x2704, 0xa005, + 0x00c0, 0x4928, 0x609c, 0xa005, 0x0040, 0x4937, 0x2060, 0x6004, + 0xa084, 0x000f, 0xa080, 0x45e3, 0x203c, 0x87fb, 0x1040, 0x290c, + 0x7008, 0x007e, 0xa084, 0x01e0, 0x007f, 0x0040, 0x4932, 0xa006, + 0x0078, 0x4937, 0xa084, 0x0003, 0xa086, 0x0003, 0x007c, 0x2051, + 0x0000, 0x007c, 0x127e, 0x007e, 0x0d7e, 0x70d4, 0xa084, 0x4600, + 0x8004, 0x2090, 0x0d7f, 0x087f, 0x7108, 0xa184, 0x0003, 0x00c0, + 0x494f, 0x6828, 0xa005, 0x0040, 0x495f, 0x0078, 0x4517, 0x7108, + 0xd1fc, 0x0040, 0x4957, 0x1078, 0x46e0, 0x0078, 0x4944, 0x7007, + 0x0010, 0x7108, 0xd1fc, 0x0040, 0x4959, 0x1078, 0x46e0, 0x7008, + 0xa086, 0x0008, 0x00c0, 0x4944, 0x7000, 0xa005, 0x00c0, 0x4944, + 0x7003, 0x0000, 0x2049, 0x0000, 0x127f, 0x2000, 0x007c, 0x127e, + 0x147e, 0x137e, 0x157e, 0x0c7e, 0x0d7e, 0x70d4, 0xa084, 0x4600, + 0x8004, 0x2090, 0x0d7f, 0x2049, 0x496f, 0xad80, 0x0011, 0x20a0, + 0xb284, 0x0100, 0x0040, 0x4992, 0x2001, 0x4d04, 0x2004, 0xd0ec, + 0x0040, 0x498e, 0x2099, 0x0031, 0x0078, 0x4994, 0x2099, 0x0032, + 0x0078, 0x4994, 0x2099, 0x0031, 0x700c, 0xa084, 0x03ff, 0x682a, + 0x7007, 0x0008, 0x7007, 0x0002, 0x7003, 0x0001, 0x0040, 0x49a3, + 0x8000, 0x80ac, 0x53a5, 0x700c, 0xa084, 0x03ff, 0x0040, 0x49af, + 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x49aa, 0x0c7f, + 0x2049, 0x0000, 0x7003, 0x0000, 0x157f, 0x137f, 0x147f, 0x127f, + 0x2000, 0x007c, 0x2091, 0x8000, 0x2091, 0x6000, 0x78ac, 0xa005, + 0x00c0, 0x49d1, 0x7974, 0x70d0, 0xa106, 0x00c0, 0x49d1, 0x781c, + 0xa005, 0x0040, 0x49d1, 0x781f, 0x0000, 0x0068, 0x49d1, 0x2091, + 0x4080, 0x7830, 0x8001, 0x7832, 0x00c0, 0x4a59, 0x7834, 0x7832, + 0x7810, 0xd0ec, 0x00c0, 0x4a52, 0x2061, 0x72c0, 0x2069, 0x4d80, + 0xc7fd, 0x68d0, 0xa005, 0x0040, 0x49eb, 0x8001, 0x68d2, 0x00c0, + 0x49eb, 0x1078, 0x4c22, 0x6800, 0xa084, 0x000f, 0x0040, 0x4a00, + 0xa086, 0x0001, 0x0040, 0x4a00, 0x6844, 0xa00d, 0x0040, 0x4a00, + 0x2104, 0xa005, 0x0040, 0x4a00, 0x8001, 0x200a, 0x0040, 0x4b95, + 0x6814, 0xa005, 0x0040, 0x4a25, 0x8001, 0x6816, 0x00c0, 0x4a25, + 0x68a7, 0x0001, 0x0f7e, 0xd7fc, 0x00c0, 0x4a1a, 0x7810, 0xd0ec, + 0x0040, 0x4a16, 0x2079, 0x0100, 0x0078, 0x4a1c, 0x2079, 0x0200, + 0x0078, 0x4a1c, 0x2079, 0x0100, 0x1078, 0x42fe, 0x0f7f, 0x6864, + 0xa005, 0x0040, 0x4a25, 0x1078, 0x25ea, 0x6880, 0xa005, 0x0040, + 0x4a32, 0x8001, 0x6882, 0x00c0, 0x4a32, 0x6867, 0x0000, 0x68d4, + 0xc0dd, 0x68d6, 0x68d4, 0xd0fc, 0x0040, 0x4a4f, 0xc0fc, 0x68d6, + 0x20a9, 0x0200, 0x6034, 0xa005, 0x0040, 0x4a4b, 0x8001, 0x6036, + 0x68d4, 0xc0fd, 0x68d6, 0x00c0, 0x4a4b, 0x6010, 0xa005, 0x0040, + 0x4a4b, 0x1078, 0x25ea, 0xace0, 0x0010, 0x00f0, 0x4a3a, 0xd7fc, + 0x0040, 0x4a59, 0x2061, 0x52c0, 0x2069, 0x4d40, 0xc7fc, 0x0078, + 0x49e1, 0x1078, 0x4a95, 0x7838, 0x8001, 0x783a, 0x00c0, 0x4a7b, + 0x783c, 0x783a, 0x2061, 0x52c0, 0x2069, 0x4d40, 0xc7fc, 0x680c, + 0xa005, 0x0040, 0x4a6d, 0x1078, 0x4aec, 0xd7fc, 0x00c0, 0x4a7b, + 0x7810, 0xd0ec, 0x00c0, 0x4a7b, 0x2061, 0x72c0, 0x2069, 0x4d80, + 0xc7fd, 0x0078, 0x4a67, 0x7814, 0xd0e4, 0x00c0, 0x4a7f, 0x7810, + 0xd0cc, 0x0040, 0x4a92, 0xd0ac, 0x00c0, 0x4a8b, 0xd0a4, 0x0040, + 0x4a92, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0068, 0x4a91, 0x1078, + 0x2356, 0x007c, 0x2091, 0x8001, 0x007c, 0x7840, 0x8001, 0x7842, + 0x00c0, 0x4aeb, 0x7844, 0x7842, 0x2091, 0x8000, 0x2061, 0x52c0, + 0x2069, 0x4d40, 0xc7fc, 0x7810, 0x2079, 0x0200, 0xd0ec, 0x0040, + 0x4aab, 0x2079, 0x0100, 0x68d8, 0xa005, 0x0040, 0x4ab7, 0x7de0, + 0xa504, 0x00c0, 0x4ab7, 0x68da, 0x68d4, 0xc0bc, 0x68d6, 0x2079, + 0x4d00, 0x6810, 0xa005, 0x00c0, 0x4abf, 0x2001, 0x0101, 0x8001, + 0x6812, 0xd7fc, 0x0040, 0x4ac8, 0xa080, 0x93d0, 0x0078, 0x4aca, + 0xa080, 0x92c0, 0x2040, 0x2004, 0xa065, 0x0040, 0x4adb, 0x6024, + 0xa005, 0x0040, 0x4ad7, 0x8001, 0x6026, 0x0040, 0x4b37, 0x6000, + 0x2c40, 0x0078, 0x4acc, 0xd7fc, 0x00c0, 0x4aeb, 0x7810, 0xd0ec, + 0x00c0, 0x4aeb, 0x2061, 0x72c0, 0x2069, 0x4d80, 0xc7fd, 0x2079, + 0x0200, 0x0078, 0x4aab, 0x007c, 0x2009, 0x0000, 0x20a9, 0x0200, + 0x6008, 0xd09c, 0x0040, 0x4b23, 0x6024, 0xa005, 0x0040, 0x4afc, + 0x8001, 0x6026, 0x0078, 0x4b21, 0x6008, 0xc09c, 0xd084, 0x00c0, + 0x4b04, 0xd0ac, 0x0040, 0x4b1b, 0x600a, 0x6004, 0xa06d, 0x0040, + 0x4b23, 0x0c7e, 0x017e, 0x6010, 0x8001, 0x6012, 0x1078, 0x3d56, + 0x2d00, 0x2c68, 0x2060, 0x1078, 0x1e42, 0x1078, 0x2004, 0x017f, + 0x0c7f, 0x0078, 0x4b23, 0xc0bd, 0x600a, 0xa18d, 0x0001, 0x0078, + 0x4b23, 0xa18d, 0x0100, 0xace0, 0x0010, 0x00f0, 0x4af0, 0xa184, + 0x0001, 0x0040, 0x4b32, 0xa18c, 0xfffe, 0x690e, 0x1078, 0x25ea, + 0x0078, 0x4b33, 0x690e, 0x007c, 0x00c0, 0x4b33, 0x786c, 0x6800, + 0xa005, 0x0040, 0x4b3f, 0x684c, 0xac06, 0x0040, 0x4b95, 0x6864, + 0xa005, 0x0040, 0x4b47, 0x6027, 0x0001, 0x0078, 0x4b94, 0x2c00, + 0x687e, 0x6714, 0x6f76, 0x6017, 0x0000, 0x602b, 0x0000, 0x601b, 0x0006, 0x60b4, 0xa084, 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff, - 0xa085, 0x0060, 0x6022, 0x6000, 0x2042, 0x6714, 0x6f76, 0x1078, - 0x1e02, 0x6818, 0xa005, 0x0040, 0x48d7, 0x8001, 0x681a, 0x6808, - 0xc0a4, 0x680a, 0x6810, 0x7908, 0x8109, 0x790a, 0x8001, 0x00d0, - 0x48e3, 0x1078, 0x28ec, 0x6812, 0x00c0, 0x48e9, 0x7910, 0xc1a5, - 0x7912, 0x602f, 0x0000, 0x6033, 0x0000, 0x2c68, 0x1078, 0x202a, - 0xd7fc, 0x00c0, 0x48f7, 0x2069, 0x4a40, 0x0078, 0x48f9, 0x2069, - 0x4a80, 0x6910, 0xa184, 0x0100, 0x2001, 0x0006, 0x00c0, 0x4903, - 0x697a, 0x2001, 0x0004, 0x2708, 0x1078, 0x25d1, 0x2091, 0x8001, - 0x007c, 0x0d7e, 0x694c, 0x2160, 0xd7fc, 0x00c0, 0x491b, 0x7810, - 0xd0ec, 0x0040, 0x4917, 0x2069, 0x0100, 0x0078, 0x491d, 0x2069, - 0x0200, 0x0078, 0x491d, 0x2069, 0x0100, 0x1078, 0x2881, 0x601b, - 0x0006, 0x6858, 0xa084, 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff, - 0xa085, 0x0048, 0x6022, 0x602f, 0x0000, 0x6033, 0x0000, 0x6830, - 0xd0b4, 0x0040, 0x494b, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, - 0xd094, 0x0040, 0x493d, 0x00f0, 0x4937, 0x684b, 0x0009, 0x20a9, - 0x0014, 0x6848, 0xd084, 0x0040, 0x4947, 0x00f0, 0x4941, 0x20a9, - 0x00fa, 0x00f0, 0x4949, 0x6808, 0xa084, 0xfffd, 0x680a, 0x681b, - 0x0047, 0x0d7f, 0x6867, 0x0007, 0x2091, 0x8001, 0x007c, 0x2079, - 0x4a00, 0x1078, 0x498b, 0x1078, 0x4971, 0x1078, 0x497e, 0x2009, - 0x0002, 0x2069, 0x4a80, 0x680f, 0x0000, 0x6813, 0x0000, 0x6817, - 0x0000, 0x8109, 0x0040, 0x4970, 0x2069, 0x4a40, 0x0078, 0x4963, - 0x007c, 0x7810, 0xd0ec, 0x0040, 0x4979, 0x2019, 0x00cc, 0x0078, - 0x497b, 0x2019, 0x007b, 0x7b3a, 0x7b3e, 0x007c, 0x7814, 0xd0e4, - 0x00c0, 0x4986, 0x2019, 0x0040, 0x0078, 0x4988, 0x2019, 0x0026, - 0x7b42, 0x7b46, 0x007c, 0x7814, 0xd0e4, 0x00c0, 0x4993, 0x2019, - 0x3f94, 0x0078, 0x4995, 0x2019, 0x2624, 0x7b32, 0x7b36, 0x007c, - 0x6950, 0xa185, 0x0000, 0x0040, 0x49ad, 0x0c7e, 0x6ac0, 0x2264, - 0x602b, 0x0000, 0x602f, 0x0000, 0x6008, 0xc0b5, 0x600a, 0x8210, - 0x8109, 0x00c0, 0x499f, 0x6952, 0x0c7f, 0x007c, 0x70ec, 0xd0dc, - 0x00c0, 0x49b7, 0xd0d4, 0x0040, 0x49d6, 0x0078, 0x49d9, 0x7810, - 0xd0ec, 0x0040, 0x49c2, 0xc0f5, 0x7812, 0xd0ec, 0x0040, 0x49dd, - 0x0078, 0x49d9, 0xae8e, 0x0100, 0x0040, 0x49ce, 0x7814, 0xc0f5, - 0x7816, 0xd0d4, 0x00c0, 0x49dd, 0x0078, 0x49d9, 0x7814, 0xc0fd, - 0x7816, 0xd0d4, 0x00c0, 0x49dd, 0x0078, 0x49d9, 0xd0e4, 0x0040, - 0x49df, 0x7804, 0xd08c, 0x0040, 0x49df, 0x681f, 0x000c, 0x70a0, - 0x70a2, 0x007c, 0x699a + 0xa085, 0x0060, 0x6022, 0x6000, 0x2042, 0x1078, 0x1dcb, 0x6818, + 0xa005, 0x0040, 0x4b65, 0x8001, 0x681a, 0x6808, 0xc0a4, 0x680a, + 0x6810, 0x7908, 0x8109, 0x790a, 0x8001, 0x00d0, 0x4b71, 0x1078, + 0x290c, 0x6812, 0x00c0, 0x4b77, 0x7910, 0xc1a5, 0x7912, 0x602f, + 0x0000, 0x6033, 0x0000, 0x2c68, 0x1078, 0x2013, 0xd7fc, 0x00c0, + 0x4b85, 0x2069, 0x4d40, 0x0078, 0x4b87, 0x2069, 0x4d80, 0x6910, + 0xa184, 0x0100, 0x2001, 0x0006, 0x00c0, 0x4b91, 0x697a, 0x2001, + 0x0004, 0x2708, 0x1078, 0x25dd, 0x007c, 0x0d7e, 0x694c, 0x2160, + 0xd7fc, 0x00c0, 0x4ba7, 0x7810, 0xd0ec, 0x0040, 0x4ba3, 0x2069, + 0x0100, 0x0078, 0x4ba9, 0x2069, 0x0200, 0x0078, 0x4ba9, 0x2069, + 0x0100, 0x1078, 0x288d, 0x601b, 0x0006, 0x6858, 0xa084, 0x3f00, + 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085, 0x0048, 0x6022, 0x602f, + 0x0000, 0x6033, 0x0000, 0x6808, 0xa084, 0xfffd, 0x680a, 0x6830, + 0xd0b4, 0x0040, 0x4bdb, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, + 0xd094, 0x0040, 0x4bcd, 0x00f0, 0x4bc7, 0x684b, 0x0009, 0x20a9, + 0x0014, 0x6848, 0xd084, 0x0040, 0x4bd7, 0x00f0, 0x4bd1, 0x20a9, + 0x00fa, 0x00f0, 0x4bd9, 0x681b, 0x0047, 0x0d7f, 0x6867, 0x0007, + 0x007c, 0x2079, 0x4d00, 0x1078, 0x4c15, 0x1078, 0x4bfb, 0x1078, + 0x4c08, 0x2009, 0x0002, 0x2069, 0x4d80, 0x680f, 0x0000, 0x6813, + 0x0000, 0x6817, 0x0000, 0x8109, 0x0040, 0x4bfa, 0x2069, 0x4d40, + 0x0078, 0x4bed, 0x007c, 0x7810, 0xd0ec, 0x0040, 0x4c03, 0x2019, + 0x00cc, 0x0078, 0x4c05, 0x2019, 0x007b, 0x7b3a, 0x7b3e, 0x007c, + 0x7814, 0xd0e4, 0x00c0, 0x4c10, 0x2019, 0x0040, 0x0078, 0x4c12, + 0x2019, 0x0026, 0x7b42, 0x7b46, 0x007c, 0x7814, 0xd0e4, 0x00c0, + 0x4c1d, 0x2019, 0x3f94, 0x0078, 0x4c1f, 0x2019, 0x2624, 0x7b32, + 0x7b36, 0x007c, 0x6950, 0xa185, 0x0000, 0x0040, 0x4c37, 0x0c7e, + 0x6ac0, 0x2264, 0x602b, 0x0000, 0x602f, 0x0000, 0x6008, 0xc0b5, + 0x600a, 0x8210, 0x8109, 0x00c0, 0x4c29, 0x6952, 0x0c7f, 0x007c, + 0x70ec, 0xd0dc, 0x00c0, 0x4c41, 0xd0d4, 0x0040, 0x4c64, 0x0078, + 0x4c67, 0x2008, 0x7810, 0xd0ec, 0x0040, 0x4c50, 0xd1c4, 0x00c0, + 0x4c6f, 0xc0f5, 0x7812, 0xd0ec, 0x0040, 0x4c6b, 0x0078, 0x4c67, + 0xae8e, 0x0100, 0x0040, 0x4c5c, 0x7814, 0xc0f5, 0x7816, 0xd0d4, + 0x00c0, 0x4c6b, 0x0078, 0x4c67, 0x7814, 0xc0fd, 0x7816, 0xd0d4, + 0x00c0, 0x4c6b, 0x0078, 0x4c67, 0xd0e4, 0x0040, 0x4c6d, 0x7804, + 0xd08c, 0x0040, 0x4c6d, 0x681f, 0x000c, 0x70a0, 0x70a2, 0x007c, + 0x3782 }; -unsigned short fw1280ei_length01 = 0x39e3; +#ifdef UNIQUE_FW_NAME +unsigned short fw1280ei_length01 = 0x3c71; +#else +unsigned short risc_code_length01 = 0x3c71; +#endif diff -urN linux-2.4.0-test10/drivers/scsi/qla1280.c linux-2.4.0-test10-lia/drivers/scsi/qla1280.c --- linux-2.4.0-test10/drivers/scsi/qla1280.c Mon Sep 18 13:36:25 2000 +++ linux-2.4.0-test10-lia/drivers/scsi/qla1280.c Mon Oct 30 22:50:11 2000 @@ -1,162 +1,84 @@ /******************************************************************************** - * QLOGIC LINUX SOFTWARE - * - * QLogic ISP1x80/1x160 device driver for Linux 2.3.x (redhat 6.X). - * - * COPYRIGHT (C) 1999-2000 QLOGIC CORPORATION - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the Qlogic's Linux Software License. See below. - * - * This program is WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistribution's or source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - ********************************************************************************/ - -/***************************************************************************************** - QLOGIC CORPORATION SOFTWARE - "GNU" GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION - AND MODIFICATION - -This GNU General Public License ("License") applies solely to QLogic Linux -Software ("Software") and may be distributed under the terms of this License. - -1. You may copy and distribute verbatim copies of the Software'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 Software a copy of this License along -with the Software. - -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 Software or any portion of it, thus forming -a work based on the Software, 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 Software 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 Software 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 Software under these conditions, and telling the user how to -view a copy of this License. (Exception:if the Software itself is interactive but does -not normally print such an announcement, your work based on the Software 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 Software, 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 Software, 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. - -3. You may copy and distribute the Software (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 Software 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. - -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 Software except as expressly -provided under this License. Any attempt otherwise to copy, modify, sublicense or -distribute the Software 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. This license grants you world wide, royalty free non-exclusive rights to modify or -distribute the Software or its derivative works. These actions are prohibited by law -if you do not accept this License. Therefore, by modifying or distributing the Software -(or any work based on the Software), you indicate your acceptance of this License to do -so, and all its terms and conditions for copying, distributing or modifying the Software -or works based on it. - -6. Each time you redistribute the Software (or any work based on the Software), the -recipient automatically receives a license from the original licensor to copy, distribute -or modify the Software 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 -Software at all. - -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. -NO WARRANTY - -11. THE SOFTWARE IS PROVIDED WITHOUT A WARRANTY OF ANY KIND. THERE IS NO -WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE SOFTWARE "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 SOFTWARE IS WITH YOU. -SHOULD THE SOFTWARE 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 SOFTWARE 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 SOFTWARE (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 SOFTWARE TO -OPERATE WITH ANY OTHER SOFTWARES), EVEN IF SUCH HOLDER OR OTHER PARTY HAS -BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. -END OF TERMS AND CONDITIONS - -*******************************************************************************************/ - +* QLOGIC LINUX SOFTWARE +* +* QLogic QLA1280 (Ultra2) and QLA12160 (Ultra3) SCSI driver +* Copyright (C) 2000 Qlogic Corporation +* (www.qlogic.com) +* +* 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. +** +******************************************************************************/ +#define QLA1280_VERSION "3.19 Beta" /**************************************************************************** Revision History: - Rev. 3.00 Jan 17, 1999 DG Qlogic + Rev 3.19 Beta October 13, 2000 BN Qlogic + - Declare driver_template for new kernel + (2.4.0 and greater) scsi initialization scheme. + - Update /proc/scsi entry for 2.3.18 kernels and + above as qla1280 + Rev 3.18 Beta October 10, 2000 BN Qlogic + - Changed scan order of adapters to map + the QLA12160 followed by the QLA1280. + Rev 3.17 Beta September 18, 2000 BN Qlogic + - Removed warnings for 32 bit 2.4.x compiles + - Corrected declared size for request and response + DMA addresses that are kept in each ha + Rev. 3.16 Beta August 25, 2000 BN Qlogic + - Corrected 64 bit addressing issue on IA-64 + where the upper 32 bits were not properly + passed to the RISC engine. + Rev. 3.15 Beta August 22, 2000 BN Qlogic + - Modified qla1280_setup_chip to properly load + ISP firmware for greater that 4 Gig memory on IA-64 + Rev. 3.14 Beta August 16, 2000 BN Qlogic + - Added setting of dma_mask to full 64 bit + if flags.enable_64bit_addressing is set in NVRAM + Rev. 3.13 Beta August 16, 2000 BN Qlogic + - Use new PCI DMA mapping APIs for 2.4.x kernel + Rev. 3.12 July 18, 2000 Redhat & BN Qlogic + - Added check of pci_enable_device to detect() for 2.3.x + - Use pci_resource_start() instead of + pdev->resource[0].start in detect() for 2.3.x + - Updated driver version + Rev. 3.11 July 14, 2000 BN Qlogic + - Updated SCSI Firmware to following versions: + qla1x80: 8.13.08 + qla1x160: 10.04.08 + - Updated driver version to 3.11 + Rev. 3.10 June 23, 2000 BN Qlogic + - Added filtering of AMI SubSys Vendor ID devices + Rev. 3.9 + - DEBUG_QLA1280 undefined and new version BN Qlogic + Rev. 3.08b May 9, 2000 MD Dell + - Added logic to check against AMI subsystem vendor ID + Rev. 3.08 May 4, 2000 DG Qlogic + - Added logic to check for PCI subsystem ID. + Rev. 3.07 Apr 24, 2000 DG & BN Qlogic + - Updated SCSI Firmware to following versions: + qla12160: 10.01.19 + qla1280: 8.09.00 + Rev. 3.06 Apr 12, 2000 DG & BN Qlogic + - Internal revision; not released + Rev. 3.05 Mar 28, 2000 DG & BN Qlogic + - Edit correction for virt_to_bus and PROC. + Rev. 3.04 Mar 28, 2000 DG & BN Qlogic + - Merge changes from ia64 port. + Rev. 3.03 Mar 28, 2000 BN Qlogic + - Increase version to reflect new code drop with compile fix + of issue with inclusion of linux/spinlock for 2.3 kernels + Rev. 3.02 Mar 15, 2000 BN Qlogic + - Merge qla1280_proc_info from 2.10 code base + Rev. 3.01 Feb 10, 2000 BN Qlogic + - Corrected code to compile on a 2.2.x kernel. + Rev. 3.00 Jan 17, 2000 DG Qlogic - Added 64-bit support. Rev. 2.07 Nov 9, 1999 DG Qlogic - Added new routine to set target parameters for ISP12160. @@ -183,12 +105,11 @@ *****************************************************************************/ +#include #ifdef MODULE #include #endif -#define QLA1280_VERSION " 3.00-Beta" - #include #include #include @@ -207,8 +128,16 @@ #include #include #include -/* MRS #include */ +#ifndef KERNEL_VERSION +# define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,18) +#include +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) +#include # include #endif #include "sd.h" @@ -216,23 +145,16 @@ #include "hosts.h" #define UNIQUE_FW_NAME #include "qla1280.h" -#include "ql12160_fw.h" /* ISP RISC code */ +#include "ql12160_fw.h" /* ISP RISC codes */ #include "ql1280_fw.h" #include -#include /* for kmalloc() */ - - -#ifndef KERNEL_VERSION -# define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) -#endif - +#include /* * Compile time Options: * 0 - Disable and 1 - Enable */ -#define QLA1280_64BIT_SUPPORT 1 /* 64-bit Support */ #define QL1280_TARGET_MODE_SUPPORT 0 /* Target mode support */ #define WATCHDOGTIMER 0 #define MEMORY_MAPPED_IO 0 @@ -244,15 +166,16 @@ #define AUTO_ESCALATE_ABORT 0 /* Automatically escalate aborts */ #define STOP_ON_ERROR 0 /* Stop on aborts and resets */ #define STOP_ON_RESET 0 -#define STOP_ON_ABORT 0 -#undef DYNAMIC_MEM_ALLOC - -#define DEBUG_QLA1280 0 /* Debugging */ -/* #define CHECKSRBSIZE */ +#define STOP_ON_ABORT 0 + +#define DEBUG_QLA1280 0 -/* - * These macros to assist programming - */ +/*************** 64 BIT PCI DMA ******************************************/ +#define FORCE_64BIT_PCI_DMA 0 /* set to one for testing only */ +/* Applicable to 64 version of the Linux 2.4.x and above only */ +/* NVRAM bit nv->cntr_flags_1.enable_64bit_addressing should be used for */ +/* administrator control of PCI DMA width size per system configuration */ +/*************************************************************************/ #define BZERO(ptr, amt) memset(ptr, 0, amt) #define BCOPY(src, dst, amt) memcpy(dst, src, amt) @@ -260,19 +183,28 @@ #define KMFREE(ip,siz) kfree((ip)) #define SYS_DELAY(x) udelay(x);barrier() #define QLA1280_DELAY(sec) mdelay(sec * 1000) -#define VIRT_TO_BUS(a) virt_to_bus((a)) -#if QLA1280_64BIT_SUPPORT + +/* 3.16 */ +#if BITS_PER_LONG > 32 +#define pci_dma_lo32(a) (a & 0xffffffff) +#define pci_dma_hi32(a) ((a >> 32) & 0xffffffff) +#else +#define pci_dma_lo32(a) (a & 0xffffffff) +#define pci_dma_hi32(a) 0 +#endif + +#define VIRT_TO_BUS(a) virt_to_bus(((void *)a)) + #if BITS_PER_LONG <= 32 -#define VIRT_TO_BUS_LOW(a) (uint32_t)virt_to_bus((a)) +#define VIRT_TO_BUS_LOW(a) (uint32_t)virt_to_bus(((void *)a)) #define VIRT_TO_BUS_HIGH(a) (uint32_t)(0x0) #else -#define VIRT_TO_BUS_LOW(a) (uint32_t)(0xffffffff & virt_to_bus((a))) -#define VIRT_TO_BUS_HIGH(a) (uint32_t)(0xffffffff & (virt_to_bus((a))>>32)) +#define VIRT_TO_BUS_LOW(a) (uint32_t)(0xffffffff & virt_to_bus((void *)(a))) +#define VIRT_TO_BUS_HIGH(a) (uint32_t)(0xffffffff & (virt_to_bus((void *)(a))>>32)) #endif -#endif /* QLA1280_64BIT_SUPPORT */ -#define STATIC +#define STATIC #define NVRAM_DELAY() udelay(500) /* 2 microsecond delay */ void qla1280_device_queue_depth(scsi_qla_host_t *, Scsi_Device *); @@ -285,11 +217,11 @@ #define LSB(x) (uint8_t)(x) #if BITS_PER_LONG <= 32 -#define LS_64BITS(x) (uint32_t)(x) -#define MS_64BITS(x) (uint32_t)(0x0) +#define LS_64BITS(x) (uint32_t)((unsigned long) x) +#define MS_64BITS(x) (uint32_t)((unsigned long) 0x0) #else -#define LS_64BITS(x) (uint32_t)(0xffffffff & (x)) -#define MS_64BITS(x) (uint32_t)(0xffffffff & ((x)>>32) ) +#define LS_64BITS(x) (uint32_t)(0xffffffff & ((unsigned long)x)) +#define MS_64BITS(x) (uint32_t)(0xffffffff & (((unsigned long)x)>>32) ) #endif /* @@ -300,9 +232,6 @@ STATIC void qla1280_putq_t(scsi_lu_t *, srb_t *); STATIC void qla1280_done_q_put(srb_t *, srb_t **, srb_t **); STATIC void qla1280_select_queue_depth(struct Scsi_Host *, Scsi_Device *); -#ifdef QLA1280_UNUSED -static void qla1280_dump_regs(struct Scsi_Host *host); -#endif #if STOP_ON_ERROR static void qla1280_panic(char *, struct Scsi_Host *host); #endif @@ -313,9 +242,6 @@ STATIC void qla1280_removeq(scsi_lu_t *q, srb_t *sp); STATIC void qla1280_mem_free(scsi_qla_host_t *ha); void qla1280_do_dpc(void *p); -#ifdef QLA1280_UNUSED -static void qla1280_set_flags(char * s); -#endif static char *qla1280_get_token(char *, char *); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) STATIC inline void mdelay(int); @@ -339,9 +265,7 @@ STATIC uint8_t qla1280_device_reset(scsi_qla_host_t *, uint8_t, uint32_t); STATIC uint8_t qla1280_abort_device(scsi_qla_host_t *, uint8_t, uint32_t, uint32_t); STATIC uint8_t qla1280_abort_command(scsi_qla_host_t *, srb_t *), -#if QLA1280_64BIT_SUPPORT qla1280_64bit_start_scsi(scsi_qla_host_t *, srb_t *), -#endif qla1280_32bit_start_scsi(scsi_qla_host_t *, srb_t *), qla1280_abort_isp(scsi_qla_host_t *); STATIC void qla1280_nv_write(scsi_qla_host_t *, uint16_t), @@ -374,12 +298,12 @@ qla1280_notify_ack(scsi_qla_host_t *, notify_entry_t *), qla1280_immed_notify(scsi_qla_host_t *, notify_entry_t *), qla1280_accept_io(scsi_qla_host_t *, ctio_ret_entry_t *), -#if QLA1280_64BIT_SUPPORT - qla1280_64bit_continue_io(scsi_qla_host_t *, atio_entry_t *, uint32_t, - paddr32_t *), -#endif - qla1280_32bit_continue_io(scsi_qla_host_t *, atio_entry_t *, uint32_t, - paddr32_t *), + qla1280_64bit_continue_io(scsi_qla_host_t *, + atio_entry_t *, uint32_t, + paddr32_t *), + qla1280_32bit_continue_io(scsi_qla_host_t *, + atio_entry_t *, uint32_t, + paddr32_t *), qla1280_atio_entry(scsi_qla_host_t *, atio_entry_t *), qla1280_notify_entry(scsi_qla_host_t *, notify_entry_t *); #endif /* QLA1280_TARGET_MODE_SUPPORT */ @@ -400,7 +324,7 @@ qla1280_dump_buffer(caddr_t, uint32_t); char debug_buff[80]; -#if DEBUG_QLA1280 +#if DEBUG_QLA1280 STATIC uint8_t ql_debug_print = 1; #else STATIC uint8_t ql_debug_print = 0; @@ -426,6 +350,22 @@ #endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) +/* + * Our directory Entry in /proc/scsi for the user to + * access the driver. + */ +/* Need to add in proc_fs.h PROC_SCSI_QL1280 */ +#define PROC_SCSI_QL1280 PROC_SCSI_QLOGICISP + +struct proc_dir_entry proc_scsi_qla1280 = { + PROC_SCSI_QL1280, 7, "qla1280", + S_IFDIR | S_IRUGO | S_IXUGO, 2, + 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; +#endif + /* We use the Scsi_Pointer structure that's included with each command * SCSI_Cmnd as a scratchpad for our SRB. * @@ -471,17 +411,17 @@ unsigned char *fwver; /* Ptr to F/W version array */ } qla_boards_t; -struct _qlaboards QLBoardTbl[NUM_OF_ISP_DEVICES] = +struct _qlaboards QL1280BoardTbl[NUM_OF_ISP_DEVICES] = { /* Name , Board PCI Device ID, Number of ports */ + {"QLA12160 ", QLA12160_DEVICE_ID, 2, + &fw12160i_code01[0], (unsigned long *)&fw12160i_length01,&fw12160i_addr01, &fw12160i_version_str[0] }, {"QLA1080 ", QLA1080_DEVICE_ID, 1, &fw1280ei_code01[0], (unsigned long *)&fw1280ei_length01,&fw1280ei_addr01, &fw1280ei_version_str[0] }, {"QLA1240 ", QLA1240_DEVICE_ID, 2, &fw1280ei_code01[0], (unsigned long *)&fw1280ei_length01,&fw1280ei_addr01, &fw1280ei_version_str[0] }, {"QLA1280 ", QLA1280_DEVICE_ID, 2, &fw1280ei_code01[0], (unsigned long *)&fw1280ei_length01,&fw1280ei_addr01, &fw1280ei_version_str[0] }, - {"QLA12160 ", QLA12160_DEVICE_ID, 2, - &fw12160i_code01[0], (unsigned long *)&fw12160i_length01,&fw12160i_addr01, &fw12160i_version_str[0] }, {"QLA10160 ", QLA10160_DEVICE_ID, 1, &fw12160i_code01[0], (unsigned long *)&fw12160i_length01,&fw12160i_addr01, &fw12160i_version_str[0] }, {" ", 0, 0} @@ -567,152 +507,149 @@ * * Returns: *************************************************************************/ -#ifdef QLA1280_PROFILE -#define PROC_BUF (&qla1280_buffer[size]) -#define LUN_ID (targ_lun>>(MAX_T_BITS+MAX_L_BITS)),((targ_lun>>MAX_L_BITS)&0xf), targ_lun&0x7 -#endif +#define PROC_BUF (&qla1280_buffer[len]) int -qla1280_proc_info ( char *buffer, char **start, off_t offset, int length, - int hostno, int inout) -{ -#ifdef QLA1280_PROFILE +qla1280_proc_info( char *buffer, char **start, off_t offset, int length, + int hostno, int inout) { +#if QLA1280_PROFILE struct Scsi_Host *host; scsi_qla_host_t *ha; int size = 0; - int targ_lun; scsi_lu_t *up; - int no_devices; + int len = 0; + qla_boards_t *bdp; + uint32_t b, t, l; - printk("Entering proc_info 0x%p,0x%lx,0x%x,0x%x\n",buffer,offset,length,hostno); host = NULL; - /* find the host they want to look at */ - for(ha=qla1280_hostlist; (ha != NULL) && ha->host->host_no != hostno; ha=ha->next) + + /* Find the host that was specified */ + for( ha=qla1280_hostlist; (ha != NULL) && ha->host->host_no != hostno; ha=ha->next ) ; - if (!ha) - { - size += sprintf(buffer, "Can't find adapter for host number %d\n", hostno); - if (size > length) - { + /* if host wasn't found then exit */ + if( !ha ) { + size = sprintf(buffer, "Can't find adapter for host number %d\n", hostno); + if( size > length ) { return (size); - } - else - { - return (length); + } else { + return (0); } } host = ha->host; - if (inout == TRUE) /* Has data been written to the file? */ - { - return (qla1280_set_info(buffer, length, host)); - } - /* compute number of active devices */ - no_devices = 0; - for (targ_lun = 0; targ_lun < MAX_EQ; targ_lun++) + if( inout == TRUE ) /* Has data been written to the file? */ { - if( (up = ha->dev[targ_lun]) == NULL ) - continue; - no_devices++; + printk("qla1280_proc: has data been written to the file. \n"); + return (qla1280_set_info(buffer, length, host)); } - /* size = 112 * no_devices; */ - size = 4096; - /* round up to the next page */ /* * if our old buffer is the right size use it otherwise * allocate a new one. */ - if (qla1280_buffer_size != size) - { + size = 4096; /* get a page */ + if( qla1280_buffer_size != size ) { /* deallocate this buffer and get a new one */ - if (qla1280_buffer != NULL) - { + if( qla1280_buffer != NULL ) { kfree(qla1280_buffer); qla1280_buffer_size = 0; } qla1280_buffer = kmalloc(size, GFP_KERNEL); } - if (qla1280_buffer == NULL) - { + if( qla1280_buffer == NULL ) { size = sprintf(buffer, "qla1280 - kmalloc error at line %d\n", __LINE__); return size; } + /* save the size of our buffer */ qla1280_buffer_size = size; - size = 0; - size += sprintf(PROC_BUF, "Qlogic 1280/1080 SCSI driver version: "); /* 43 bytes */ - size += sprintf(PROC_BUF, "%5s, ", QLA1280_VERSION); /* 5 */ - size += sprintf(PROC_BUF, "Qlogic Firmware version: "); /* 25 */ - size += sprintf(PROC_BUF, "%2d.%2d.%2d",_firmware_version[0], /* 8 */ - ql12_firmware_version[1], - ql12_firmware_version[2]); - size += sprintf(PROC_BUF, "\n"); /* 1 */ - - size += sprintf(PROC_BUF, "SCSI Host Adapter Information: %s\n", QLBoardTbl[ha->devnum].bdName); - size += sprintf(PROC_BUF, "Request Queue = 0x%lx, Response Queue = 0x%lx\n", + /* start building the print buffer */ + bdp = &QL1280BoardTbl[ha->devnum]; + size = sprintf(PROC_BUF, + "QLogic PCI to SCSI Adapter for ISP 1280/12160:\n" + " Firmware version: %2d.%02d.%02d, Driver version %s\n", bdp->fwver[0], bdp->fwver[1], bdp->fwver[2], QLA1280_VERSION); + + len += size; + + size = sprintf(PROC_BUF, "SCSI Host Adapter Information: %s\n", bdp->bdName); + len += size; + size = sprintf(PROC_BUF, "Request Queue = 0x%lx, Response Queue = 0x%lx\n", ha->request_dma, ha->response_dma); - size += sprintf(PROC_BUF, "Request Queue count= 0x%x, Response Queue count= 0x%x\n", + len += size; + size = sprintf(PROC_BUF, "Request Queue count= 0x%lx, Response Queue count= 0x%lx\n", REQUEST_ENTRY_CNT, RESPONSE_ENTRY_CNT); - size += sprintf(PROC_BUF,"Number of pending commands = 0x%lx\n", ha->actthreads); - size += sprintf(PROC_BUF,"Number of queued commands = 0x%lx\n", ha->qthreads); - size += sprintf(PROC_BUF,"Number of free request entries = %d\n",ha->req_q_cnt); - size += sprintf(PROC_BUF, "\n"); /* 1 */ + len += size; + size = sprintf(PROC_BUF, "Number of pending commands = 0x%lx\n", ha->actthreads); + len += size; + size = sprintf(PROC_BUF, "Number of queued commands = 0x%lx\n", ha->qthreads); + len += size; + size = sprintf(PROC_BUF, "Number of free request entries = %d\n",ha->req_q_cnt); + len += size; + size = sprintf(PROC_BUF, "\n"); /* 1 */ + len += size; - size += sprintf(PROC_BUF, "Attached devices:\n"); + size = sprintf(PROC_BUF, "SCSI device Information:\n"); + len += size; /* scan for all equipment stats */ - for (targ_lun = 0; targ_lun < MAX_EQ; targ_lun++) - { - if( (up = ha->dev[targ_lun]) == NULL ) + for (b = 0; b < MAX_BUSES; b++) + for (t = 0; t < MAX_TARGETS; t++) { + for( l = 0; l < MAX_LUNS; l++ ) { + up = (scsi_lu_t *) LU_Q(ha, b, t, l); + if( up == NULL ) continue; - if( up->io_cnt == 0 ) - { - size += sprintf(PROC_BUF,"(%2d:%2d:%2d) No stats\n",LUN_ID); + /* unused device/lun */ + if( up->io_cnt == 0 || up->io_cnt < 2 ) continue; - } /* total reads since boot */ /* total writes since boot */ /* total requests since boot */ - size += sprintf(PROC_BUF, "Total requests %ld,",up->io_cnt); + size = sprintf(PROC_BUF, "(%2d:%2d:%2d): Total reqs %ld,",b,t,l,up->io_cnt); + len += size; /* current number of pending requests */ - size += sprintf(PROC_BUF, "(%2d:%2d:%2d) pending requests %d,",LUN_ID,up->q_outcnt); + size = sprintf(PROC_BUF, " Pend reqs %d,",up->q_outcnt); + len += size; +#if 0 /* avg response time */ - size += sprintf(PROC_BUF, "Avg response time %ld%%,",(up->resp_time/up->io_cnt)*100); + size = sprintf(PROC_BUF, " Avg resp time %ld%%,",(up->resp_time/up->io_cnt)*100); + len += size; /* avg active time */ - size += sprintf(PROC_BUF, "Avg active time %ld%%\n",(up->act_time/up->io_cnt)*100); + size = sprintf(PROC_BUF, " Avg active time %ld%%\n",(up->act_time/up->io_cnt)*100); +#else + size = sprintf(PROC_BUF, "\n"); +#endif + len += size; + } + if( len >= qla1280_buffer_size ) + break; } - if (size >= qla1280_buffer_size) - { + if( len >= qla1280_buffer_size ) { printk(KERN_WARNING "qla1280: Overflow buffer in qla1280_proc.c\n"); } - if (offset > size - 1) - { + if( offset > len - 1 ) { kfree(qla1280_buffer); qla1280_buffer = NULL; qla1280_buffer_size = length = 0; *start = NULL; - } - else - { + } else { *start = &qla1280_buffer[offset]; /* Start of wanted data */ - if (size - offset < length) - { - length = size - offset; + if( len - offset < length ) { + length = len - offset; } } + return (length); +#else + return (0); #endif - return (length); } - /************************************************************************** * qla1280_detect * This routine will probe for Qlogic 1280 SCSI host adapters. @@ -735,6 +672,9 @@ scsi_qla_host_t *ha, *cur_ha; struct _qlaboards *bdp; int i, j; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) + unsigned short subsys; +#endif #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,1,95) unsigned int piobase; unsigned char pci_bus, pci_devfn, pci_irq; @@ -747,13 +687,19 @@ #else int index; #endif +#ifndef PCI_VENDOR_ID_AMI +#define PCI_VENDOR_ID_AMI 0x101e +#endif ENTER("qla1280_detect"); + if (sizeof(srb_t) > sizeof(Scsi_Pointer) ) + printk("qla1280_detect: [WARNING] srb_t Must Be Redefined"); + #ifdef CHECKSRBSIZE if (sizeof(srb_t) > sizeof(Scsi_Pointer) ) { - printk("Redefine SRB - its too big"); + printk("qla1280_detect: srb_t Must Be Redefined - its too big"); return 0; } #endif @@ -784,40 +730,77 @@ "qla1280: insmod or else it might trash certain memory areas.\n"); #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) if ((int) !pcibios_present()) +#else + if (!pci_present()) +#endif { - printk("scsi: PCI not present\n"); - return 0; - } /* end of IF */ - bdp = &QLBoardTbl[0]; + printk("scsi: PCI not present\n"); + return 0; + } + + bdp = &QL1280BoardTbl[0]; qla1280_hostlist = NULL; -#if 0 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) template->proc_dir = &proc_scsi_qla1280; #else template->proc_name = "qla1280"; #endif - /* Try and find each different type of adapter we support */ for( i=0; bdp->device_id != 0 && i < NUM_OF_ISP_DEVICES; i++, bdp++ ) { #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,18) + /* PCI_SUBSYSTEM_IDS supported */ + while ((pdev = pci_find_subsys(QLA1280_VENDOR_ID, + bdp->device_id, PCI_ANY_ID, PCI_ANY_ID, pdev) )) { + if (pci_enable_device(pdev)) continue; +#else while ((pdev = pci_find_device(QLA1280_VENDOR_ID, bdp->device_id, pdev ) )) { - if (pci_enable_device(pdev)) continue; -#else +#endif /* 2,3,18 */ +#else /* less than 2,1,95 */ while (!(pcibios_find_device(QLA1280_VENDOR_ID, bdp->device_id, index++, &pci_bus, &pci_devfn)) ) { -#endif +#endif /* 2,1,95 */ /* found a adapter */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,18) + printk("qla1280: detect() found an HBA\n"); + printk("qla1280: VID=%x DID=%x SSVID=%x SSDID=%x\n", + pdev->vendor, pdev->device, + pdev->subsystem_vendor, pdev->subsystem_device); + /* If it's an AMI SubSys Vendor ID adapter, skip it. */ + if (pdev->subsystem_vendor == PCI_VENDOR_ID_AMI) + { + printk("qla1280: Skip AMI SubSys Vendor ID Chip\n"); + continue; + } +#else +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95) + pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, + &subsys); + /* Bypass all AMI SUBSYS VENDOR IDs */ + if (subsys == PCI_VENDOR_ID_AMI) + { + printk("qla1280: Skip AMI SubSys Vendor ID Chip\n"); + continue; + } +#endif /* 2,1,95 */ +#endif /* 2,3,18 */ host = scsi_register(template, sizeof(scsi_qla_host_t)); ha = (scsi_qla_host_t *) host->hostdata; /* Clear our data area */ for( j =0, cp = (char *)ha; j < sizeof(scsi_qla_host_t); j++) - *cp = 0; + *cp++ = 0; /* Sanitize the information from PCI BIOS. */ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95) host->irq = pdev->irq; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) + host->io_port = (unsigned int) pdev->base_address[0]; +#else host->io_port = pci_resource_start(pdev, 0); +#endif ha->pci_bus = pdev->bus->number; ha->pci_device_fn = pdev->devfn; ha->pdev = pdev; @@ -834,35 +817,35 @@ ha->devnum = i; if( qla1280_mem_alloc(ha) ) { - printk(KERN_INFO "qla1280: Failed to allocate memory for adapter\n"); + printk(KERN_INFO "qla1280: Failed to get memory\n"); } ha->ports = bdp->numPorts; + /* following needed for all cases of OS versions */ + host->io_port &= PCI_BASE_ADDRESS_IO_MASK; ha->iobase = (device_reg_t *) host->io_port; ha->host = host; ha->host_no = host->host_no; /* load the F/W, read paramaters, and init the H/W */ + ha->instance = num_hosts; if (qla1280_initialize_adapter(ha)) { - - printk(KERN_INFO "qla1280: Failed to initialized adapter\n"); - qla1280_mem_free(ha); - scsi_unregister(host); - continue; + printk(KERN_INFO "qla1280: Failed to initialize adapter\n"); + qla1280_mem_free(ha); + scsi_unregister(host); + continue; } host->max_channel = bdp->numPorts-1; - ha->instance = num_hosts; /* Register our resources with Linux */ if( qla1280_register_with_Linux(ha, bdp->numPorts-1) ) { - printk(KERN_INFO "qla1280: Failed to register our resources\n"); - qla1280_mem_free(ha); - scsi_unregister(host); - continue; + printk(KERN_INFO "qla1280: Failed to register resources\n"); + qla1280_mem_free(ha); + scsi_unregister(host); + continue; } - reg = ha->iobase; /* Disable ISP interrupts. */ qla1280_disable_intrs(ha); @@ -919,8 +902,11 @@ host->can_queue = 0xfffff; /* unlimited */ host->cmd_per_lun = 1; host->select_queue_depths = qla1280_select_queue_depth; - host->n_io_port = 0xFF; - host->base = (unsigned long) ha->mmpbase; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) + host->base = (unsigned char *) ha->mmpbase; +#else + host->base = (u_long) ha->mmpbase; +#endif host->max_channel = maxchannels; host->max_lun = MAX_LUNS-1; host->unique_id = ha->instance; @@ -1011,10 +997,10 @@ bp = &qla1280_buffer[0]; ha = (scsi_qla_host_t *)host->hostdata; - bdp = &QLBoardTbl[ha->devnum]; + bdp = &QL1280BoardTbl[ha->devnum]; memset(bp, 0, sizeof(qla1280_buffer)); sprintf(bp, - "QLogic %sPCI to SCSI Host Adapter: bus %d device %d irq %d\n" + "QLogic %s PCI to SCSI Host Adapter: bus %d device %d irq %d\n" " Firmware version: %2d.%02d.%02d, Driver version %s", (char *)&bdp->bdName[0], ha->pci_bus, (ha->pci_device_fn & 0xf8) >> 3, host->irq, bdp->fwver[0],bdp->fwver[1],bdp->fwver[2], @@ -1046,8 +1032,8 @@ scsi_lu_t *q; u_long handle; - ENTER("qla1280_queuecommand"); - COMTRACE('C') + /*ENTER("qla1280_queuecommand"); + COMTRACE('C')*/ host = cmd->host; ha = (scsi_qla_host_t *) host->hostdata; @@ -1074,7 +1060,7 @@ { LU_Q(ha, b, t, l) = q; BZERO(q,sizeof(struct scsi_lu)); - DEBUG(sprintf(debug_buff,"Allocate new device queue 0x%x\n",q)); + DEBUG(sprintf(debug_buff,"Allocate new device queue 0x%x\n\r",q)); DEBUG(qla1280_print(debug_buff)); DRIVER_UNLOCK } @@ -1093,15 +1079,13 @@ handle = INVALID_HANDLE; CMD_HANDLE(cmd) = (unsigned char *)handle; - /* Bookkeeping information */ - sp->r_start = jiffies; /* time the request was recieved */ - sp->u_start = 0; - /* add the command to our queue */ ha->qthreads++; qla1280_putq_t(q,sp); - DEBUG(sprintf(debug_buff,"qla1280_queuecmd: queue pid=%d, hndl=0x%x\n\r",cmd->pid,handle)); + DEBUG(sprintf(debug_buff, + "qla1280_QC: t=%x CDB=%x I/OSize=0x%x haQueueCount=0x%x\n\r", + t,cmd->cmnd[0],CMD_XFRLEN(cmd),ha->qthreads)); DEBUG(qla1280_print(debug_buff)); /* send command to adapter */ @@ -1111,7 +1095,7 @@ DRIVER_UNLOCK - LEAVE("qla1280_queuecommand"); + /*LEAVE("qla1280_queuecommand");*/ return (0); } @@ -1722,6 +1706,7 @@ scsi_lu_t *q; uint32_t b, t, l; Scsi_Cmnd *cmd; + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) unsigned long cpu_flags = 0; #endif @@ -1738,7 +1723,8 @@ *done_q_last = NULL; else (*done_q_first)->s_prev = NULL; - cmd = sp->cmd; + + cmd = sp->cmd; b = SCSI_BUS_32(cmd); t = SCSI_TCN_32(cmd); l = SCSI_LUN_32(cmd); @@ -1752,8 +1738,6 @@ q->q_flag &= ~QLA1280_QBUSY; } - q->resp_time += jiffies - sp->r_start; /* Lun bookkeeping information */ - q->act_time += jiffies - sp->u_start; q->io_cnt++; if( sp->dir & BIT_5 ) q->r_cnt++; @@ -1776,7 +1760,28 @@ default: break; } - + /* 3.13 64 and 32 bit */ + /* Release memory used for this I/O */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18) + if (cmd->use_sg) { + DEBUG(sprintf(debug_buff, + "S/G unmap_sg cmd=%x\n\r",cmd);) + DEBUG(qla1280_print(debug_buff)); + pci_unmap_sg(ha->pdev, cmd->request_buffer, + cmd->use_sg, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); + } + else if (cmd->request_bufflen) { + DEBUG(sprintf(debug_buff, + "No S/G unmap_single cmd=%x saved_dma_handle=%lx\n\r", + cmd,sp->saved_dma_handle);) + DEBUG(qla1280_print(debug_buff);) + + pci_unmap_single(ha->pdev,sp->saved_dma_handle, + cmd->request_bufflen, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); + } +#endif /* Call the mid-level driver interrupt handler */ CMD_HANDLE(sp->cmd) = (unsigned char *) 0; ha->actthreads--; @@ -1790,8 +1795,6 @@ qla1280_next(ha, q, b); } DRIVER_UNLOCK - - COMTRACE('d') LEAVE("qla1280_done"); } @@ -1963,7 +1966,7 @@ if (q->q_outcnt >= ha->bus_settings[b].hiwat) q->q_flag |= QLA1280_QBUSY; -#if QLA1280_64BIT_SUPPORT +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18) if (ha->flags.enable_64bit_addressing) status = qla1280_64bit_start_scsi(ha, sp); else @@ -1980,7 +1983,7 @@ /* Wait for 30 sec for command to be accepted. */ for (cnt = 6000000; cnt; cnt--) { -#if QLA1280_64BIT_SUPPORT +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18) if (ha->flags.enable_64bit_addressing) status = qla1280_64bit_start_scsi(ha, sp); else @@ -2071,7 +2074,7 @@ ENTER("qla1280_putq_t"); #endif DRIVER_LOCK - DEBUG(sprintf(debug_buff,"Adding to device 0x%p<-(0x%p)\n\r",q,sp)); + DEBUG(sprintf(debug_buff,"Adding to device q=0x%p<-(0x%p)sp\n\r",q,sp)); DEBUG(qla1280_print(debug_buff)); sp->s_next = NULL; if (!q->q_first) /* If queue empty */ @@ -2156,28 +2159,33 @@ { uint8_t status = 1; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,18) + dma_addr_t dma_handle; +#endif #ifdef QL_DEBUG_LEVEL_3 ENTER("qla1280_mem_alloc"); #endif -#ifdef DYNAMIC_MEM_ALLOC - ha->request_ring = qla1280_alloc_phys(REQUEST_ENTRY_SIZE * REQUEST_ENTRY_CNT, - &ha->request_dma); - if(ha->request_ring) { - ha->response_ring = qla1280_alloc_phys(RESPONSE_ENTRY_SIZE * RESPONSE_ENTRY_CNT, - &ha->response_dma); - if(ha->response_ring) { - status = 0; - } - } -#else + /* 3.13 */ + /* get consistent memory allocated for request and response rings */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) ha->request_ring = &ha->req[0]; ha->request_dma = VIRT_TO_BUS(&ha->req[0]); ha->response_ring = &ha->res[0]; ha->response_dma = VIRT_TO_BUS(&ha->res[0]); status = 0; -#endif +#else + ha->request_ring = pci_alloc_consistent(ha->pdev, + ((REQUEST_ENTRY_CNT+1)*(sizeof(request_t))), + &dma_handle); + ha->request_dma = dma_handle; + ha->response_ring = pci_alloc_consistent(ha->pdev, + ((RESPONSE_ENTRY_CNT+1)*(sizeof(response_t))), + &dma_handle); + ha->response_dma = dma_handle; + status = 0; +#endif if(status) { #if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) @@ -2221,6 +2229,16 @@ ha->dev[b] = (scsi_lu_t *)NULL; } + /* 3.13 */ + /* free consistent memory allocated for request and response rings */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18) + pci_free_consistent(ha->pdev, ((REQUEST_ENTRY_CNT+1)*(sizeof(request_t))), + ha->request_ring, ha->request_dma); + + pci_free_consistent(ha->pdev,((RESPONSE_ENTRY_CNT+1)*(sizeof(response_t))), + ha->response_ring, ha->response_dma); +#endif + LEAVE("qlc1280_mem_free"); } @@ -2481,7 +2499,7 @@ /* Verify checksum of loaded RISC code. */ mb[0] = MBC_VERIFY_CHECKSUM; /* mb[1] = ql12_risc_code_addr01; */ - mb[1] = *QLBoardTbl[ha->devnum].fwstart; + mb[1] = *QL1280BoardTbl[ha->devnum].fwstart; if (!(status = qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]))) { @@ -2491,7 +2509,7 @@ #endif mb[0] = MBC_EXECUTE_FIRMWARE; /* mb[1] = ql12_risc_code_addr01; */ - mb[1] = *QLBoardTbl[ha->devnum].fwstart; + mb[1] = *QL1280BoardTbl[ha->devnum].fwstart; qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]); } else @@ -2526,18 +2544,69 @@ qla1280_pci_config(scsi_qla_host_t *ha) { uint8_t status = 1; - uint32_t command; #if MEMORY_MAPPED_IO uint32_t page_offset, base; uint32_t mmapbase; #endif - config_reg_t *creg = 0; uint16_t buf_wd; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) + uint32_t command; + config_reg_t *creg = 0; +#endif + ENTER("qla1280_pci_config"); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18) + /* + * Set Bus Master Enable, Memory Address Space Enable and + * reset any error bits, in the command register. + */ + pci_read_config_word(ha->pdev, PCI_COMMAND, &buf_wd); + buf_wd &= ~0x7; +#if MEMORY_MAPPED_IO + DEBUG(printk("qla1280: MEMORY MAPPED IO is enabled.\n")); + buf_wd |= BIT_2 + BIT_1 + BIT_0; +#else + buf_wd |= BIT_2 + BIT_0; +#endif + pci_write_config_word(ha->pdev, PCI_COMMAND, buf_wd); + /* + * Reset expansion ROM address decode enable. + */ + pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &buf_wd); + buf_wd &= ~PCI_ROM_ADDRESS_ENABLE; + pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, buf_wd); +#if MEMORY_MAPPED_IO + /* + * Get memory mapped I/O address. + */ + pci_read_config_word(ha->pdev, PCI_BASE_ADDRESS_1, &mmapbase); + mmapbase &= PCI_BASE_ADDRESS_MEM_MASK; + + /* + * Find proper memory chunk for memory map I/O reg. + */ + base = mmapbase & PAGE_MASK; + page_offset = mmapbase - base; + /* + * Get virtual address for I/O registers. + */ + ha->mmpbase = ioremap_nocache(base, page_offset + 256); + if( ha->mmpbase ) + { + ha->mmpbase += page_offset; + /* ha->iobase = ha->mmpbase; */ + status = 0; + } +#else /* MEMORY_MAPPED_IO */ + status = 0; +#endif /* MEMORY_MAPPED_IO */ + +#else /*LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) */ + /* Get command register. */ - if (pci_read_config_word(ha->pdev,OFFSET(creg->command), &buf_wd) == PCIBIOS_SUCCESSFUL) + if (pcibios_read_config_word(ha->pci_bus,ha->pci_device_fn, OFFSET(creg->command), &buf_wd) == PCIBIOS_SUCCESSFUL) { command = buf_wd; /* @@ -2551,20 +2620,20 @@ #else buf_wd |= BIT_2 + BIT_0; #endif - if( pci_write_config_word(ha->pdev,OFFSET(creg->command), buf_wd) ) + if( pcibios_write_config_word(ha->pci_bus,ha->pci_device_fn, OFFSET(creg->command), buf_wd) ) { printk(KERN_WARNING "qla1280: Could not write config word.\n"); } /* Get expansion ROM address. */ - if (pci_read_config_word(ha->pdev,OFFSET(creg->expansion_rom), &buf_wd) == PCIBIOS_SUCCESSFUL) + if (pcibios_read_config_word(ha->pci_bus,ha->pci_device_fn, OFFSET(creg->expansion_rom), &buf_wd) == PCIBIOS_SUCCESSFUL) { /* Reset expansion ROM address decode enable. */ buf_wd &= ~BIT_0; - if (pci_write_config_word(ha->pdev,OFFSET(creg->expansion_rom), buf_wd) == PCIBIOS_SUCCESSFUL) + if (pcibios_write_config_word(ha->pci_bus,ha->pci_device_fn, OFFSET(creg->expansion_rom), buf_wd) == PCIBIOS_SUCCESSFUL) { #if MEMORY_MAPPED_IO /* Get memory mapped I/O address. */ - pci_read_config_dword(ha->pdev,OFFSET(cfgp->mem_base_addr), &mmapbase); + pcibios_read_config_dword(ha->pci_bus, ha->pci_device_fn,OFFSET(cfgp->mem_base_addr), &mmapbase); mmapbase &= PCI_BASE_ADDRESS_MEM_MASK; /* Find proper memory chunk for memory map I/O reg. */ @@ -2588,6 +2657,7 @@ } } } +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18) */ LEAVE("qla1280_pci_config"); return(status); @@ -2718,6 +2788,7 @@ * Returns: * 0 = success. */ +#define DUMP_IT_BACK 0 /* for debug of RISC loading */ STATIC uint8_t qla1280_setup_chip(scsi_qla_host_t *ha) { @@ -2726,37 +2797,52 @@ uint16_t *risc_code_address; long risc_code_size; uint16_t mb[MAILBOX_REGISTER_COUNT]; -#ifdef QLA1280_UNUSED - uint8_t *sp; - int i; -#endif uint16_t cnt; int num; +#if DUMP_IT_BACK + int i; + uint8_t *sp; uint8_t *tbuf; - u_long p_tbuf; +#if BITS_PER_LONG > 32 + dma_addr_t p_tbuf; +#else + uint32_t p_tbuf; +#endif +#endif #ifdef QL_DEBUG_LEVEL_3 ENTER("qla1280_setup_chip"); #endif - if( (tbuf = (uint8_t *)KMALLOC(8000) ) == NULL ) - { - printk("setup_chip: couldn't alloacte memory\n"); - return(1); - } - p_tbuf = VIRT_TO_BUS(tbuf); + /* 3.13 */ +#if DUMP_IT_BACK +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) + if( (tbuf = (uint8_t *)KMALLOC(8000) ) == NULL ) + { + printk("setup_chip: couldn't alloacte memory\n"); + return(1); + } + p_tbuf = VIRT_TO_BUS(tbuf); +#else + /* get consistent memory allocated for setup_chip */ + tbuf = pci_alloc_consistent(ha->pdev, 8000, &p_tbuf); +#endif +#endif + /* Load RISC code. */ /* risc_address = ql12_risc_code_addr01; risc_code_address = &ql12_risc_code01[0]; risc_code_size = ql12_risc_code_length01; */ - risc_address = *QLBoardTbl[ha->devnum].fwstart; - risc_code_address = QLBoardTbl[ha->devnum].fwcode; - risc_code_size = (long)(*QLBoardTbl[ha->devnum].fwlen & 0xffff); - - DEBUG(printk("qla1280: DMAing RISC code (%d) words.\n",(int)risc_code_size)); - DEBUG(sprintf(debug_buff,"qla1280_setup_chip: Loading RISC code size =(%ld).\n\r",risc_code_size);) + risc_address = *QL1280BoardTbl[ha->devnum].fwstart; + risc_code_address = QL1280BoardTbl[ha->devnum].fwcode; + risc_code_size = (long)(*QL1280BoardTbl[ha->devnum].fwlen & 0xffff); + + DEBUG(printk("qla1280_setup_chip: DMA RISC code (%d) words\n", + (int)risc_code_size)); + DEBUG(sprintf(debug_buff, + "qla1280_setup_chip: DMA RISC code (%d) words\n\r",risc_code_size);) DEBUG(qla1280_print(debug_buff)); num =0; while (risc_code_size > 0 && !status) @@ -2766,29 +2852,31 @@ if ( cnt > risc_code_size ) cnt = risc_code_size; - DEBUG(sprintf(debug_buff,"qla1280_setup_chip: loading risc @ =(0x%p),%d,%d(0x%x).\n\r",risc_code_address,cnt,num,risc_address);) + DEBUG(sprintf(debug_buff, + "qla1280_setup_chip: loading risc @ =(0x%p),%d,%d(0x%x).\n\r", + risc_code_address,cnt,num,risc_address);) DEBUG(qla1280_print(debug_buff)); - DEBUG(printk("qla1280_setup_chip: loading risc @ =code=(0x%p),cnt=%d,seg=%d,addr=0x%x\n\r",risc_code_address,cnt,num,risc_address)); - BCOPY((caddr_t) risc_code_address,(caddr_t) ha->request_ring, (cnt <<1)); + BCOPY((caddr_t) risc_code_address,(caddr_t) ha->request_ring, + (cnt <<1)); + + flush_cache_all(); + mb[0] = MBC_LOAD_RAM; - /* mb[0] = MBC_LOAD_RAM_A64; */ mb[1] = risc_address; mb[4] = cnt; mb[3] = (uint16_t) ha->request_dma & 0xffff; mb[2] = (uint16_t) (ha->request_dma >> 16) & 0xffff; mb[7] = (uint16_t) (MS_64BITS(ha->request_dma) & 0xffff); mb[6] = (uint16_t) (MS_64BITS(ha->request_dma) >> 16) & 0xffff; - DEBUG(printk("qla1280_setup_chip: op=%d 0x%lx = 0x%4x,0x%4x,0x%4x,0x%4x\n",mb[0],ha->request_dma,mb[6],mb[7],mb[2],mb[3])); + DEBUG(printk("qla1280_setup_chip: op=%d 0x%p = 0x%4x,0x%4x,0x%4x,0x%4x\n",mb[0],ha->request_dma,mb[6],mb[7],mb[2],mb[3])); if( (status = qla1280_mailbox_command(ha, BIT_4|BIT_3|BIT_2|BIT_1|BIT_0, &mb[0])) ) { printk("Failed to load partial segment of f/w\n"); break; } - /* dump it back */ - -#if 0 - mb[0] = MBC_DUMP_RAM_A64; +#if DUMP_IT_BACK + mb[0] = MBC_READ_RAM_WORD; mb[1] = risc_address; mb[4] = cnt; mb[3] = (uint16_t) p_tbuf & 0xffff; @@ -2796,10 +2884,13 @@ mb[7] = (uint16_t) (p_tbuf >> 32) & 0xffff; mb[6] = (uint16_t) (p_tbuf >> 48) & 0xffff; - if( (status = qla1280_mailbox_command(ha, BIT_4|BIT_3|BIT_2|BIT_1|BIT_0, - &mb[0])) ) + if( (status = qla1280_mailbox_command(ha, + BIT_4|BIT_3|BIT_2|BIT_1|BIT_0,&mb[0])) ) { printk("Failed to dump partial segment of f/w\n"); + DEBUG(sprintf(debug_buff, + "setup_chip: Failed to dump partial segment of f/w\n\r");) + DEBUG(qla1280_print(debug_buff)); break; } sp = (uint8_t *)ha->request_ring; @@ -2807,51 +2898,20 @@ { if( tbuf[i] != sp[i] ) { - printk("qla1280 : firmware compare error @ byte (0x%x)\n",i); - break; + printk("qla1280_setup_chip: FW compare error @ byte(0x%x) loop#=%x\n",i,num); + printk("setup_chip: FWbyte=%x FWfromChip=%x\n",sp[i],tbuf[i]); + DEBUG(sprintf(debug_buff, + "qla1280_setup_chip: FW compare error @ byte(0x%x) loop#=%x\n\r",i);) + DEBUG(qla1280_print(debug_buff);) + /*break;*/ } } - #endif risc_address += cnt; risc_code_size = risc_code_size - cnt; risc_code_address = risc_code_address + cnt; num++; } -#ifdef QLA1280_UNUSED - DEBUG(ql_debug_print = 0;) - { - for (i = 0; i < ql12_risc_code_length01; i++) - { - mb[0] = 0x4; - mb[1] = ql12_risc_code_addr01 + i; - mb[2] = ql12_risc_code01[i]; - - status = qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, - &mb[0]); - if (status) - { - printk("qla1280 : firmware load failure\n"); - break; - } - - mb[0] = 0x5; - mb[1] = ql12_risc_code_addr01 + i; - mb[2] = 0; - - status = qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, - &mb[0]); - if (status) - { - printk("qla1280 : firmware dump failure\n"); - break; - } - if( mb[2] != ql12_risc_code01[i] ) - printk("qla1280 : firmware compare error @ (0x%x)\n",ql12_risc_code_addr01+i); - } - } - DEBUG(ql_debug_print = 1;) -#endif /* Verify checksum of loaded RISC code. */ if (!status) @@ -2859,22 +2919,29 @@ DEBUG(printk("qla1280_setup_chip: Verifying checksum of loaded RISC code.\n");) mb[0] = MBC_VERIFY_CHECKSUM; /* mb[1] = ql12_risc_code_addr01; */ - mb[1] = *QLBoardTbl[ha->devnum].fwstart; + mb[1] = *QL1280BoardTbl[ha->devnum].fwstart; if (!(status = qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]))) { /* Start firmware execution. */ DEBUG(qla1280_print("qla1280_setup_chip: start firmware running.\n\r");) mb[0] = MBC_EXECUTE_FIRMWARE; - /* mb[1] = ql12_risc_code_addr01; */ - mb[1] = *QLBoardTbl[ha->devnum].fwstart; + mb[1] = *QL1280BoardTbl[ha->devnum].fwstart; qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]); } else printk("qla1280_setup_chip: Failed checksum.\n"); } - KMFREE(tbuf,8000); + /* 3.13 */ +#if DUMP_IT_BACK +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) + KMFREE(tbuf,8000); +#else + /* free consistent memory allocated for setup_chip */ + pci_free_consistent(ha->pdev, 8000, tbuf, p_tbuf); +#endif +#endif #if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) if (status) @@ -3151,10 +3218,28 @@ /* Disable RISC load of firmware. */ ha->flags.disable_risc_code_load = nv->cntr_flags_1.disable_loading_risc_code; + /* Enable 64bit addressing. */ ha->flags.enable_64bit_addressing = nv->cntr_flags_1.enable_64bit_addressing; +#if FORCE_64BIT_PCI_DMA + ha->flags.enable_64bit_addressing = 1; +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18) + if (ha->flags.enable_64bit_addressing) { + printk("[[[ qla1x160: 64 Bit PCI Addressing Enabled ]]]\n"); + +#if BITS_PER_LONG > 32 + /* Update our PCI device dma_mask for full 64 bit mask */ + //ha->pdev->dma_mask = (pci_dma_t) 0xffffffffffffffffull; + ha->pdev->dma_mask = 0xffffffffffffffff; + +#endif + } +#endif + /* Set ISP hardware DMA burst */ mb[0] = nv->isp_config.c; WRT_REG_WORD(®->cfg_1, mb[0]); @@ -3837,7 +3922,7 @@ #endif } -#if QLA1280_64BIT_SUPPORT +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,18) /* * qla1280_64bit_start_scsi * The start SCSI is responsible for building request packets on @@ -3862,10 +3947,13 @@ uint16_t seg_cnt; struct scatterlist *sg = (struct scatterlist *) NULL; uint32_t *dword_ptr; + dma_addr_t dma_handle; -#ifdef QL_DEBUG_LEVEL_3 ENTER("qla1280_64bit_start_scsi:"); -#endif + + DEBUG(sprintf(debug_buff, + "64bit_start: cmd=%x sp=%x CDB=%x\n\r",cmd,sp,cmd->cmnd[0]);) + DEBUG(qla1280_print(debug_buff)); if( qla1280_check_for_dead_scsi_bus(ha, sp) ) { @@ -3876,9 +3964,10 @@ seg_cnt = 0; req_cnt = 1; if (cmd->use_sg) - { - seg_cnt = cmd->use_sg; + { /* 3.13 64 bit */ sg = (struct scatterlist *) cmd->request_buffer; + seg_cnt = pci_map_sg(ha->pdev,sg,cmd->use_sg, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); if (seg_cnt > 2) { @@ -3889,7 +3978,7 @@ } else if (cmd->request_bufflen) /* If data transfer. */ { - DEBUG(printk("Single data transfer (0x%x)\n",cmd->request_bufflen)); + DEBUG(printk("Single data transfer len=0x%x\n",cmd->request_bufflen)); seg_cnt = 1; } @@ -3950,7 +4039,7 @@ /* Load SCSI command packet. */ pkt->cdb_len = (uint16_t)CMD_CDBLEN(cmd); BCOPY(&(CMD_CDBP(cmd)), pkt->scsi_cdb, pkt->cdb_len); - DEBUG(printk("Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0])); + //DEBUG(printk("Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0])); /* * Load data segments. @@ -3976,12 +4065,17 @@ /* Load command entry data segments. */ for (cnt = 0; cnt < 2 && seg_cnt; cnt++, seg_cnt--) { - DEBUG(sprintf(debug_buff,"SG Segment ap=0x%p, len=0x%x\n\r",sg->address,sg->length)); - DEBUG(qla1280_print(debug_buff)); - *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_LOW(sg->address)); - *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_HIGH(sg->address)); - *dword_ptr++ = sg->length; + /* 3.13 64 bit */ + *dword_ptr++ = cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))); + *dword_ptr++ = cpu_to_le32(pci_dma_hi32(sg_dma_address(sg))); + *dword_ptr++ = cpu_to_le32(sg_dma_len(sg)); sg++; + DEBUG(sprintf(debug_buff, + "S/G Segment phys_addr=%x %x, len=0x%x\n\r", + cpu_to_le32(pci_dma_hi32(sg_dma_address(sg))), + cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))), + cpu_to_le32(sg_dma_len(sg)));) + DEBUG(qla1280_print(debug_buff)); } #ifdef QL_DEBUG_LEVEL_5 qla1280_print( @@ -3998,6 +4092,10 @@ /* * Build continuation packets. */ + DEBUG(sprintf(debug_buff, + "S/G Building Continuation...seg_cnt=0x%x remains\n\r", + seg_cnt);) + DEBUG(qla1280_print(debug_buff)); while (seg_cnt > 0) { /* Adjust ring index. */ @@ -4031,10 +4129,17 @@ /* Load continuation entry data segments. */ for (cnt = 0; cnt < 5 && seg_cnt; cnt++, seg_cnt--) { - *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_LOW(sg->address)); - *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_HIGH(sg->address)); - *dword_ptr++ = sg->length; - sg++; + /* 3.13 64 bit */ + *dword_ptr++ = cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))); + *dword_ptr++ = cpu_to_le32(pci_dma_hi32(sg_dma_address(sg))); + *dword_ptr++ = cpu_to_le32(sg_dma_len(sg)); + DEBUG(sprintf(debug_buff, + "S/G Segment Cont. phys_addr=%x %x, len=0x%x\n\r", + cpu_to_le32(pci_dma_hi32(sg_dma_address(sg))), + cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))), + cpu_to_le32(sg_dma_len(sg)));) + DEBUG(qla1280_print(debug_buff)); + sg++; } #ifdef QL_DEBUG_LEVEL_5 qla1280_print( @@ -4051,11 +4156,21 @@ #endif } } - else /* No scatter gather data transfer */ - { - *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_LOW(cmd->request_buffer)); - *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_HIGH(cmd->request_buffer)); - *dword_ptr = (uint32_t) cmd->request_bufflen; + else /* No scatter gather data transfer */ + { /* 3.13 64 bit */ + dma_handle = pci_map_single(ha->pdev, + cmd->request_buffer, + cmd->request_bufflen, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); + /* save dma_handle for pci_unmap_single */ + sp->saved_dma_handle = dma_handle; + + *dword_ptr++ = cpu_to_le32(pci_dma_lo32(dma_handle)); + *dword_ptr++ = cpu_to_le32(pci_dma_hi32(dma_handle)); + *dword_ptr = (uint32_t) cmd->request_bufflen; + DEBUG(sprintf(debug_buff, + "No S/G map_single saved_dma_handle=%lx\n\r",dma_handle)); + DEBUG(qla1280_print(debug_buff)); #ifdef QL_DEBUG_LEVEL_5 qla1280_print( "qla1280_64bit_start_scsi: No scatter/gather command packet data - c"); @@ -4070,12 +4185,12 @@ #endif } } -#ifdef QL_DEBUG_LEVEL_5 - else /* No data transfer */ + else /* No data transfer */ { *dword_ptr++ = (uint32_t) 0; *dword_ptr++ = (uint32_t) 0; *dword_ptr = (uint32_t) 0; +#ifdef QL_DEBUG_LEVEL_5 qla1280_print( "qla1280_64bit_start_scsi: No data, command packet data - c"); qla1280_print(" b "); @@ -4086,8 +4201,8 @@ qla1280_output_number((uint32_t)SCSI_LUN_32(cmd), 10); qla1280_print("\n\r"); qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE); - } #endif + } /* Adjust ring index. */ ha->req_ring_index++; if (ha->req_ring_index == REQUEST_ENTRY_CNT) @@ -4139,7 +4254,7 @@ #endif return(status); } -#endif /* QLA1280_64BIT_SUPPORT */ +#endif /* * qla1280_32bit_start_scsi @@ -4174,8 +4289,15 @@ uint8_t *data_ptr; uint32_t *dword_ptr; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18) + dma_addr_t dma_handle; +#endif + ENTER("qla1280_32bit_start_scsi"); + DEBUG(sprintf(debug_buff, + "32bit_start: cmd=%x sp=%x CDB=%x\n\r",cmd,sp,cmd->cmnd[0]);) + DEBUG(qla1280_print(debug_buff)); if( qla1280_check_for_dead_scsi_bus(ha, sp) ) { @@ -4192,8 +4314,15 @@ * differences and the kernel SG list uses virtual addresses where * we need physical addresses. */ - seg_cnt = cmd->use_sg; sg = (struct scatterlist *) cmd->request_buffer; + /* 3.13 32 bit */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) + seg_cnt = cmd->use_sg; +#else + seg_cnt = pci_map_sg(ha->pdev,sg,cmd->use_sg, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); +#endif + /* * if greater than four sg entries then we need to allocate * continuation entries @@ -4204,17 +4333,22 @@ if ((uint16_t)(seg_cnt - 4) % 7) req_cnt++; } - DEBUG(sprintf(debug_buff,"S/G for data transfer -num segs(%d), req blk cnt(%d)\n\r",seg_cnt,req_cnt)); + DEBUG(sprintf(debug_buff, + "S/G Transfer cmd=%x seg_cnt=0x%x, req_cnt=%x\n\r", + cmd,seg_cnt,req_cnt)); DEBUG(qla1280_print(debug_buff)); } else if (cmd->request_bufflen) /* If data transfer. */ { - DEBUG(printk("Single data transfer (0x%x)\n",cmd->request_bufflen)); + DEBUG(sprintf(debug_buff, + "No S/G transfer t=%x cmd=%x len=%x CDB=%x\n\r", + SCSI_TCN_32(cmd),cmd,cmd->request_bufflen,cmd->cmnd[0])); + DEBUG(qla1280_print(debug_buff)); seg_cnt = 1; } else { - DEBUG(printk("No data transfer \n")); + //DEBUG(printk("No data transfer \n")); seg_cnt = 0; } @@ -4231,7 +4365,8 @@ ha->req_q_cnt = REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt); } - DEBUG(sprintf(debug_buff,"Number of free entries = (%d)\n\r",ha->req_q_cnt)); + DEBUG(sprintf(debug_buff,"Number of free entries=(%d) seg_cnt=0x%x\n\r", + ha->req_q_cnt,seg_cnt)); DEBUG(qla1280_print(debug_buff)); /* If room for request in request ring. */ if ((uint16_t)(req_cnt + 2) < ha->req_q_cnt) @@ -4279,20 +4414,15 @@ data_ptr = (uint8_t *) &(CMD_CDBP(cmd)); for (cnt = 0; cnt < pkt->cdb_len; cnt++) pkt->scsi_cdb[cnt] = *data_ptr++; - DEBUG(printk("Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0])); + //DEBUG(printk("Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0])); /* * Load data segments. */ if (seg_cnt) { - DEBUG(printk("loading data segments..\n")); /* Set transfer direction (READ and WRITE) */ /* Linux doesn't tell us */ - /* - * 3/10 dg - Normally, we should need this check with our F/W - * but because of a small issue with it we do. - * * For block devices, cmd->request.cmd has the operation * For character devices, this isn't always set properly, so * we need to check data_cmnd[0]. This catches the conditions @@ -4318,15 +4448,32 @@ /* Load command entry data segments. */ for (cnt = 0; cnt < 4 && seg_cnt; cnt++, seg_cnt--) { + /* 3.13 32 bit */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) *dword_ptr++ = (uint32_t) cpu_to_le32(VIRT_TO_BUS(sg->address)); *dword_ptr++ = sg->length; - DEBUG(sprintf(debug_buff,"SG Segment ap=0x%p, len=0x%x\n\r",sg->address,sg->length)); + DEBUG(sprintf(debug_buff, + "S/G Segment phys_addr=0x%x, len=0x%x\n\r", + cpu_to_le32(VIRT_TO_BUS(sg->address)),sg->length)); + DEBUG(qla1280_print(debug_buff)); +#else + *dword_ptr++ = cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))); + *dword_ptr++ = cpu_to_le32(sg_dma_len(sg)); + DEBUG(sprintf(debug_buff, + "S/G Segment phys_addr=0x%x, len=0x%x\n\r", + cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))), + cpu_to_le32(sg_dma_len(sg)));) DEBUG(qla1280_print(debug_buff)); +#endif sg++; } /* * Build continuation packets. */ + DEBUG(sprintf(debug_buff, + "S/G Building Continuation...seg_cnt=0x%x remains\n\r", + seg_cnt);) + DEBUG(qla1280_print(debug_buff)); while (seg_cnt > 0) { /* Adjust ring index. */ @@ -4361,9 +4508,25 @@ /* Load continuation entry data segments. */ for (cnt = 0; cnt < 7 && seg_cnt; cnt++, seg_cnt--) { - *dword_ptr++ = (u_int) cpu_to_le32(VIRT_TO_BUS(sg->address)); - *dword_ptr++ = sg->length; - sg++; + /* 3.13 32 bit */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) + *dword_ptr++ = (u_int) cpu_to_le32(VIRT_TO_BUS(sg->address)); + *dword_ptr++ = sg->length; + DEBUG(sprintf(debug_buff, + "S/G Segment Cont. phys_addr=0x%x, len=0x%x\n\r", + cpu_to_le32(pci_dma_lo32(VIRT_TO_BUS(sg->address))), + sg->length);) + DEBUG(qla1280_print(debug_buff)); +#else + *dword_ptr++ = cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))); + *dword_ptr++ = cpu_to_le32(sg_dma_len(sg)); + DEBUG(sprintf(debug_buff, + "S/G Segment Cont. phys_addr=0x%x, len=0x%x\n\r", + cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))), + cpu_to_le32(sg_dma_len(sg)));) + DEBUG(qla1280_print(debug_buff)); +#endif + sg++; } #ifdef QL_DEBUG_LEVEL_5 qla1280_print( @@ -4378,14 +4541,28 @@ #endif } } - else /* No scatter gather data transfer */ + else /* No S/G data transfer */ { + /* 3.13 32 bit */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) *dword_ptr++ = (uint32_t) cpu_to_le32(VIRT_TO_BUS(cmd->request_buffer)); *dword_ptr = (uint32_t) cmd->request_bufflen; - DEBUG(printk("Single Segment ap=0x%p, len=0x%x\n",cmd->request_buffer,cmd->request_bufflen)); +#else + dma_handle = pci_map_single(ha->pdev, + cmd->request_buffer, + cmd->request_bufflen, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); + sp->saved_dma_handle = dma_handle; + + *dword_ptr++ = cpu_to_le32(pci_dma_lo32(dma_handle)); + *dword_ptr = (uint32_t) cmd->request_bufflen; + DEBUG(sprintf(debug_buff, + "No S/G map_single saved_dma_handle=%lx\n\r",dma_handle)); + DEBUG(qla1280_print(debug_buff)); +#endif } } - else /* No data transfer */ + else /* No data transfer at all */ { *dword_ptr++ = (uint32_t) 0; *dword_ptr = (uint32_t) 0; @@ -4413,7 +4590,6 @@ /* Set chip new ring index. */ DEBUG(qla1280_print("qla1280_32bit_start_scsi: Wakeup RISC for pending command\n\r")); ha->qthreads--; - sp->u_start = jiffies; sp->flags |= SRB_SENT; ha->actthreads++; /* qla1280_output_number((uint32_t)ha->actthreads++, 16); */ @@ -4424,7 +4600,7 @@ status = 1; #ifdef QL_DEBUG_LEVEL_2 qla1280_print( - "qla1280_32bit_start_scsi: NO ROOM IN OUTSTANDING ARRAY\n\r"); + "qla1280_32bit_start_scsi: NO ROOM IN OUTSTANDING ARRAY\n\r"); qla1280_print(" req_q_cnt="); qla1280_output_number((uint32_t)ha->req_q_cnt, 16); qla1280_print("\n\r"); @@ -4458,6 +4634,7 @@ return(status); } + /* * qla1280_req_pkt * Function is responsible for locking ring and @@ -4888,7 +5065,7 @@ { device_reg_t *reg = ha->iobase; response_t *pkt; - srb_t *sp; + srb_t *sp = 0; uint16_t mailbox[MAILBOX_REGISTER_COUNT]; uint16_t *wptr; uint32_t index; @@ -4902,9 +5079,11 @@ /* Check for mailbox interrupt. */ mailbox[0] = RD_REG_WORD(®->semaphore); + if (mailbox[0] & BIT_0) { /* Get mailbox data. */ + //DEBUG(qla1280_print("qla1280_isr: In Get mailbox data \n\r");) wptr = &mailbox[0]; *wptr++ = RD_REG_WORD(®->mailbox0); @@ -4937,7 +5116,7 @@ { case MBA_SCSI_COMPLETION: /* Response completion */ #ifdef QL_DEBUG_LEVEL_5 - qla1280_print("qla1280_isr: mailbox response completion\n\r"); + qla1280_print("qla1280_isr: mailbox SCSI response completion\n\r"); #endif if (ha->flags.online) { @@ -4966,9 +5145,11 @@ else (*done_q_last)->s_next = sp; *done_q_last = sp; + } else { + #ifdef QL_DEBUG_LEVEL_2 qla1280_print("qla1280_isr: ISP invalid handle\n\r"); #endif @@ -5040,6 +5221,7 @@ #endif break; default: + //DEBUG(qla1280_print("qla1280_isr: default case of switch MB \n\r");) if (mailbox[0] < MBA_ASYNC_EVENT) { wptr = &mailbox[0]; @@ -5056,9 +5238,9 @@ break; } } - else + else { WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); - + } /* * Response ring */ @@ -5122,6 +5304,7 @@ qla1280_error_entry(ha, pkt, done_q_first, done_q_last); + /* Adjust ring index. */ ha->rsp_ring_index++; if (ha->rsp_ring_index == RESPONSE_ENTRY_CNT) @@ -5305,9 +5488,12 @@ } pkt->scsi_status = S_CKCON; pkt->option_flags |= (uint32_t)OF_SSTS | (uint32_t)OF_NO_DATA; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18) if (ha->flags.enable_64bit_addressing) qla1280_64bit_continue_io(ha, pkt, 0, 0); else +#endif qla1280_32bit_continue_io(ha, pkt, 0, 0); break; case 0x16: /* Requested Capability Not Available */ @@ -5666,10 +5852,12 @@ (uint32_t)OF_NO_DATA; break; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18) if (ha->flags.enable_64bit_addressing) - qla1280_64bit_continue_io(ha, pkt, len, (paddr32_t *)&phy_addr); + qla1280_64bit_continue_io(ha, pkt, len, (paddr32_t *)&phy_addr); else - qla1280_32bit_continue_io(ha, pkt, len, (paddr32_t *)&phy_addr); +#endif + qla1280_32bit_continue_io(ha, pkt, len, (paddr32_t *)&phy_addr); break; default: break; @@ -5743,11 +5931,13 @@ ha->outstanding_cmds[pkt->handle] = 0; cp = sp->cmd; + /* Generate LU queue on cntrl, target, LUN */ b = SCSI_BUS_32(cp); t = SCSI_TCN_32(cp); l = SCSI_LUN_32(cp); q = LU_Q(ha, b, t, l); + if( pkt->comp_status || pkt->scsi_status ) { DEBUG(qla1280_print( "scsi: comp_status = ");) @@ -5878,7 +6068,7 @@ /* Place command on done queue. */ qla1280_done_q_put(sp, done_q_first, done_q_last); } -#if QLA1280_64BIT_SUPPORT +#if BITS_PER_LONG > 32 else if (pkt->entry_type == COMMAND_A64_TYPE) { #ifdef QL_DEBUG_LEVEL_2 @@ -5955,7 +6145,6 @@ sp->timeout += 2; */ /* Place request back on top of device queue. */ - /* sp->flags &= ~(SRB_SENT | SRB_TIMEOUT); */ sp->flags = 0; qla1280_putq_t(q, sp); } @@ -6073,7 +6262,7 @@ } } #ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_restart_queues: exiting normally\n"); + qla1280_print("qla1280_restart_queues: exiting normally\n\r"); #endif } @@ -6159,13 +6348,15 @@ return(ret); } - -/* - * Declarations for load module - */ -static Scsi_Host_Template driver_template = QLA1280_LINUX_TEMPLATE; - +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) +#ifdef MODULE +Scsi_Host_Template driver_template = QLA1280_LINUX_TEMPLATE; #include "scsi_module.c" +#endif +#else /* new kernel scsi initialization scheme */ +static Scsi_Host_Template driver_template = QLA1280_LINUX_TEMPLATE; +#include "scsi_module.c" +#endif /************************************************************************ * qla1280_check_for_dead_scsi_bus * @@ -6276,13 +6467,13 @@ #if MEMORY_MAPPED_IO ret = *port; #else - ret = inb((int)port); + ret = inb((long)port); #endif if (ql_debug_print) { qla1280_print("qla1280_getbyte: address = "); - qla1280_output_number((uint32_t)port, 16); + qla1280_output_number((unsigned long)port, 16); qla1280_print(" data = 0x"); qla1280_output_number((uint32_t)ret, 16); qla1280_print("\n\r"); @@ -6302,13 +6493,13 @@ #if MEMORY_MAPPED_IO ret = *port; #else - ret = inw((int)port); + ret = inw((unsigned long)port); #endif if (ql_debug_print) { qla1280_print("qla1280_getword: address = "); - qla1280_output_number((uint32_t)port, 16); + qla1280_output_number((unsigned long)port, 16); qla1280_print(" data = 0x"); qla1280_output_number((uint32_t)ret, 16); qla1280_print("\n\r"); @@ -6328,13 +6519,13 @@ #if MEMORY_MAPPED_IO ret = *port; #else - ret = inl((int)port); + ret = inl((unsigned long)port); #endif if (ql_debug_print) { qla1280_print("qla1280_getdword: address = "); - qla1280_output_number((uint32_t)port, 16); + qla1280_output_number((unsigned long)port, 16); qla1280_print(" data = 0x"); qla1280_output_number((uint32_t)ret, 16); qla1280_print("\n\r"); @@ -6352,13 +6543,13 @@ #if MEMORY_MAPPED_IO *port = data; #else - outb(data, (int)port); + outb(data, (unsigned long)port); #endif if (ql_debug_print) { qla1280_print("qla1280_putbyte: address = "); - qla1280_output_number((uint32_t)port, 16); + qla1280_output_number((unsigned long)port, 16); qla1280_print(" data = 0x"); qla1280_output_number((uint32_t)data, 16); qla1280_print("\n\r"); @@ -6377,14 +6568,14 @@ #ifdef _LINUX_IOPORTS outw(data, (int)port); #else - outw((int)port, data); + outw((unsigned long)port, data); #endif #endif if (ql_debug_print) { qla1280_print("qla1280_putword: address = "); - qla1280_output_number((uint32_t)port, 16); + qla1280_output_number((unsigned long)port, 16); qla1280_print(" data = 0x"); qla1280_output_number((uint32_t)data, 16); qla1280_print("\n\r"); @@ -6403,14 +6594,14 @@ #ifdef _LINUX_IOPORTS outl(data,(int)port); #else - outl((int)port, data); + outl((unsigned long)port, data); #endif #endif if (ql_debug_print) { qla1280_print("qla1280_putdword: address = "); - qla1280_output_number((uint32_t)port, 16); + qla1280_output_number((unsigned long)port, 16); qla1280_print(" data = 0x"); qla1280_output_number((uint32_t)data, 16); qla1280_print("\n\r"); @@ -6434,8 +6625,7 @@ /* * Out character to COM2 port. - * PORT must be at standard address for COM2 = 0x2F8, - * or COM1 = 0x3F8 + * PORT must be at standard address for COM1 = 0x3f8 */ #define OUTB(addr,data) outb((data),(addr)) @@ -6445,7 +6635,7 @@ #ifdef QL_DEBUG_CONSOLE printk("%c", c); #else - int com_addr = 0x2f8; + int com_addr = 0x3f8; int hardware_flow_control = 1; int software_flow_control = 0; uint8_t data; @@ -6457,7 +6647,7 @@ }while (!(data & BIT_6)); /* - * Set BAUD rate for COM2 to 19200 (0x6) + * Set BAUD rate for COM2 to 9600 (0x6) */ /* Select rate divisor. */ @@ -6653,8 +6843,6 @@ qla1280_print(debug_buff); sprintf(debug_buff," Pid=%d, SP=0x%p\n\r", (int)cmd->pid, CMD_SP(cmd)); qla1280_print(debug_buff); - sprintf(debug_buff," r_start=0x%lx, u_start=0x%lx\n\r",sp->r_start,sp->u_start); - qla1280_print(debug_buff); sprintf(debug_buff," underflow size = 0x%x, direction=0x%x, req.cmd=0x%x \n\r", cmd->underflow, sp->dir,cmd->request.cmd); qla1280_print(debug_buff); } @@ -6682,23 +6870,6 @@ } #endif -#ifdef QLA1280_UNUSED -/************************************************************************** - * ql1280_dump_regs - * - **************************************************************************/ -static void qla1280_dump_regs(struct Scsi_Host *host) -{ - printk("Mailbox registers:\n"); - printk("qla1280 : mbox 0 0x%04x \n", inw(host->io_port + 0x70)); - printk("qla1280 : mbox 1 0x%04x \n", inw(host->io_port + 0x72)); - printk("qla1280 : mbox 2 0x%04x \n", inw(host->io_port + 0x74)); - printk("qla1280 : mbox 3 0x%04x \n", inw(host->io_port + 0x76)); - printk("qla1280 : mbox 4 0x%04x \n", inw(host->io_port + 0x78)); - printk("qla1280 : mbox 5 0x%04x \n", inw(host->io_port + 0x7a)); -} -#endif - #if STOP_ON_ERROR @@ -6725,9 +6896,6 @@ printk("HA flags =0x%lx\n", *fp); DEBUG2(ql_debug_print = 1;) /* DEBUG2(ql1280_dump_device((scsi_qla_host_t *) host->hostdata)); */ -#ifdef QLA1280_UNUSED - qla1280_dump_regs(host); -#endif sti(); panic("Ooops"); /* cli(); @@ -6740,11 +6908,6 @@ } #endif -#ifdef QLA1280_UNUSED -static void qla1280_set_flags(char * s) -{ -} -#endif /************************************************************************** * qla1280_setup @@ -6758,24 +6921,6 @@ { char *end, *str, *cp; -#ifdef QLA1280_UNUSED - static struct - { - const char *name; - int siz; - void (*func)(); - int arg; - } options[] = - { - { "dump_regs", 9, &qla1280_dump_regs, 0 - }, - { "verbose", 7, &qla1280_set_flags, 0x1 - }, - { "", 0, NULL, 0 - } - }; -#endif - printk("scsi: Processing Option str = %s\n", s); end = strchr(s, '\0'); /* locate command */ @@ -6824,4 +6969,3 @@ * tab-width: 8 * End: */ - diff -urN linux-2.4.0-test10/drivers/scsi/qla1280.h linux-2.4.0-test10-lia/drivers/scsi/qla1280.h --- linux-2.4.0-test10/drivers/scsi/qla1280.h Mon Sep 18 13:40:13 2000 +++ linux-2.4.0-test10-lia/drivers/scsi/qla1280.h Wed Nov 15 22:17:38 2000 @@ -1,169 +1,35 @@ -/************************************************************************* - * QLOGIC LINUX SOFTWARE - * - * QLogic ISP1x80/1x160 device driver for Linux 2.3.x (redhat 6.x). - * - * COPYRIGHT (C) 1996-2000 QLOGIC CORPORATION - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the Qlogic's Linux Software License. - * - * This program is WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistribution's or source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - *****************************************************************************/ - -/************************************************************************************* - QLOGIC CORPORATION SOFTWARE - "GNU" GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION - AND MODIFICATION - -This GNU General Public License ("License") applies solely to QLogic Linux -Software ("Software") and may be distributed under the terms of this License. - -1. You may copy and distribute verbatim copies of the Software'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 Software a copy of this License along -with the Software. - -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 Software or any portion of it, thus forming -a work based on the Software, 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 Software 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 Software 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 Software under these conditions, and telling the user how to -view a copy of this License. (Exception:if the Software itself is interactive but does -not normally print such an announcement, your work based on the Software 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 Software, 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 Software, 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. - -3. You may copy and distribute the Software (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 Software 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. - -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 Software except as expressly -provided under this License. Any attempt otherwise to copy, modify, sublicense or -distribute the Software 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. This license grants you world wide, royalty free non-exclusive rights to modify or -distribute the Software or its derivative works. These actions are prohibited by law -if you do not accept this License. Therefore, by modifying or distributing the Software -(or any work based on the Software), you indicate your acceptance of this License to do -so, and all its terms and conditions for copying, distributing or modifying the Software -or works based on it. - -6. Each time you redistribute the Software (or any work based on the Software), the -recipient automatically receives a license from the original licensor to copy, distribute -or modify the Software 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 -Software at all. - -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. -NO WARRANTY - -11. THE SOFTWARE IS PROVIDED WITHOUT A WARRANTY OF ANY KIND. THERE IS NO -WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE SOFTWARE "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 SOFTWARE IS WITH YOU. -SHOULD THE SOFTWARE 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 SOFTWARE 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 SOFTWARE (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 SOFTWARE TO -OPERATE WITH ANY OTHER SOFTWARES), EVEN IF SUCH HOLDER OR OTHER PARTY HAS -BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. -END OF TERMS AND CONDITIONS +/******************************************************************************** +* QLOGIC LINUX SOFTWARE +* +* QLogic ISP1280 (Ultra2) /12160 (Ultra3) SCSI driver +* Copyright (C) 2000 Qlogic Corporation +* (www.qlogic.com) +* +* 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. +** +******************************************************************************/ -*************************************************************************************/ - - #ifndef _IO_HBA_QLA1280_H /* wrapper symbol for kernel use */ #define _IO_HBA_QLA1280_H /* subject to change without notice */ + +#ifndef LINUX_VERSION_CODE +#include +#endif /* LINUX_VERSION_CODE not defined */ + #if defined(__cplusplus) extern "C" { #endif -#include - +#ifndef HOSTS_C /* included in hosts.c */ /* * Enable define statement to ignore Data Underrun Errors, * remove define statement to enable detection. @@ -173,15 +39,18 @@ /* * Driver debug definitions. */ -/* #define QL_DEBUG_LEVEL_1 */ /* Output register accesses to COM2. */ -/* #define QL_DEBUG_LEVEL_2 */ /* Output error msgs to COM2. */ -/* #define QL_DEBUG_LEVEL_3 */ /* Output function trace msgs to COM2. */ -/* #define QL_DEBUG_LEVEL_4 */ /* Output NVRAM trace msgs to COM2. */ -/* #define QL_DEBUG_LEVEL_5 */ /* Output ring trace msgs to COM2. */ -/* #define QL_DEBUG_LEVEL_6 */ /* Output WATCHDOG timer trace to COM2. */ -/* #define QL_DEBUG_LEVEL_7 */ /* Output RISC load trace msgs to COM2. */ +/* #define QL_DEBUG_LEVEL_1 */ /* Output register accesses to COM1 */ +/* #define QL_DEBUG_LEVEL_2 */ /* Output error msgs to COM1 */ +/* #define QL_DEBUG_LEVEL_3 */ /* Output function trace msgs to COM1 */ +/* #define QL_DEBUG_LEVEL_4 */ /* Output NVRAM trace msgs to COM1 */ +/* #define QL_DEBUG_LEVEL_5 */ /* Output ring trace msgs to COM1 */ +/* #define QL_DEBUG_LEVEL_6 */ /* Output WATCHDOG timer trace to COM1 */ +/* #define QL_DEBUG_LEVEL_7 */ /* Output RISC load trace msgs to COM1 */ + + #define QL_DEBUG_CONSOLE /* Output to console instead of COM1 */ + /* comment this #define to get output of qla1280_print to COM1 */ + /* if COM1 is not connected to a host system, the driver hangs system! */ -#define QL_DEBUG_CONSOLE /* Output to console instead of COM2. */ #ifndef TRUE # define TRUE 1 @@ -206,7 +75,11 @@ * Locking */ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0) -# include +# if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) +# include +# else +# include +# endif # include # define cpuid smp_processor_id() # if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) @@ -314,12 +187,12 @@ #define WRT_REG_DWORD(addr, data) qla1280_putdword((uint32_t *)addr, data) #else /* QL_DEBUG_LEVEL_1 */ #ifdef MEMORY_MAPPED_IO - #define RD_REG_BYTE(addr) readb((unsigned long) (addr) - #define RD_REG_WORD(addr) readw((unsigned long) (addr) - #define RD_REG_DWORD(addr) readl((unsigned long) (addr) - #define WRT_REG_BYTE(addr, data) writeb((data), (unsigned long) (addr)) - #define WRT_REG_WORD(addr, data) writew((data), (unsigned long) (addr)) - #define WRT_REG_DWORD(addr, data) writel((data), (unsigned long) (addr)) + #define RD_REG_BYTE(addr) (*((volatile uint8_t *)addr)) + #define RD_REG_WORD(addr) (*((volatile uint16_t *)addr)) + #define RD_REG_DWORD(addr) (*((volatile uint32_t *)addr)) + #define WRT_REG_BYTE(addr, data) (*((volatile uint8_t *)addr) = data) + #define WRT_REG_WORD(addr, data) (*((volatile uint16_t *)addr) = data) + #define WRT_REG_DWORD(addr, data) (*((volatile uint32_t *)addr) = data) #else /* MEMORY_MAPPED_IO */ #define RD_REG_BYTE(addr) (inb((unsigned long)addr)) #define RD_REG_WORD(addr) (inw((unsigned long)addr)) @@ -374,7 +247,8 @@ typedef struct timer_list timer_t; /* timer */ /* - * SCSI Request Block structure + * SCSI Request Block structure (sp) that is placed + * on cmd->SCp location of every I/O */ typedef struct srb { @@ -383,10 +257,11 @@ struct srb *s_prev; /* (4) Previous block on LU queue */ uint8_t flags; /* (1) Status flags. */ uint8_t dir; /* direction of transfer */ - uint8_t unused[2]; - u_long r_start; /* jiffies at start of request */ - u_long u_start; /* jiffies when sent to F/W */ -}srb_t; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18) + dma_addr_t saved_dma_handle; /* for unmap of single transfers */ +#endif + +} srb_t; /* * SRB flag definitions @@ -1564,22 +1439,35 @@ request_t req[REQUEST_ENTRY_CNT+1]; response_t res[RESPONSE_ENTRY_CNT+1]; - unsigned long request_dma; /* Physical address. */ +#if BITS_PER_LONG > 32 + dma_addr_t request_dma; /* Physical Address */ +#else + uint32_t request_dma; /* Physical address. */ +#endif request_t *request_ring; /* Base virtual address */ request_t *request_ring_ptr; /* Current address. */ uint16_t req_ring_index; /* Current index. */ uint16_t req_q_cnt; /* Number of available entries. */ - unsigned long response_dma; /* Physical address. */ +#if BITS_PER_LONG > 32 + dma_addr_t response_dma; /* Physical address. */ +#else + uint32_t response_dma; /* Physical address. */ +#endif response_t *response_ring; /* Base virtual address */ response_t *response_ring_ptr; /* Current address. */ uint16_t rsp_ring_index; /* Current index. */ #if QL1280_TARGET_MODE_SUPPORT /* Target buffer and sense data. */ +#if BITS_PER_LONG > 32 + dma_addr_t tbuf_dma; /* Physical address. */ + dma_addr_t tsense_dma; /* Physical address. */ +#else uint32_t tbuf_dma; /* Physical address. */ - tgt_t *tbuf; uint32_t tsense_dma; /* Physical address. */ +#endif + tgt_t *tbuf; uint8_t *tsense; #endif @@ -1616,8 +1504,13 @@ uint32_t dpc :1; /* 15 */ uint32_t dpc_sched :1; /* 16 */ uint32_t interrupts_on :1; /* 17 */ + uint32_t bios_enabled :1; /* 18 */ }flags; + /* needed holders for PCI ordered list of hosts */ + unsigned long io_port; + uint32_t irq; + }scsi_qla_host_t; /* @@ -1646,6 +1539,8 @@ #define QLA1280_RING_LOCK(ha) #define QLA1280_RING_UNLOCK(ha) +#endif /* HOSTS_C */ + #if defined(__cplusplus) } #endif @@ -1663,49 +1558,20 @@ int qla1280_biosparam(Disk *, kdev_t, int[]); void qla1280_intr_handler(int, void *, struct pt_regs *); void qla1280_setup(char *s, int *dummy); -#if defined(__386__) + # define QLA1280_BIOSPARAM qla1280_biosparam -#else -# define QLA1280_BIOSPARAM NULL -#endif /* * Scsi_Host_template (see hosts.h) * Device driver Interfaces to mid-level SCSI driver. */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) -/* This interface is now obsolete !!! */ -#define QLA1280_LINUX_TEMPLATE { \ - next: NULL, \ - usage_count: NULL, \ - proc_dir: NULL, \ - proc_info: NULL, \ - name: "Qlogic ISP 1280", \ - detect: qla1280_detect, \ - release: qla1280_release, \ - info: qla1280_info, \ - command: NULL, \ - queuecommand: qla1280_queuecommand, \ - abort: qla1280_abort, \ - reset: qla1280_reset, \ - slave_attach: NULL, \ - bios_param: QLA1280_BIOSPARAM, \ - can_queue: 255, /* MAX_OUTSTANDING_COMMANDS */ \ - this_id: -1, /* scsi id of host adapter */ \ - sg_tablesize: SG_ALL, \ - cmd_per_lun: 3, /* max commands per lun */ \ - present: 0, /* number of 1280s present */ \ - unchecked_isa_dma: 0, /* no memeory DMA restrictions */ \ - use_clustering: ENABLE_CLUSTERING \ -} -#else -#define QLA1280_LINUX_TEMPLATE { \ +#define QLA1280_LINUX_TEMPLATE { \ next: NULL, \ module: NULL, \ proc_dir: NULL, \ proc_info: qla1280_proc_info, \ - name: "Qlogic ISP 1280\1080", \ + name: "Qlogic ISP 1280\12160", \ detect: qla1280_detect, \ release: qla1280_release, \ info: qla1280_info, \ @@ -1725,13 +1591,14 @@ this_id: -1, /* scsi id of host adapter */\ sg_tablesize: SG_ALL, /* max scatter-gather cmds */\ cmd_per_lun: 3, /* cmds per lun (linked cmds) */\ - present: 0, /* number of 7xxx's present */\ + present: 0, /* number of 1280's present */\ unchecked_isa_dma: 0, /* no memory DMA restrictions */\ use_clustering: ENABLE_CLUSTERING, \ use_new_eh_code: 0, \ emulated: 0 \ } -#endif + #endif /* _IO_HBA_QLA1280_H */ + diff -urN linux-2.4.0-test10/drivers/scsi/simscsi.c linux-2.4.0-test10-lia/drivers/scsi/simscsi.c --- linux-2.4.0-test10/drivers/scsi/simscsi.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/drivers/scsi/simscsi.c Mon Oct 30 22:17:11 2000 @@ -0,0 +1,364 @@ +/* + * Simulated SCSI driver. + * + * Copyright (C) 1999 Hewlett-Packard Co + * Copyright (C) 1999 David Mosberger-Tang + * Copyright (C) 1999 Stephane Eranian + * + * 99/12/18 David Mosberger Added support for READ10/WRITE10 needed by linux v2.3.33 + */ +#include +#include +#include +#include +#include + +#include + +#include + +#include "scsi.h" +#include "sd.h" +#include "hosts.h" +#include "simscsi.h" + +#define DEBUG_SIMSCSI 0 + +/* Simulator system calls: */ + +#define SSC_OPEN 50 +#define SSC_CLOSE 51 +#define SSC_READ 52 +#define SSC_WRITE 53 +#define SSC_GET_COMPLETION 54 +#define SSC_WAIT_COMPLETION 55 + +#define SSC_WRITE_ACCESS 2 +#define SSC_READ_ACCESS 1 + +struct timer_list disk_timer; + +struct disk_req { + unsigned long addr; + unsigned len; +}; + +struct disk_stat { + int fd; + unsigned count; +}; + +extern long ia64_ssc (long arg0, long arg1, long arg2, long arg3, int nr); + +static int desc[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; + +static struct queue_entry { + Scsi_Cmnd *sc; +} queue[SIMSCSI_REQ_QUEUE_LEN]; + +static int rd, wr; +static atomic_t num_reqs = ATOMIC_INIT(0); + +/* base name for default disks */ +static char *simscsi_root = DEFAULT_SIMSCSI_ROOT; + +#define MAX_ROOT_LEN 128 + +/* + * used to setup a new base for disk images + * to use /foo/bar/disk[a-z] as disk images + * you have to specify simscsi=/foo/bar/disk on the command line + */ +static int __init +simscsi_setup (char *s) +{ + /* XXX Fix me we may need to strcpy() ? */ + if (strlen(s) > MAX_ROOT_LEN) { + printk("simscsi_setup: prefix too long---using default %s\n", simscsi_root); + } + simscsi_root = s; + return 1; +} + +__setup("simscsi=", simscsi_setup); + +static void +simscsi_interrupt (unsigned long val) +{ + unsigned long flags; + Scsi_Cmnd *sc; + + spin_lock_irqsave(&io_request_lock, flags); + { + while ((sc = queue[rd].sc) != 0) { + atomic_dec(&num_reqs); + queue[rd].sc = 0; +#if DEBUG_SIMSCSI + printk("simscsi_interrupt: done with %ld\n", sc->serial_number); +#endif + (*sc->scsi_done)(sc); + rd = (rd + 1) % SIMSCSI_REQ_QUEUE_LEN; + } + } + spin_unlock_irqrestore(&io_request_lock, flags); +} + +int +simscsi_detect (Scsi_Host_Template *templ) +{ + templ->proc_name = "simscsi"; + init_timer(&disk_timer); + disk_timer.function = simscsi_interrupt; + return 1; /* fake one SCSI host adapter */ +} + +int +simscsi_release (struct Scsi_Host *host) +{ + return 0; /* this is easy... */ +} + +const char * +simscsi_info (struct Scsi_Host *host) +{ + return "simulated SCSI host adapter"; +} + +int +simscsi_abort (Scsi_Cmnd *cmd) +{ + printk ("simscsi_abort: unimplemented\n"); + return SCSI_ABORT_SUCCESS; +} + +int +simscsi_reset (Scsi_Cmnd *cmd, unsigned int reset_flags) +{ + printk ("simscsi_reset: unimplemented\n"); + return SCSI_RESET_SUCCESS; +} + +int +simscsi_biosparam (Disk *disk, kdev_t n, int ip[]) +{ + int size = disk->capacity; + + ip[0] = 64; + ip[1] = 32; + ip[2] = size >> 11; + return 0; +} + +static void +simscsi_readwrite (Scsi_Cmnd *sc, int mode, unsigned long offset, unsigned long len) +{ + struct disk_stat stat; + struct disk_req req; + + req.addr = __pa(sc->request_buffer); + req.len = len; /* # of bytes to transfer */ + + if (sc->request_bufflen < req.len) + return; + + stat.fd = desc[sc->target]; +#if DEBUG_SIMSCSI + printk("simscsi_%s @ %lx (off %lx)\n", + mode == SSC_READ ? "read":"write", req.addr, offset); +#endif + ia64_ssc(stat.fd, 1, __pa(&req), offset, mode); + ia64_ssc(__pa(&stat), 0, 0, 0, SSC_WAIT_COMPLETION); + + if (stat.count == req.len) { + sc->result = GOOD; + } else { + sc->result = DID_ERROR << 16; + } +} + +static void +simscsi_sg_readwrite (Scsi_Cmnd *sc, int mode, unsigned long offset) +{ + int list_len = sc->use_sg; + struct scatterlist *sl = (struct scatterlist *)sc->buffer; + struct disk_stat stat; + struct disk_req req; + + stat.fd = desc[sc->target]; + + while (list_len) { + req.addr = __pa(sl->address); + req.len = sl->length; +#if DEBUG_SIMSCSI + printk("simscsi_sg_%s @ %lx (off %lx) use_sg=%d len=%d\n", + mode == SSC_READ ? "read":"write", req.addr, offset, list_len, sl->length); +#endif + ia64_ssc(stat.fd, 1, __pa(&req), offset, mode); + ia64_ssc(__pa(&stat), 0, 0, 0, SSC_WAIT_COMPLETION); + + /* should not happen in our case */ + if (stat.count != req.len) { + sc->result = DID_ERROR << 16; + return; + } + offset += sl->length; + sl++; + list_len--; + } + sc->result = GOOD; +} + +/* + * function handling both READ_6/WRITE_6 (non-scatter/gather mode) + * commands. + * Added 02/26/99 S.Eranian + */ +static void +simscsi_readwrite6 (Scsi_Cmnd *sc, int mode) +{ + unsigned long offset; + + offset = (((sc->cmnd[1] & 0x1f) << 16) | (sc->cmnd[2] << 8) | sc->cmnd[3])*512; + if (sc->use_sg > 0) + simscsi_sg_readwrite(sc, mode, offset); + else + simscsi_readwrite(sc, mode, offset, sc->cmnd[4]*512); +} + + +static void +simscsi_readwrite10 (Scsi_Cmnd *sc, int mode) +{ + unsigned long offset; + + offset = ( (sc->cmnd[2] << 24) | (sc->cmnd[3] << 16) + | (sc->cmnd[4] << 8) | (sc->cmnd[5] << 0))*512; + if (sc->use_sg > 0) + simscsi_sg_readwrite(sc, mode, offset); + else + simscsi_readwrite(sc, mode, offset, ((sc->cmnd[7] << 8) | sc->cmnd[8])*512); +} + +int +simscsi_queuecommand (Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *)) +{ + char fname[MAX_ROOT_LEN+16]; + char *buf; + +#if DEBUG_SIMSCSI + register long sp asm ("sp"); + printk("simscsi_queuecommand: target=%d,cmnd=%u,sc=%lu,sp=%lx,done=%p\n", + sc->target, sc->cmnd[0], sc->serial_number, sp, done); +#endif + + sc->result = DID_BAD_TARGET << 16; + sc->scsi_done = done; + if (sc->target <= 7 && sc->lun == 0) { + switch (sc->cmnd[0]) { + case INQUIRY: + if (sc->request_bufflen < 35) { + break; + } + sprintf (fname, "%s%c", simscsi_root, 'a' + sc->target); + desc[sc->target] = ia64_ssc (__pa(fname), SSC_READ_ACCESS|SSC_WRITE_ACCESS, + 0, 0, SSC_OPEN); + if (desc[sc->target] < 0) { + /* disk doesn't exist... */ + break; + } + buf = sc->request_buffer; + buf[0] = 0; /* magnetic disk */ + buf[1] = 0; /* not a removable medium */ + buf[2] = 2; /* SCSI-2 compliant device */ + buf[3] = 2; /* SCSI-2 response data format */ + buf[4] = 31; /* additional length (bytes) */ + buf[5] = 0; /* reserved */ + buf[6] = 0; /* reserved */ + buf[7] = 0; /* various flags */ + memcpy(buf + 8, "HP SIMULATED DISK 0.00", 28); + sc->result = GOOD; + break; + + case TEST_UNIT_READY: + sc->result = GOOD; + break; + + case READ_6: + if (desc[sc->target] < 0 ) + break; + simscsi_readwrite6(sc, SSC_READ); + break; + + case READ_10: + if (desc[sc->target] < 0 ) + break; + simscsi_readwrite10(sc, SSC_READ); + break; + + case WRITE_6: + if (desc[sc->target] < 0) + break; + simscsi_readwrite6(sc, SSC_WRITE); + break; + + case WRITE_10: + if (desc[sc->target] < 0) + break; + simscsi_readwrite10(sc, SSC_WRITE); + break; + + + case READ_CAPACITY: + if (desc[sc->target] < 0 || sc->request_bufflen < 8) { + break; + } + buf = sc->request_buffer; + + /* pretend to be a 1GB disk (partition table contains real stuff): */ + buf[0] = 0x00; + buf[1] = 0x1f; + buf[2] = 0xff; + buf[3] = 0xff; + /* set block size of 512 bytes: */ + buf[4] = 0; + buf[5] = 0; + buf[6] = 2; + buf[7] = 0; + sc->result = GOOD; + break; + + case MODE_SENSE: + printk("MODE_SENSE\n"); + break; + + case START_STOP: + printk("START_STOP\n"); + break; + + default: + panic("simscsi: unknown SCSI command %u\n", sc->cmnd[0]); + } + } + if (sc->result == DID_BAD_TARGET) { + sc->result |= DRIVER_SENSE << 24; + sc->sense_buffer[0] = 0x70; + sc->sense_buffer[2] = 0x00; + } + if (atomic_read(&num_reqs) >= SIMSCSI_REQ_QUEUE_LEN) { + panic("Attempt to queue command while command is pending!!"); + } + atomic_inc(&num_reqs); + queue[wr].sc = sc; + wr = (wr + 1) % SIMSCSI_REQ_QUEUE_LEN; + + if (!timer_pending(&disk_timer)) { + disk_timer.expires = jiffies + HZ/20; + add_timer(&disk_timer); + } + return 0; +} + + +static Scsi_Host_Template driver_template = SIMSCSI; + +#include "scsi_module.c" diff -urN linux-2.4.0-test10/drivers/scsi/simscsi.h linux-2.4.0-test10-lia/drivers/scsi/simscsi.h --- linux-2.4.0-test10/drivers/scsi/simscsi.h Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/drivers/scsi/simscsi.h Mon Oct 30 22:17:11 2000 @@ -0,0 +1,39 @@ +/* + * Simulated SCSI driver. + * + * Copyright (C) 1999 Hewlett-Packard Co + * Copyright (C) 1999 David Mosberger-Tang + */ +#ifndef SIMSCSI_H +#define SIMSCSI_H + +#define SIMSCSI_REQ_QUEUE_LEN 64 + +#define DEFAULT_SIMSCSI_ROOT "/var/ski-disks/sd" + +extern int simscsi_detect (Scsi_Host_Template *); +extern int simscsi_release (struct Scsi_Host *); +extern const char *simscsi_info (struct Scsi_Host *); +extern int simscsi_queuecommand (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +extern int simscsi_abort (Scsi_Cmnd *); +extern int simscsi_reset (Scsi_Cmnd *, unsigned int); +extern int simscsi_biosparam (Disk *, kdev_t, int[]); + +#define SIMSCSI { \ + detect: simscsi_detect, \ + release: simscsi_release, \ + info: simscsi_info, \ + queuecommand: simscsi_queuecommand, \ + abort: simscsi_abort, \ + reset: simscsi_reset, \ + bios_param: simscsi_biosparam, \ + can_queue: SIMSCSI_REQ_QUEUE_LEN, \ + this_id: -1, \ + sg_tablesize: 32, \ + cmd_per_lun: SIMSCSI_REQ_QUEUE_LEN, \ + present: 0, \ + unchecked_isa_dma: 0, \ + use_clustering: DISABLE_CLUSTERING \ +} + +#endif /* SIMSCSI_H */ diff -urN linux-2.4.0-test10/drivers/usb/uhci.c linux-2.4.0-test10-lia/drivers/usb/uhci.c --- linux-2.4.0-test10/drivers/usb/uhci.c Tue Sep 19 17:47:06 2000 +++ linux-2.4.0-test10-lia/drivers/usb/uhci.c Mon Oct 30 22:17:11 2000 @@ -34,7 +34,7 @@ #include #include #include -#define DEBUG +#undef DEBUG #include #include @@ -69,6 +69,46 @@ /* If a transfer is still active after this much time, turn off FSBR */ #define IDLE_TIMEOUT (HZ / 20) /* 50 ms */ +#ifdef CONFIG_ITANIUM_A1_SPECIFIC + +static struct uhci *guhci; + +void +disable_usb (void) +{ + unsigned short cmd; + unsigned int io_addr; + + if (guhci == NULL) + return; + + io_addr = guhci->io_addr; + + cmd = inw (io_addr + USBCMD); + + outw(cmd & ~ USBCMD_RS, io_addr+USBCMD); + + while ((inw (io_addr + USBSTS) & USBSTS_HCH) == 0); +} + +void +reenable_usb (void) +{ + unsigned int io_addr; + unsigned short cmd; + + if (guhci == NULL) + return; + + io_addr = guhci->io_addr; + + cmd = inw (io_addr + USBCMD); + + outw(cmd | USBCMD_RS, io_addr+USBCMD); +} + +#endif /* CONFIG_ITANIUM_A1_SPECIFIC */ + /* * Only the USB core should call uhci_alloc_dev and uhci_free_dev */ @@ -2361,6 +2401,11 @@ if (!uhci_start_root_hub(uhci)) { struct pm_dev *pmdev; +#ifdef CONFIG_ITANIUM_A1_SPECIFIC + guhci = uhci; + printk("%s: enabling Lion USB workaround io_addr=%x\n", + __FILE__, guhci->io_addr); +#endif pmdev = pm_register(PM_PCI_DEV, PM_PCI_ID(dev), handle_pm_event); diff -urN linux-2.4.0-test10/fs/binfmt_elf.c linux-2.4.0-test10-lia/fs/binfmt_elf.c --- linux-2.4.0-test10/fs/binfmt_elf.c Fri Oct 27 11:04:43 2000 +++ linux-2.4.0-test10-lia/fs/binfmt_elf.c Thu Nov 2 00:29:03 2000 @@ -484,6 +484,20 @@ if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 || strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) ibcs2_interpreter = 1; +#if defined(__ia64__) && !defined(CONFIG_BINFMT_ELF32) + /* + * XXX temporary gross hack until all IA-64 Linux binaries + * use /lib/ld-linux-ia64.so.1 as the linker name. + */ +#define INTRP64 "/lib/ld-linux-ia64.so.1" + if (strcmp(elf_interpreter,"/lib/ld-linux.so.2") == 0) { + kfree(elf_interpreter); + elf_interpreter=(char *)kmalloc(sizeof(INTRP64), GFP_KERNEL); + if (!elf_interpreter) + goto out_free_file; + strcpy(elf_interpreter, INTRP64); + } +#endif /* defined(__ia64__) && !defined(CONFIG_BINFMT_ELF32) */ #if 0 printk("Using ELF interpreter %s\n", elf_interpreter); #endif diff -urN linux-2.4.0-test10/fs/nfsd/nfsfh.c linux-2.4.0-test10-lia/fs/nfsd/nfsfh.c --- linux-2.4.0-test10/fs/nfsd/nfsfh.c Mon Oct 16 12:58:51 2000 +++ linux-2.4.0-test10-lia/fs/nfsd/nfsfh.c Wed Nov 1 14:58:08 2000 @@ -379,7 +379,7 @@ /* It's a directory, or we are required to confirm the file's * location in the tree. */ - dprintk("nfs_fh: need to look harder for %d/%ld\n",sb->s_dev,ino); + dprintk("nfs_fh: need to look harder for %d/%ld\n",sb->s_dev,(long) ino); down(&sb->s_nfsd_free_path_sem); /* claiming the semaphore might have allowed things to get fixed up */ diff -urN linux-2.4.0-test10/fs/partitions/Config.in linux-2.4.0-test10-lia/fs/partitions/Config.in --- linux-2.4.0-test10/fs/partitions/Config.in Sun Jul 9 22:21:41 2000 +++ linux-2.4.0-test10-lia/fs/partitions/Config.in Wed Nov 1 23:20:37 2000 @@ -23,6 +23,7 @@ bool ' BSD disklabel (FreeBSD partition tables) support' CONFIG_BSD_DISKLABEL bool ' Solaris (x86) partition table support' CONFIG_SOLARIS_X86_PARTITION bool ' Unixware slices support' CONFIG_UNIXWARE_DISKLABEL + bool ' EFI GUID Partition support' CONFIG_EFI_PARTITION fi bool ' SGI partition support' CONFIG_SGI_PARTITION bool ' Ultrix partition table support' CONFIG_ULTRIX_PARTITION diff -urN linux-2.4.0-test10/fs/partitions/Makefile linux-2.4.0-test10-lia/fs/partitions/Makefile --- linux-2.4.0-test10/fs/partitions/Makefile Tue Jul 18 22:49:47 2000 +++ linux-2.4.0-test10-lia/fs/partitions/Makefile Wed Nov 1 23:20:52 2000 @@ -20,6 +20,7 @@ obj-$(CONFIG_SUN_PARTITION) += sun.o obj-$(CONFIG_ULTRIX_PARTITION) += ultrix.o obj-$(CONFIG_IBM_PARTITION) += ibm.o +obj-$(CONFIG_EFI_PARTITION) += efi.o O_OBJS += $(obj-y) M_OBJS += $(obj-m) diff -urN linux-2.4.0-test10/fs/partitions/check.c linux-2.4.0-test10-lia/fs/partitions/check.c --- linux-2.4.0-test10/fs/partitions/check.c Mon Oct 16 12:58:51 2000 +++ linux-2.4.0-test10-lia/fs/partitions/check.c Wed Nov 1 23:21:07 2000 @@ -32,6 +32,7 @@ #include "sun.h" #include "ibm.h" #include "ultrix.h" +#include "efi.h" extern void device_init(void); extern int *blk_size[]; @@ -71,6 +72,9 @@ #endif #ifdef CONFIG_IBM_PARTITION ibm_partition, +#endif +#ifdef CONFIG_EFI_PARTITION + efi_partition, #endif NULL }; diff -urN linux-2.4.0-test10/fs/partitions/efi.c linux-2.4.0-test10-lia/fs/partitions/efi.c --- linux-2.4.0-test10/fs/partitions/efi.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/fs/partitions/efi.c Wed Nov 1 23:21:21 2000 @@ -0,0 +1,646 @@ +/************************************************************ + * EFI GUID Partition Table handling + * Per Intel EFI Specification v0.99 + * http://developer.intel.com/technology/efi/efi.htm + * efi.[ch] by Matt Domsch + * Copyright 2000 Dell Computer Corporation + * CRC routines taken from the EFI Sample Implementation, + * 1999.12.31, lib/crc.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 + * + * + * TODO: + * + * Changelog: + * Wed Oct 25 2000 Matt Domsch + * - Fixed the LastLBA() call to return the proper last block + * + * Thu Oct 12 2000 Matt Domsch + * - Thanks to Andries Brouwer for his debugging assistance. + * - Code works, detects all the partitions. + * + ************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "check.h" +#include "efi.h" + +#if CONFIG_BLK_DEV_MD && CONFIG_AUTODETECT_RAID +extern void md_autodetect_dev(kdev_t dev); +#endif + + +#undef EFI_DEBUG +#ifdef EFI_DEBUG +static char *efi_printk_level = KERN_DEBUG; +#define debug_printk printk +#else +#define debug_printk(...) +#endif + +/* CRC routines taken from the EFI Sample Implementation, + * 1999.12.31, lib/crc.c + * + * Note, the EFI Specification, v0.99, has a reference to + * Dr. Dobbs Journal, May 1994 (actually it's in May 1992) + * but that isn't the CRC function being used by EFI. + */ + +static u32 CRCTable[256] = { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, + 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, + 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, + 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, + 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, + 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, + 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, + 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, + 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, + 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, + 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, + 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, + 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, + 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, + 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, + 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, + 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, + 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, + 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, + 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, + 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, + 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D +}; + +static u32 +CalculateCrc (void *_pt, u32 Size) +{ + u8 *pt = (u8 *)_pt; + register u32 Crc; + + /* compute crc */ + Crc = 0xffffffff; + while (Size) { + Crc = (Crc >> 8) ^ CRCTable[(__u8) Crc ^ *pt]; + pt += 1; + Size -= 1; + } + Crc = Crc ^ 0xffffffff; + return Crc; +} + + + +/************************************************************ + * IsLegacyMBRValid() + * Requires: + * - mbr is a pointer to a legacy mbr structure + * Modifies: nothing + * Returns: + * 1 on true + * 0 on false + ************************************************************/ +static inline int +IsLegacyMBRValid(LegacyMBR_t *mbr) +{ + return (mbr ? (mbr->Signature == MSDOS_MBR_SIGNATURE) : 0); +} + + + +/************************************************************ + * LastLBA() + * Requires: + * - struct gendisk hd + * - kdev_t dev + * Modifies: nothing + * Returns: + * Last LBA value on success. This is stored (by sd and + * ide-geometry) in + * the part[0] entry for this disk, and is the number of + * physical sectors available on the disk. + * 0 on error + ************************************************************/ +u64 +LastLBA(struct gendisk *hd, kdev_t dev) +{ + if (!hd || !hd->part) return 0; + return hd->part[MINOR(dev)].nr_sects - 1; +} + + +/************************************************************ + * ReadLBA() + * Requires: + * - hd is our disk device. + * - dev is our device major number + * - lba is the logical block address desired (disk hardsector number) + * - buffer is a buffer of size size into which data copied + * - size_t count is size of the read (in bytes) + * Modifies: + * - buffer + * Returns: + * - count of bytes read + * - 0 on error + * Bugs: + * - bread() takes second argument as a signed int, not a u64. + * This is because getblk() takes the block number as a signed int. + * This overflow is known on l-k. We overflow at about 1TB. + * + ************************************************************/ + +static size_t +ReadLBA(struct gendisk *hd, kdev_t dev, u64 _lba, u8 *buffer, size_t count) +{ + struct buffer_head *bh; + size_t totalreadcount = 0, bytesread; + int lba = (_lba & 0x7FFFFFFF), i, blockstoread, blocksize; + debug_printk(efi_printk_level "ReadLBA(%p,%s,%x,%p,%x)\n", + hd, kdevname(dev), lba, buffer, count); + + if (!hd || !buffer || !count) return 0; + + + blocksize = get_hardblocksize(dev); + if (!blocksize) blocksize = 512; + blockstoread = count / blocksize; + if (count % blocksize) blockstoread += 1; + debug_printk(efi_printk_level "about to read %d blocks\n", + blockstoread); + + + for (i=0; i bh->b_size ? bh->b_size : count); + memcpy(buffer, bh->b_data, bytesread); + + buffer += bytesread; /* Advance the buffer pointer */ + totalreadcount += bytesread; /* Advance the total read count */ + count -= bytesread; /* Subtract bytesread from count */ + + brelse(bh); + } + + return totalreadcount; +} + +void +PrintGuidPartitionTableHeader(GuidPartitionTableHeader_t *gpt) +{ + debug_printk(efi_printk_level "GUID Partition Table Header\n"); + if (!gpt) return; + debug_printk(efi_printk_level "Signature : %lx\n", + gpt->Signature); + debug_printk(efi_printk_level "Revision : %x\n", + gpt->Revision); + debug_printk(efi_printk_level "HeaderSize : %x\n", + gpt->HeaderSize); + debug_printk(efi_printk_level "HeaderCRC32 : %x\n", + gpt->HeaderCRC32); + debug_printk(efi_printk_level "MyLBA : %lx\n", + gpt->MyLBA); + debug_printk(efi_printk_level "AlternateLBA : %lx\n", + gpt->AlternateLBA); + debug_printk(efi_printk_level "FirstUsableLBA : %lx\n", + gpt->FirstUsableLBA); + debug_printk(efi_printk_level "LastUsableLBA : %lx\n", + gpt->LastUsableLBA); + + debug_printk(efi_printk_level "PartitionEntryLBA : %lx\n", + gpt->PartitionEntryLBA); + debug_printk(efi_printk_level "NumberOfPartitionEntries : %x\n", + gpt->NumberOfPartitionEntries); + debug_printk(efi_printk_level "SizeOfPartitionEntry : %x\n", + gpt->SizeOfPartitionEntry); + debug_printk(efi_printk_level "PartitionEntryArrayCRC32 : %x\n", + gpt->PartitionEntryArrayCRC32); + + return; +} + + + +/************************************************************ + * ReadGuidPartitionEntries() + * Requires: + * - filedes is an open file descriptor, suitable for reading + * - lba is the Logical Block Address of the partition table + * - gpt is a buffer into which the GPT will be put + * Modifies: + * - filedes file and pointer + * - gpt + * Returns: + * pte on success + * NULL on error + * Notes: remember to free pte when you're done! + ************************************************************/ +GuidPartitionEntry_t * +ReadGuidPartitionEntries(struct gendisk *hd, kdev_t dev, + GuidPartitionTableHeader_t *gpt) +{ + size_t count; + GuidPartitionEntry_t *pte; + if (!hd || !gpt) return NULL; + + count = gpt->NumberOfPartitionEntries * gpt->SizeOfPartitionEntry; + debug_printk(efi_printk_level "ReadGPTEs() kmallocing %x bytes\n", + count); + if (!count) return NULL; + pte = kmalloc(count, GFP_KERNEL); + if (!pte) return NULL; + memset(pte, 0, count); + + if (ReadLBA(hd, dev, gpt->PartitionEntryLBA, (u8 *)pte, + count) < count) { + kfree(pte); + return NULL; + } + return pte; +} + + + +/************************************************************ + * ReadGuidPartitionTableHeader() + * Requires: + * - hd is our struct gendisk + * - dev is our device major number + * - lba is the Logical Block Address of the partition table + * - gpt is a buffer into which the GPT will be put + * - pte is a buffer into which the PTEs will be put + * Modifies: + * - gpt and pte + * Returns: + * 1 on success + * 0 on error + ************************************************************/ + +GuidPartitionTableHeader_t * +ReadGuidPartitionTableHeader(struct gendisk *hd, kdev_t dev, u64 lba) + +{ + GuidPartitionTableHeader_t *gpt; + if (!hd) return NULL; + + gpt = kmalloc(sizeof(GuidPartitionTableHeader_t), GFP_KERNEL); + if (!gpt) return NULL; + memset(gpt, 0, sizeof(GuidPartitionTableHeader_t)); + + debug_printk(efi_printk_level "GPTH() calling ReadLBA().\n"); + if (ReadLBA(hd, dev, lba, (u8 *)gpt, + sizeof(GuidPartitionTableHeader_t)) < + sizeof(GuidPartitionTableHeader_t)) { + debug_printk(efi_printk_level "ReadGPTH(%lx) read failed.\n", + lba); + kfree(gpt); + return NULL; + } + PrintGuidPartitionTableHeader(gpt); + + return gpt; +} + + + +/************************************************************ + * IsGuidPartitionTableValid() + * Requires: + * - gd points to our struct gendisk + * - dev is our device major number + * - lba is the logical block address of the GPTH to test + * - gpt is a GPTH if it's valid + * - ptes is a PTEs if it's valid + * Modifies: + * - gpt and ptes + * Returns: + * 1 if valid + * 0 on error + ************************************************************/ +static int +IsGuidPartitionTableValid(struct gendisk *hd, kdev_t dev, u64 lba, + GuidPartitionTableHeader_t **gpt, + GuidPartitionEntry_t **ptes) +{ + u32 crc, origcrc; + + if (!hd || !gpt || !ptes) return 0; + if (!(*gpt = ReadGuidPartitionTableHeader(hd, dev, lba))) return 0; + + /* Check the GUID Partition Table Signature */ + if ((*gpt)->Signature != GUID_PT_HEADER_SIGNATURE) { + debug_printk(efi_printk_level "GUID Partition Table Header Signature is wrong: %x != %x\n", (*gpt)->Signature, GUID_PT_HEADER_SIGNATURE); + kfree(*gpt); + *gpt = NULL; + return 0; + } + + /* Check the GUID Partition Table CRC */ + origcrc = (*gpt)->HeaderCRC32; + (*gpt)->HeaderCRC32 = 0; + crc = CalculateCrc(*gpt, (*gpt)->HeaderSize); + + + if (crc != origcrc) { + debug_printk(efi_printk_level "GUID Partition Table Header CRC is wrong: %x != %x\n", (*gpt)->HeaderCRC32, origcrc); + kfree(*gpt); + *gpt = NULL; + return 0; + } + (*gpt)->HeaderCRC32 = origcrc; + + /* Check that the MyLBA entry points to the LBA that contains + * the GUID Partition Table */ + if ((*gpt)->MyLBA != lba) { + debug_printk(efi_printk_level "GPT MyLBA incorrect: %lx != %lx\n", (*gpt)->MyLBA, lba); + kfree(*gpt); + *gpt = NULL; + return 0; + } + + if (!(*ptes = ReadGuidPartitionEntries(hd, dev, *gpt))) { + debug_printk(efi_printk_level "read PTEs failed.\n"); + kfree(*gpt); + *gpt = NULL; + return 0; + } + + /* Check the GUID Partition Entry Array CRC */ + crc = CalculateCrc(*ptes, (*gpt)->NumberOfPartitionEntries * + (*gpt)->SizeOfPartitionEntry); + + if (crc != (*gpt)->PartitionEntryArrayCRC32) { + debug_printk(efi_printk_level "GUID Partitition Entry Array CRC check failed.\n"); + kfree(*gpt); + *gpt = NULL; + kfree(*ptes); + *ptes = NULL; + return 0; + } + + + /* We're done, all's well */ + return 1; +} + + + +/************************************************************ + * FindValidGPT() + * Requires: + * - gd points to our struct gendisk + * - dev is our device major number + * - gpt is a GPTH if it's valid + * - ptes is a PTE + * Modifies: + * - gpt & ptes + * Returns: + * 1 if valid + * 0 on error + ************************************************************/ +static int +FindValidGPT(struct gendisk *hd, kdev_t dev, + GuidPartitionTableHeader_t **gpt, + GuidPartitionEntry_t **ptes) +{ + int rc = 0; + GuidPartitionTableHeader_t *pgpt = NULL, *agpt = NULL; + GuidPartitionEntry_t *pptes = NULL, *aptes = NULL; + u64 lastlba; + if (!hd || !gpt || !ptes) return 0; + + lastlba = LastLBA(hd, dev); + /* Check the Primary GPT */ + rc = IsGuidPartitionTableValid(hd, dev, 1, &pgpt, &pptes); + if (rc) { + /* Primary GPT is OK, check the alternate and warn if bad */ + rc = IsGuidPartitionTableValid(hd, dev, pgpt->AlternateLBA, + &agpt, &aptes); + if (!rc){ + printk(KERN_WARNING "Alternate GPT is invalid, using primary GPT.\n"); + } + + *gpt = pgpt; + *ptes = pptes; + if (agpt) kfree(agpt); + if (aptes) kfree(aptes); + return 1; + } /* if primary is valid */ + else { + /* Primary GPT is bad, check the Alternate GPT */ + rc = IsGuidPartitionTableValid(hd, dev, lastlba, + &agpt, &aptes); + if (rc) { + /* Primary is bad, alternate is good. + Return values from the alternate and warn. + */ + printk(KERN_WARNING "Primary GPT is invalid, using alternate GPT.\n"); + *gpt = agpt; + *ptes = aptes; + return 1; + } + else { + /* Primary is bad, alternate is bad, try "other" + * alternate. This is necessary because if we + * have an odd-sized disk, user-space might + * have put the alternate in block lastlba-1. + */ + if (!(lastlba & 1)) { + lastlba--; + rc = IsGuidPartitionTableValid(hd, dev, + lastlba, + &agpt, &aptes); + if (rc) { + /* Primary is bad, alternate is good. + * Return values from the alternate + * and warn. + */ + printk("Primary GPT is invalid, using alternate GPT.\n"); + *gpt = agpt; + *ptes = aptes; + return 1; + } + } + } + } + /* Both primary and alternate GPTs are bad. + * This isn't our disk, return 0. + */ + return 0; +} + + + +/* + * Create devices for each entry in the GUID Partition Table Entries. + * The first block of each partition is a Legacy MBR. + * + * We do not create a Linux partition for GPT, but + * only for the actual data partitions. + * Returns: + * -1 if unable to read the partition table + * 0 if this isn't our partition table + * 1 if successful + * + */ + +static int +add_gpt_partitions(struct gendisk *hd, kdev_t dev, int nextminor) +{ + GuidPartitionTableHeader_t *gpt = NULL; + GuidPartitionEntry_t *ptes = NULL; + u32 i, nummade=0; + + efi_guid_t unusedGuid = UNUSED_ENTRY_GUID; +#if CONFIG_BLK_DEV_MD && CONFIG_AUTODETECT_RAID + efi_guid_t raidGuid = PARTITION_LINUX_RAID_GUID; +#endif + + if (!hd) return -1; + + if (!FindValidGPT(hd, dev, &gpt, &ptes) || + !gpt || !ptes) { + if (gpt) kfree(gpt); + if (ptes) kfree(ptes); + return 0; + } + + debug_printk(efi_printk_level "GUID Partition Table is valid! Yea!\n"); + for (i = 0; i < gpt->NumberOfPartitionEntries && + nummade < (hd->max_p - 1); i++) { + if (!efi_guidcmp(unusedGuid, ptes[i].PartitionTypeGuid)) + continue; + + add_gd_partition(hd, nextminor, ptes[i].StartingLBA, + (ptes[i].EndingLBA-ptes[i].StartingLBA + 1)); + + /* If there's this is a RAID volume, tell md */ +#if CONFIG_BLK_DEV_MD && CONFIG_AUTODETECT_RAID + if (!efi_guidcmp(raidGuid, ptes[i].PartitionTypeGuid)) { + md_autodetect_dev(MKDEV(MAJOR(dev),nextminor)); + } +#endif + nummade++; + nextminor++; + + } + kfree(ptes); + kfree(gpt); + printk("\n"); + return 1; + +} + + +/* + * efi_partition() + * + * If the first block on the disk is a legacy MBR, + * it got handled already by msdos_partition(). + * If it's a Protective MBR, we'll handle it here. + * + * Returns: + * -1 if unable to read the partition table + * 0 if this isn't our partitoin table + * 1 if successful + * + */ + +int +efi_partition(struct gendisk *hd, kdev_t dev, + unsigned long first_sector, int first_part_minor) { + int hardblocksize = get_hardblocksize(dev); + int orig_blksize_size = BLOCK_SIZE; + int rc = 0; + + /* not good, but choose something! */ + if (!hardblocksize) hardblocksize = 512; + + /* Need to change the block size that the block layer uses */ + if (blksize_size[MAJOR(dev)]){ + orig_blksize_size = blksize_size[MAJOR(dev)][MINOR(dev)]; + } + + if (orig_blksize_size != hardblocksize) + set_blocksize(dev, hardblocksize); + + rc = add_gpt_partitions(hd, dev, first_part_minor); + + /* change back */ + if (orig_blksize_size != hardblocksize) + set_blocksize(dev, orig_blksize_size); + + return rc; +} + + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 4 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -4 + * c-argdecl-indent: 4 + * c-label-offset: -4 + * c-continued-statement-offset: 4 + * c-continued-brace-offset: 0 + * indent-tabs-mode: nil + * tab-width: 8 + * End: + */ + + + diff -urN linux-2.4.0-test10/fs/partitions/efi.h linux-2.4.0-test10-lia/fs/partitions/efi.h --- linux-2.4.0-test10/fs/partitions/efi.h Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/fs/partitions/efi.h Wed Nov 15 22:23:17 2000 @@ -0,0 +1,154 @@ +/************************************************************ + * EFI GUID Partition Table + * Per Intel EFI Specification v0.99 + * http://developer.intel.com/technology/efi/efi.htm + * + * By Matt Domsch Fri Sep 22 22:15:56 CDT 2000 + * Copyright 2000 Dell Computer Corporation + * + * 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 + * + ************************************************************/ + +#ifndef FS_PART_EFI_H_INCLUDED +#define FS_PART_EFI_H_INCLUDED + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define MSDOS_MBR_SIGNATURE 0xaa55 +#define EFI_PMBR_OSTYPE_EFI 0xEF +#define EFI_PMBR_OSTYPE_EFI_GPT 0xEE + +#define GUID_PT_BLOCK_SIZE 512 + +#define GUID_PT_HEADER_SIGNATURE 0x5452415020494645L +#define GUID_PT_HEADER_REVISION_V1 0x00010000 +#define GUID_PT_HEADER_REVISION_V0_99 0x00000099 +#define UNUSED_ENTRY_GUID \ + ((efi_guid_t) { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}) +#define PARTITION_SYSTEM_GUID \ +((efi_guid_t) { 0xC12A7328, 0xF81F, 0x11d2, { 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B }}) +#define LEGACY_MBR_PARTITION_GUID \ + ((efi_guid_t) { 0x024DEE41, 0x33E7, 0x11d3, { 0x9D, 0x69, 0x00, 0x08, 0xC7, 0x81, 0xF3, 0x9F }}) +#define PARTITION_MSFT_RESERVED_GUID \ + ((efi_guid_t) { 0xE3C9E316, 0x0B5C, 0x4DB8, { 0x81, 0x7D, 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE }}) +#define PARTITION_BASIC_DATA_GUID \ + ((efi_guid_t) { 0xEBD0A0A2, 0xB9E5, 0x4433, { 0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7 }}) +#define PARTITION_LINUX_RAID_GUID \ + ((efi_guid_t) { 0xa19d880f, 0x05fc, 0x4d3b, { 0xa0, 0x06, 0x74, 0x3f, 0x0f, 0x84, 0x91, 0x1e }}) +#define PARTITION_LINUX_SWAP_GUID \ + ((efi_guid_t) { 0x0657fd6d, 0xa4ab, 0x43c4, { 0x84, 0xe5, 0x09, 0x33, 0xc8, 0x4b, 0x4f, 0x4f }}) + +typedef struct _GuidPartitionTableHeader_t { + u64 Signature; + u32 Revision; + u32 HeaderSize; + u32 HeaderCRC32; + u32 Reserved1; + u64 MyLBA; + u64 AlternateLBA; + u64 FirstUsableLBA; + u64 LastUsableLBA; + efi_guid_t DiskGUID; + u64 PartitionEntryLBA; + u32 NumberOfPartitionEntries; + u32 SizeOfPartitionEntry; + u32 PartitionEntryArrayCRC32; + u8 Reserved2[GUID_PT_BLOCK_SIZE - 92]; +} GuidPartitionTableHeader_t; + +typedef struct _GuidPartitionEntryAttributes_t { + __u64 RequiredToFunction:1; + __u64 Reserved:63; +} GuidPartitionEntryAttributes_t; + +typedef struct _GuidPartitionEntry_t { + efi_guid_t PartitionTypeGuid; + efi_guid_t UniquePartitionGuid; + u64 StartingLBA; + u64 EndingLBA; + GuidPartitionEntryAttributes_t Attributes; + efi_char16_t PartitionName[72/sizeof(efi_char16_t)]; +} GuidPartitionEntry_t; + + + +typedef struct _PartitionRecord_t { + u8 BootIndicator; /* Not used by EFI firmware. Set to 0x80 to indicate that this + is the bootable legacy partition. */ + u8 StartHead; /* Start of partition in CHS address, not used by EFI firmware. */ + u8 StartSector; /* Start of partition in CHS address, not used by EFI firmware. */ + u8 StartTrack; /* Start of partition in CHS address, not used by EFI firmware. */ + u8 OSType; /* OS type. A value of 0xEF defines an EFI system partition. + Other values are reserved for legacy operating systems, and + allocated independently of the EFI specification. */ + u8 EndHead; /* End of partition in CHS address, not used by EFI firmware. */ + u8 EndSector; /* End of partition in CHS address, not used by EFI firmware. */ + u8 EndTrack; /* End of partition in CHS address, not used by EFI firmware. */ + u32 StartingLBA; /* Starting LBA address of the partition on the disk. Used by + EFI firmware to define the start of the partition. */ + u32 SizeInLBA; /* Size of partition in LBA. Used by EFI firmware to determine + the size of the partition. */ +} PartitionRecord_t; + +typedef struct _LegacyMBR_t { + u8 BootCode[440]; + u32 UniqueMBRSignature; + u16 Unknown; + PartitionRecord_t PartitionRecord[4]; + u16 Signature; +} __attribute__ ((packed)) LegacyMBR_t; + + + +#define EFI_GPT_PRIMARY_PARTITION_TABLE_LBA 1 + +/* Functions */ +extern int +efi_partition(struct gendisk *hd, kdev_t dev, + unsigned long first_sector, int first_part_minor); + + + + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * -------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 4 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -4 + * c-argdecl-indent: 4 + * c-label-offset: -4 + * c-continued-statement-offset: 4 + * c-continued-brace-offset: 0 + * indent-tabs-mode: nil + * tab-width: 8 + * End: + */ diff -urN linux-2.4.0-test10/fs/partitions/msdos.c linux-2.4.0-test10-lia/fs/partitions/msdos.c --- linux-2.4.0-test10/fs/partitions/msdos.c Tue Jul 18 23:29:16 2000 +++ linux-2.4.0-test10-lia/fs/partitions/msdos.c Thu Nov 2 00:10:33 2000 @@ -36,6 +36,10 @@ #include "check.h" #include "msdos.h" +#ifdef CONFIG_EFI_PARTITION +#include "efi.h" +#endif + #if CONFIG_BLK_DEV_MD && CONFIG_AUTODETECT_RAID extern void md_autodetect_dev(kdev_t dev); #endif @@ -378,6 +382,16 @@ bforget(bh); return 0; } +#ifdef CONFIG_EFI_PARTITION + p = (struct partition *) (0x1be + data); + for (i=1 ; i<=4 ; i++,p++) { + /* If this is an EFI GPT disk, msdos should ignore it. */ + if (SYS_IND(p) == EFI_PMBR_OSTYPE_EFI_GPT) { + bforget(bh); + return 0; + } + } +#endif p = (struct partition *) (0x1be + data); #ifdef CONFIG_BLK_DEV_IDE diff -urN linux-2.4.0-test10/fs/proc/generic.c linux-2.4.0-test10-lia/fs/proc/generic.c --- linux-2.4.0-test10/fs/proc/generic.c Sun Oct 1 20:35:16 2000 +++ linux-2.4.0-test10-lia/fs/proc/generic.c Mon Oct 30 22:17:11 2000 @@ -43,7 +43,7 @@ #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #endif -/* 4K page size but our output routines use some slack for overruns */ +/* buffer size is one page but our output routines use some slack for overruns */ #define PROC_BLOCK_SIZE (PAGE_SIZE - 1024) static ssize_t diff -urN linux-2.4.0-test10/fs/readdir.c linux-2.4.0-test10-lia/fs/readdir.c --- linux-2.4.0-test10/fs/readdir.c Fri Aug 11 14:29:01 2000 +++ linux-2.4.0-test10-lia/fs/readdir.c Mon Oct 30 22:17:11 2000 @@ -325,4 +325,3 @@ out: return error; } - diff -urN linux-2.4.0-test10/include/asm-alpha/module.h linux-2.4.0-test10-lia/include/asm-alpha/module.h --- linux-2.4.0-test10/include/asm-alpha/module.h Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/include/asm-alpha/module.h Mon Oct 30 22:17:11 2000 @@ -0,0 +1,11 @@ +#ifndef _ASM_ALPHA_MODULE_H +#define _ASM_ALPHA_MODULE_H +/* + * This file contains the alpha architecture specific module code. + */ + +#define module_map(x) vmalloc(x) +#define module_unmap(x) vfree(x) +#define module_arch_init(x) (0) + +#endif /* _ASM_ALPHA_MODULE_H */ diff -urN linux-2.4.0-test10/include/asm-alpha/pgtable.h linux-2.4.0-test10-lia/include/asm-alpha/pgtable.h --- linux-2.4.0-test10/include/asm-alpha/pgtable.h Wed Oct 18 14:25:46 2000 +++ linux-2.4.0-test10-lia/include/asm-alpha/pgtable.h Wed Nov 1 14:58:17 2000 @@ -301,9 +301,6 @@ #define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define swp_entry_to_pte(x) ((pte_t) { (x).val }) -#define module_map vmalloc -#define module_unmap vfree - /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ #define PageSkip(page) (0) #define kern_addr_valid(addr) (1) diff -urN linux-2.4.0-test10/include/asm-arm/module.h linux-2.4.0-test10-lia/include/asm-arm/module.h --- linux-2.4.0-test10/include/asm-arm/module.h Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/include/asm-arm/module.h Mon Oct 30 22:17:11 2000 @@ -0,0 +1,11 @@ +#ifndef _ASM_ARM_MODULE_H +#define _ASM_ARM_MODULE_H +/* + * This file contains the arm architecture specific module code. + */ + +#define module_map(x) vmalloc(x) +#define module_unmap(x) vfree(x) +#define module_arch_init(x) (0) + +#endif /* _ASM_ARM_MODULE_H */ diff -urN linux-2.4.0-test10/include/asm-generic/pgtable.h linux-2.4.0-test10-lia/include/asm-generic/pgtable.h --- linux-2.4.0-test10/include/asm-generic/pgtable.h Thu Oct 19 15:51:16 2000 +++ linux-2.4.0-test10-lia/include/asm-generic/pgtable.h Wed Nov 15 18:13:56 2000 @@ -26,7 +26,7 @@ return pte; } -static inline void ptep_clear_wrprotect(pte_t *ptep) +static inline void ptep_set_wrprotect(pte_t *ptep) { pte_t old_pte = *ptep; set_pte(ptep, pte_wrprotect(old_pte)); diff -urN linux-2.4.0-test10/include/asm-i386/module.h linux-2.4.0-test10-lia/include/asm-i386/module.h --- linux-2.4.0-test10/include/asm-i386/module.h Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/include/asm-i386/module.h Mon Oct 30 22:17:11 2000 @@ -0,0 +1,11 @@ +#ifndef _ASM_I386_MODULE_H +#define _ASM_I386_MODULE_H +/* + * This file contains the i386 architecture specific module code. + */ + +#define module_map(x) vmalloc(x) +#define module_unmap(x) vfree(x) +#define module_arch_init(x) (0) + +#endif /* _ASM_I386_MODULE_H */ diff -urN linux-2.4.0-test10/include/asm-i386/pgtable.h linux-2.4.0-test10-lia/include/asm-i386/pgtable.h --- linux-2.4.0-test10/include/asm-i386/pgtable.h Tue Oct 31 11:18:05 2000 +++ linux-2.4.0-test10-lia/include/asm-i386/pgtable.h Wed Nov 15 18:14:06 2000 @@ -283,7 +283,7 @@ static inline int ptep_test_and_clear_dirty(pte_t *ptep) { return test_and_clear_bit(_PAGE_BIT_DIRTY, ptep); } static inline int ptep_test_and_clear_young(pte_t *ptep) { return test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep); } -static inline void ptep_clear_wrprotect(pte_t *ptep) { clear_bit(_PAGE_BIT_RW, ptep); } +static inline void ptep_set_wrprotect(pte_t *ptep) { clear_bit(_PAGE_BIT_RW, ptep); } static inline void ptep_mkdirty(pte_t *ptep) { set_bit(_PAGE_BIT_RW, ptep); } /* @@ -339,9 +339,6 @@ #define SWP_ENTRY(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) }) #define pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_low }) #define swp_entry_to_pte(x) ((pte_t) { (x).val }) - -#define module_map vmalloc -#define module_unmap vfree #endif /* !__ASSEMBLY__ */ diff -urN linux-2.4.0-test10/include/asm-ia64/acpikcfg.h linux-2.4.0-test10-lia/include/asm-ia64/acpikcfg.h --- linux-2.4.0-test10/include/asm-ia64/acpikcfg.h Fri Oct 13 12:05:29 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/acpikcfg.h Wed Nov 15 22:22:30 2000 @@ -1,3 +1,4 @@ +#ifdef CONFIG_ACPI_KERNEL_CONFIG /* * acpikcfg.h - ACPI based Kernel Configuration Manager External Interfaces * @@ -5,9 +6,6 @@ * Copyright (C) 2000 J.I. Lee */ -#include - -#ifdef CONFIG_ACPI_KERNEL_CONFIG u32 __init acpi_cf_init (void * rsdp); u32 __init acpi_cf_terminate (void ); diff -urN linux-2.4.0-test10/include/asm-ia64/cache.h linux-2.4.0-test10-lia/include/asm-ia64/cache.h --- linux-2.4.0-test10/include/asm-ia64/cache.h Fri Apr 21 15:21:24 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/cache.h Wed Nov 15 22:22:30 2000 @@ -9,11 +9,11 @@ */ /* Bytes per L1 (data) cache line. */ -#define LOG_L1_CACHE_BYTES 6 -#define L1_CACHE_BYTES (1 << LOG_L1_CACHE_BYTES) +#define L1_CACHE_SHIFT 6 +#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) #ifdef CONFIG_SMP -# define SMP_LOG_CACHE_BYTES LOG_L1_CACHE_BYTES +# define SMP_CACHE_SHIFT L1_CACHE_SHIFT # define SMP_CACHE_BYTES L1_CACHE_BYTES #else /* @@ -21,7 +21,7 @@ * safe and provides an easy way to avoid wasting space on a * uni-processor: */ -# define SMP_LOG_CACHE_BYTES 3 +# define SMP_CACHE_SHIFT 3 # define SMP_CACHE_BYTES (1 << 3) #endif diff -urN linux-2.4.0-test10/include/asm-ia64/delay.h linux-2.4.0-test10-lia/include/asm-ia64/delay.h --- linux-2.4.0-test10/include/asm-ia64/delay.h Mon Oct 9 17:54:57 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/delay.h Wed Nov 15 22:22:35 2000 @@ -55,6 +55,10 @@ unsigned long result; __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory"); +#ifdef CONFIG_ITANIUM + while (__builtin_expect ((__s32) result == -1, 0)) + __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory"); +#endif return result; } diff -urN linux-2.4.0-test10/include/asm-ia64/hw_irq.h linux-2.4.0-test10-lia/include/asm-ia64/hw_irq.h --- linux-2.4.0-test10/include/asm-ia64/hw_irq.h Fri Oct 13 12:05:29 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/hw_irq.h Wed Nov 15 22:22:34 2000 @@ -6,8 +6,11 @@ * Copyright (C) 2000 David Mosberger-Tang */ +#include + #include +#include #include #include @@ -29,13 +32,22 @@ #define IA64_SPURIOUS_INT 0x0f -#define IA64_MIN_VECTORED_IRQ 16 -#define IA64_MAX_VECTORED_IRQ 255 +/* + * Vectors 0x10-0x1f are used for low priority interrupts, e.g. CMCI. + */ +#define PCE_IRQ 0x1e /* platform corrected error interrupt vector */ +#define CMC_IRQ 0x1f /* correctable machine-check interrupt vector */ +/* + * Vectors 0x20-0x2f are reserved for legacy ISA IRQs. + */ +#define FIRST_DEVICE_IRQ 0x30 +#define LAST_DEVICE_IRQ 0xe7 -#define PERFMON_IRQ 0x28 /* performanc monitor interrupt vector */ +#define MCA_RENDEZ_IRQ 0xe8 /* MCA rendez interrupt */ +#define PERFMON_IRQ 0xee /* performanc monitor interrupt vector */ #define TIMER_IRQ 0xef /* use highest-prio group 15 interrupt for timer */ +#define MCA_WAKEUP_IRQ 0xf0 /* MCA wakeup interrupt (must be higher than MCA_RENDEZ_IRQ) */ #define IPI_IRQ 0xfe /* inter-processor interrupt vector */ -#define CMC_IRQ 0xff /* correctable machine-check interrupt vector */ /* IA64 inter-cpu interrupt related definitions */ @@ -60,12 +72,13 @@ extern struct hw_interrupt_type irq_type_ia64_sapic; /* CPU-internal interrupt controller */ -extern void ipi_send (int cpu, int vector, int delivery_mode, int redirect); +extern int ia64_alloc_irq (void); /* allocate a free irq */ +extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect); static inline void hw_resend_irq (struct hw_interrupt_type *h, unsigned int vector) { - ipi_send(smp_processor_id(), vector, IA64_IPI_DM_INT, 0); + platform_send_ipi(smp_processor_id(), vector, IA64_IPI_DM_INT, 0); } #endif /* _ASM_IA64_HW_IRQ_H */ diff -urN linux-2.4.0-test10/include/asm-ia64/ia32.h linux-2.4.0-test10-lia/include/asm-ia64/ia32.h --- linux-2.4.0-test10/include/asm-ia64/ia32.h Mon Oct 9 17:54:58 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/ia32.h Wed Nov 15 22:22:40 2000 @@ -5,6 +5,8 @@ #ifdef CONFIG_IA32_SUPPORT +#include + /* * 32 bit structures for IA32 support. */ @@ -32,6 +34,8 @@ #define IA32_PAGE_SHIFT 12 /* 4KB pages */ #define IA32_PAGE_SIZE (1ULL << IA32_PAGE_SHIFT) +#define IA32_CLOCKS_PER_SEC 100 /* Cast in stone for IA32 Linux */ +#define IA32_TICK(tick) ((unsigned long long)(tick) * IA32_CLOCKS_PER_SEC / CLOCKS_PER_SEC) /* fcntl.h */ struct flock32 { diff -urN linux-2.4.0-test10/include/asm-ia64/io.h linux-2.4.0-test10-lia/include/asm-ia64/io.h --- linux-2.4.0-test10/include/asm-ia64/io.h Mon Oct 9 17:54:58 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/io.h Wed Nov 15 22:22:31 2000 @@ -29,6 +29,7 @@ # ifdef __KERNEL__ +#include #include #include @@ -54,8 +55,7 @@ #define bus_to_virt phys_to_virt #define virt_to_bus virt_to_phys -# else /* !KERNEL */ -# endif /* !KERNEL */ +# endif /* KERNEL */ /* * Memory fence w/accept. This should never be used in code that is @@ -100,7 +100,7 @@ */ static inline unsigned int -__inb (unsigned long port) +__ia64_inb (unsigned long port) { volatile unsigned char *addr = __ia64_mk_io_addr(port); unsigned char ret; @@ -111,7 +111,7 @@ } static inline unsigned int -__inw (unsigned long port) +__ia64_inw (unsigned long port) { volatile unsigned short *addr = __ia64_mk_io_addr(port); unsigned short ret; @@ -122,7 +122,7 @@ } static inline unsigned int -__inl (unsigned long port) +__ia64_inl (unsigned long port) { volatile unsigned int *addr = __ia64_mk_io_addr(port); unsigned int ret; @@ -133,112 +133,148 @@ } static inline void -__insb (unsigned long port, void *dst, unsigned long count) +__ia64_outb (unsigned char val, unsigned long port) { volatile unsigned char *addr = __ia64_mk_io_addr(port); - unsigned char *dp = dst; + *addr = val; __ia64_mf_a(); - while (count--) { - *dp++ = *addr; - } - __ia64_mf_a(); - return; } static inline void -__insw (unsigned long port, void *dst, unsigned long count) +__ia64_outw (unsigned short val, unsigned long port) { volatile unsigned short *addr = __ia64_mk_io_addr(port); - unsigned short *dp = dst; + *addr = val; __ia64_mf_a(); - while (count--) { - *dp++ = *addr; - } - __ia64_mf_a(); - return; } static inline void -__insl (unsigned long port, void *dst, unsigned long count) +__ia64_outl (unsigned int val, unsigned long port) { volatile unsigned int *addr = __ia64_mk_io_addr(port); - unsigned int *dp = dst; + *addr = val; __ia64_mf_a(); - while (count--) { - *dp++ = *addr; - } - __ia64_mf_a(); - return; } static inline void -__outb (unsigned char val, unsigned long port) +__insb (unsigned long port, void *dst, unsigned long count) { - volatile unsigned char *addr = __ia64_mk_io_addr(port); + unsigned char *dp = dst; - *addr = val; - __ia64_mf_a(); + if (platform_inb == __ia64_inb) { + volatile unsigned char *addr = __ia64_mk_io_addr(port); + + __ia64_mf_a(); + while (count--) + *dp++ = *addr; + __ia64_mf_a(); + } else + while (count--) + *dp++ = platform_inb(port); + return; } static inline void -__outw (unsigned short val, unsigned long port) +__insw (unsigned long port, void *dst, unsigned long count) { - volatile unsigned short *addr = __ia64_mk_io_addr(port); + unsigned short *dp = dst; - *addr = val; - __ia64_mf_a(); + if (platform_inw == __ia64_inw) { + volatile unsigned short *addr = __ia64_mk_io_addr(port); + + __ia64_mf_a(); + while (count--) + *dp++ = *addr; + __ia64_mf_a(); + } else + while (count--) + *dp++ = platform_inw(port); + return; } static inline void -__outl (unsigned int val, unsigned long port) +__insl (unsigned long port, void *dst, unsigned long count) { - volatile unsigned int *addr = __ia64_mk_io_addr(port); + unsigned int *dp = dst; - *addr = val; - __ia64_mf_a(); + if (platform_inl == __ia64_inl) { + volatile unsigned int *addr = __ia64_mk_io_addr(port); + + __ia64_mf_a(); + while (count--) + *dp++ = *addr; + __ia64_mf_a(); + } else + while (count--) + *dp++ = platform_inl(port); + return; } static inline void __outsb (unsigned long port, const void *src, unsigned long count) { - volatile unsigned char *addr = __ia64_mk_io_addr(port); const unsigned char *sp = src; - while (count--) { - *addr = *sp++; - } - __ia64_mf_a(); + if (platform_outb == __ia64_outb) { + volatile unsigned char *addr = __ia64_mk_io_addr(port); + + while (count--) + *addr = *sp++; + __ia64_mf_a(); + } else + while (count--) + platform_outb(*sp++, port); return; } static inline void __outsw (unsigned long port, const void *src, unsigned long count) { - volatile unsigned short *addr = __ia64_mk_io_addr(port); const unsigned short *sp = src; - while (count--) { - *addr = *sp++; - } - __ia64_mf_a(); + if (platform_outw == __ia64_outw) { + volatile unsigned short *addr = __ia64_mk_io_addr(port); + + while (count--) + *addr = *sp++; + __ia64_mf_a(); + } else + while (count--) + platform_outw(*sp++, port); return; } static inline void __outsl (unsigned long port, void *src, unsigned long count) { - volatile unsigned int *addr = __ia64_mk_io_addr(port); const unsigned int *sp = src; - while (count--) { - *addr = *sp++; - } - __ia64_mf_a(); + if (platform_outl == __ia64_outl) { + volatile unsigned int *addr = __ia64_mk_io_addr(port); + + while (count--) + *addr = *sp++; + __ia64_mf_a(); + } else + while (count--) + platform_outl(*sp++, port); return; } + +/* + * Unfortunately, some platforms are broken and do not follow the + * IA-64 architecture specification regarding legacy I/O support. + * Thus, we have to make these operations platform dependent... + */ +#define __inb platform_inb +#define __inw platform_inw +#define __inl platform_inl +#define __outb platform_outb +#define __outw platform_outw +#define __outl platform_outl #define inb __inb #define inw __inw diff -urN linux-2.4.0-test10/include/asm-ia64/iosapic.h linux-2.4.0-test10-lia/include/asm-ia64/iosapic.h --- linux-2.4.0-test10/include/asm-ia64/iosapic.h Thu Jun 22 07:09:45 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/iosapic.h Mon Oct 30 22:53:32 2000 @@ -3,121 +3,60 @@ #include -#define IO_SAPIC_DEFAULT_ADDR 0xFEC00000 +#define IOSAPIC_DEFAULT_ADDR 0xFEC00000 -#define IO_SAPIC_REG_SELECT 0x0 -#define IO_SAPIC_WINDOW 0x10 -#define IO_SAPIC_EOI 0x40 +#define IOSAPIC_REG_SELECT 0x0 +#define IOSAPIC_WINDOW 0x10 +#define IOSAPIC_EOI 0x40 -#define IO_SAPIC_VERSION 0x1 +#define IOSAPIC_VERSION 0x1 /* * Redirection table entry */ +#define IOSAPIC_RTE_LOW(i) (0x10+i*2) +#define IOSAPIC_RTE_HIGH(i) (0x11+i*2) -#define IO_SAPIC_RTE_LOW(i) (0x10+i*2) -#define IO_SAPIC_RTE_HIGH(i) (0x11+i*2) - - -#define IO_SAPIC_DEST_SHIFT 16 +#define IOSAPIC_DEST_SHIFT 16 /* * Delivery mode */ - -#define IO_SAPIC_DELIVERY_SHIFT 8 -#define IO_SAPIC_FIXED 0x0 -#define IO_SAPIC_LOWEST_PRIORITY 0x1 -#define IO_SAPIC_PMI 0x2 -#define IO_SAPIC_NMI 0x4 -#define IO_SAPIC_INIT 0x5 -#define IO_SAPIC_EXTINT 0x7 +#define IOSAPIC_DELIVERY_SHIFT 8 +#define IOSAPIC_FIXED 0x0 +#define IOSAPIC_LOWEST_PRIORITY 0x1 +#define IOSAPIC_PMI 0x2 +#define IOSAPIC_NMI 0x4 +#define IOSAPIC_INIT 0x5 +#define IOSAPIC_EXTINT 0x7 /* * Interrupt polarity */ - -#define IO_SAPIC_POLARITY_SHIFT 13 -#define IO_SAPIC_POL_HIGH 0 -#define IO_SAPIC_POL_LOW 1 +#define IOSAPIC_POLARITY_SHIFT 13 +#define IOSAPIC_POL_HIGH 0 +#define IOSAPIC_POL_LOW 1 /* * Trigger mode */ - -#define IO_SAPIC_TRIGGER_SHIFT 15 -#define IO_SAPIC_EDGE 0 -#define IO_SAPIC_LEVEL 1 +#define IOSAPIC_TRIGGER_SHIFT 15 +#define IOSAPIC_EDGE 0 +#define IOSAPIC_LEVEL 1 /* * Mask bit */ - -#define IO_SAPIC_MASK_SHIFT 16 -#define IO_SAPIC_UNMASK 0 -#define IO_SAPIC_MSAK 1 - -/* - * Bus types - */ -#define BUS_ISA 0 /* ISA Bus */ -#define BUS_PCI 1 /* PCI Bus */ - -#ifndef CONFIG_IA64_PCI_FIRMWARE_IRQ -struct intr_routing_entry { - unsigned char srcbus; - unsigned char srcbusno; - unsigned char srcbusirq; - unsigned char iosapic_pin; - unsigned char dstiosapic; - unsigned char mode; - unsigned char trigger; - unsigned char polarity; -}; - -extern struct intr_routing_entry intr_routing[]; -#endif +#define IOSAPIC_MASK_SHIFT 16 +#define IOSAPIC_UNMASK 0 +#define IOSAPIC_MSAK 1 #ifndef __ASSEMBLY__ -#include - -/* - * IOSAPIC Version Register return 32 bit structure like: - * { - * unsigned int version : 8; - * unsigned int reserved1 : 8; - * unsigned int pins : 8; - * unsigned int reserved2 : 8; - * } - */ -extern unsigned int iosapic_version(unsigned long); -extern void iosapic_init(unsigned long, int); - -struct iosapic_vector { - unsigned long iosapic_base; /* IOSAPIC Base address */ - char pin; /* IOSAPIC pin (-1 == No data) */ - unsigned char bus; /* Bus number */ - unsigned char baseirq; /* Base IRQ handled by this IOSAPIC */ - unsigned char bustype; /* Bus type (ISA, PCI, etc) */ - unsigned int busdata; /* Bus specific ID */ - /* These bitfields use the values defined above */ - unsigned char dmode : 3; - unsigned char polarity : 1; - unsigned char trigger : 1; - unsigned char UNUSED : 3; -}; -extern struct iosapic_vector iosapic_vector[NR_IRQS]; - -#define iosapic_addr(v) iosapic_vector[v].iosapic_base -#define iosapic_pin(v) iosapic_vector[v].pin -#define iosapic_bus(v) iosapic_vector[v].bus -#define iosapic_baseirq(v) iosapic_vector[v].baseirq -#define iosapic_bustype(v) iosapic_vector[v].bustype -#define iosapic_busdata(v) iosapic_vector[v].busdata -#define iosapic_dmode(v) iosapic_vector[v].dmode -#define iosapic_trigger(v) iosapic_vector[v].trigger -#define iosapic_polarity(v) iosapic_vector[v].polarity +extern void __init iosapic_init (unsigned long address, unsigned int base_irq); +extern void iosapic_register_legacy_irq (unsigned long irq, unsigned long pin, + unsigned long polarity, unsigned long trigger); +extern void iosapic_pci_fixup (void); # endif /* !__ASSEMBLY__ */ #endif /* __ASM_IA64_IOSAPIC_H */ diff -urN linux-2.4.0-test10/include/asm-ia64/machvec.h linux-2.4.0-test10-lia/include/asm-ia64/machvec.h --- linux-2.4.0-test10/include/asm-ia64/machvec.h Fri Aug 11 19:09:06 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/machvec.h Wed Nov 15 22:22:30 2000 @@ -31,7 +31,22 @@ typedef void ia64_mv_mca_handler_t (void); typedef void ia64_mv_cmci_handler_t (int, void *, struct pt_regs *); typedef void ia64_mv_log_print_t (void); -typedef void ia64_mv_register_iosapic_t (struct acpi_entry_iosapic *); +typedef void ia64_mv_send_ipi_t (int, int, int, int); +/* + * WARNING: The legacy I/O space is _architected_. Platforms are + * expected to follow this architected model (see Section 10.7 in the + * IA-64 Architecture Software Developer's Manual). Unfortunately, + * some broken machines do not follow that model, which is why we have + * to make the inX/outX operations part of the machine vector. + * Platform designers should follow the architected model whenever + * possible. + */ +typedef unsigned int ia64_mv_inb_t (unsigned long); +typedef unsigned int ia64_mv_inw_t (unsigned long); +typedef unsigned int ia64_mv_inl_t (unsigned long); +typedef void ia64_mv_outb_t (unsigned char, unsigned long); +typedef void ia64_mv_outw_t (unsigned short, unsigned long); +typedef void ia64_mv_outl_t (unsigned int, unsigned long); extern void machvec_noop (void); @@ -39,7 +54,7 @@ # include # elif defined (CONFIG_IA64_DIG) # include -# elif defined (CONFIG_IA64_SGI_SN1_SIM) +# elif defined (CONFIG_IA64_SGI_SN1) # include # elif defined (CONFIG_IA64_GENERIC) @@ -55,7 +70,13 @@ # define platform_cmci_handler ia64_mv.cmci_handler # define platform_log_print ia64_mv.log_print # define platform_pci_fixup ia64_mv.pci_fixup -# define platform_register_iosapic ia64_mv.register_iosapic +# define platform_send_ipi ia64_mv.send_ipi +# define platform_inb ia64_mv.inb +# define platform_inw ia64_mv.inw +# define platform_inl ia64_mv.inl +# define platform_outb ia64_mv.outb +# define platform_outw ia64_mv.outw +# define platform_outl ia64_mv.outl # endif struct ia64_machine_vector { @@ -68,7 +89,13 @@ ia64_mv_mca_handler_t *mca_handler; ia64_mv_cmci_handler_t *cmci_handler; ia64_mv_log_print_t *log_print; - ia64_mv_register_iosapic_t *register_iosapic; + ia64_mv_send_ipi_t *send_ipi; + ia64_mv_inb_t *inb; + ia64_mv_inw_t *inw; + ia64_mv_inl_t *inl; + ia64_mv_outb_t *outb; + ia64_mv_outw_t *outw; + ia64_mv_outl_t *outl; }; #define MACHVEC_INIT(name) \ @@ -82,7 +109,13 @@ platform_mca_handler, \ platform_cmci_handler, \ platform_log_print, \ - platform_register_iosapic \ + platform_send_ipi, \ + platform_inb, \ + platform_inw, \ + platform_inl, \ + platform_outb, \ + platform_outw, \ + platform_outl \ } extern struct ia64_machine_vector ia64_mv; @@ -117,8 +150,26 @@ #ifndef platform_pci_fixup # define platform_pci_fixup ((ia64_mv_pci_fixup_t *) machvec_noop) #endif -#ifndef platform_register_iosapic -# define platform_register_iosapic ((ia64_mv_register_iosapic_t *) machvec_noop) +#ifndef platform_send_ipi +# define platform_send_ipi ia64_send_ipi /* default to architected version */ +#endif +#ifndef platform_inb +# define platform_inb __ia64_inb +#endif +#ifndef platform_inw +# define platform_inw __ia64_inw +#endif +#ifndef platform_inl +# define platform_inl __ia64_inl +#endif +#ifndef platform_outb +# define platform_outb __ia64_outb +#endif +#ifndef platform_outw +# define platform_outw __ia64_outw +#endif +#ifndef platform_outl +# define platform_outl __ia64_outl #endif #endif /* _ASM_IA64_MACHVEC_H */ diff -urN linux-2.4.0-test10/include/asm-ia64/machvec_dig.h linux-2.4.0-test10-lia/include/asm-ia64/machvec_dig.h --- linux-2.4.0-test10/include/asm-ia64/machvec_dig.h Fri Aug 11 19:09:06 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/machvec_dig.h Wed Nov 15 18:15:39 2000 @@ -3,9 +3,8 @@ extern ia64_mv_setup_t dig_setup; extern ia64_mv_irq_init_t dig_irq_init; -extern ia64_mv_pci_fixup_t dig_pci_fixup; +extern ia64_mv_pci_fixup_t iosapic_pci_fixup; extern ia64_mv_map_nr_t map_nr_dense; -extern ia64_mv_register_iosapic_t dig_register_iosapic; /* * This stuff has dual use! @@ -17,8 +16,7 @@ #define platform_name "dig" #define platform_setup dig_setup #define platform_irq_init dig_irq_init -#define platform_pci_fixup dig_pci_fixup +#define platform_pci_fixup iosapic_pci_fixup #define platform_map_nr map_nr_dense -#define platform_register_iosapic dig_register_iosapic #endif /* _ASM_IA64_MACHVEC_DIG_h */ diff -urN linux-2.4.0-test10/include/asm-ia64/machvec_hpsim.h linux-2.4.0-test10-lia/include/asm-ia64/machvec_hpsim.h --- linux-2.4.0-test10/include/asm-ia64/machvec_hpsim.h Fri Jul 14 16:08:12 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/machvec_hpsim.h Wed Nov 15 18:15:49 2000 @@ -15,7 +15,6 @@ #define platform_name "hpsim" #define platform_setup hpsim_setup #define platform_irq_init hpsim_irq_init -#define platform_pci_fixup hpsim_pci_fixup #define platform_map_nr map_nr_dense #endif /* _ASM_IA64_MACHVEC_HPSIM_h */ diff -urN linux-2.4.0-test10/include/asm-ia64/machvec_init.h linux-2.4.0-test10-lia/include/asm-ia64/machvec_init.h --- linux-2.4.0-test10/include/asm-ia64/machvec_init.h Fri Aug 11 19:09:06 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/machvec_init.h Wed Nov 15 22:08:12 2000 @@ -4,6 +4,14 @@ #include +extern ia64_mv_send_ipi_t ia64_send_ipi; +extern ia64_mv_inb_t __ia64_inb; +extern ia64_mv_inw_t __ia64_inw; +extern ia64_mv_inl_t __ia64_inl; +extern ia64_mv_outb_t __ia64_outb; +extern ia64_mv_outw_t __ia64_outw; +extern ia64_mv_outl_t __ia64_outl; + #define MACHVEC_HELPER(name) \ struct ia64_machine_vector machvec_##name __attribute__ ((unused, __section__ (".machvec"))) \ = MACHVEC_INIT(name); diff -urN linux-2.4.0-test10/include/asm-ia64/machvec_sn1.h linux-2.4.0-test10-lia/include/asm-ia64/machvec_sn1.h --- linux-2.4.0-test10/include/asm-ia64/machvec_sn1.h Sun Feb 6 18:42:40 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/machvec_sn1.h Wed Nov 15 18:16:14 2000 @@ -4,6 +4,7 @@ extern ia64_mv_setup_t sn1_setup; extern ia64_mv_irq_init_t sn1_irq_init; extern ia64_mv_map_nr_t sn1_map_nr; +extern ia64_mv_send_ipi_t sn1_send_IPI; /* * This stuff has dual use! @@ -16,5 +17,6 @@ #define platform_setup sn1_setup #define platform_irq_init sn1_irq_init #define platform_map_nr sn1_map_nr +#define platform_send_ipi sn1_send_IPI #endif /* _ASM_IA64_MACHVEC_SN1_h */ diff -urN linux-2.4.0-test10/include/asm-ia64/mca.h linux-2.4.0-test10-lia/include/asm-ia64/mca.h --- linux-2.4.0-test10/include/asm-ia64/mca.h Fri Apr 21 15:21:24 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/mca.h Wed Nov 15 22:22:31 2000 @@ -18,6 +18,7 @@ #include #include #include +#include /* These are the return codes from all the IA64_MCA specific interfaces */ typedef int ia64_mca_return_code_t; @@ -30,9 +31,9 @@ #define IA64_MCA_RENDEZ_TIMEOUT (100 * HZ) /* 1000 milliseconds */ /* Interrupt vectors reserved for MC handling. */ -#define IA64_MCA_RENDEZ_INT_VECTOR 0xF3 /* Rendez interrupt */ -#define IA64_MCA_WAKEUP_INT_VECTOR 0x12 /* Wakeup interrupt */ -#define IA64_MCA_CMC_INT_VECTOR 0xF2 /* Correctable machine check interrupt */ +#define IA64_MCA_RENDEZ_INT_VECTOR MCA_RENDEZ_IRQ /* Rendez interrupt */ +#define IA64_MCA_WAKEUP_INT_VECTOR MCA_WAKEUP_IRQ /* Wakeup interrupt */ +#define IA64_MCA_CMC_INT_VECTOR CMC_IRQ /* Correctable machine check interrupt */ #define IA64_CMC_INT_DISABLE 0 #define IA64_CMC_INT_ENABLE 1 diff -urN linux-2.4.0-test10/include/asm-ia64/mman.h linux-2.4.0-test10-lia/include/asm-ia64/mman.h --- linux-2.4.0-test10/include/asm-ia64/mman.h Fri Apr 21 15:21:24 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/mman.h Mon Oct 30 22:54:48 2000 @@ -23,6 +23,8 @@ #define MAP_EXECUTABLE 0x1000 /* mark it as an executable */ #define MAP_LOCKED 0x2000 /* pages are locked */ #define MAP_NORESERVE 0x4000 /* don't check for reservations */ +#define MAP_WRITECOMBINED 0x10000 /* write-combine the area */ +#define MAP_NONCACHED 0x20000 /* don't cache the memory */ #define MS_ASYNC 1 /* sync memory asynchronously */ #define MS_INVALIDATE 2 /* invalidate the caches */ diff -urN linux-2.4.0-test10/include/asm-ia64/mmu_context.h linux-2.4.0-test10-lia/include/asm-ia64/mmu_context.h --- linux-2.4.0-test10/include/asm-ia64/mmu_context.h Mon Oct 9 17:54:59 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/mmu_context.h Wed Nov 15 22:22:32 2000 @@ -32,20 +32,11 @@ #define IA64_REGION_ID_KERNEL 0 /* the kernel's region id (tlb.c depends on this being 0) */ -#define IA64_REGION_ID_BITS 18 - -#ifdef CONFIG_IA64_TLB_CHECKS_REGION_NUMBER -# define IA64_HW_CONTEXT_BITS IA64_REGION_ID_BITS -#else -# define IA64_HW_CONTEXT_BITS (IA64_REGION_ID_BITS - 3) -#endif - -#define IA64_HW_CONTEXT_MASK ((1UL << IA64_HW_CONTEXT_BITS) - 1) - struct ia64_ctx { spinlock_t lock; unsigned int next; /* next context number to use */ unsigned int limit; /* next >= limit => must call wrap_mmu_context() */ + unsigned int max_ctx; /* max. context value supported by all CPUs */ }; extern struct ia64_ctx ia64_ctx; @@ -60,11 +51,7 @@ static inline unsigned long ia64_rid (unsigned long context, unsigned long region_addr) { -# ifdef CONFIG_IA64_TLB_CHECKS_REGION_NUMBER - return context; -# else return context << 3 | (region_addr >> 61); -# endif } static inline void @@ -108,12 +95,8 @@ unsigned long rid_incr = 0; unsigned long rr0, rr1, rr2, rr3, rr4; - rid = mm->context; - -#ifndef CONFIG_IA64_TLB_CHECKS_REGION_NUMBER - rid <<= 3; /* make space for encoding the region number */ + rid = mm->context << 3; /* make space for encoding the region number */ rid_incr = 1 << 8; -#endif /* encode the region id, preferred page size, and VHPT enable bit: */ rr0 = (rid << 8) | (PAGE_SHIFT << 2) | 1; @@ -132,11 +115,10 @@ } /* - * Switch from address space PREV to address space NEXT. Note that - * TSK may be NULL. + * Switch from address space PREV to address space NEXT. */ static inline void -switch_mm (struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu) +activate_mm (struct mm_struct *prev, struct mm_struct *next) { /* * We may get interrupts here, but that's OK because interrupt @@ -147,7 +129,6 @@ reload_context(next); } -#define activate_mm(prev,next) \ - switch_mm((prev), (next), NULL, smp_processor_id()) +#define switch_mm(prev_mm,next_mm,next_task,cpu) activate_mm(prev_mm, next_mm) #endif /* _ASM_IA64_MMU_CONTEXT_H */ diff -urN linux-2.4.0-test10/include/asm-ia64/module.h linux-2.4.0-test10-lia/include/asm-ia64/module.h --- linux-2.4.0-test10/include/asm-ia64/module.h Mon Oct 9 17:54:59 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/module.h Wed Nov 15 22:22:34 2000 @@ -75,10 +75,10 @@ /* * Pointers are reasonable, add the module unwind table */ - archdata->unw_table = unw_add_unwind_table(mod->name, archdata->segment_base, + archdata->unw_table = unw_add_unwind_table(mod->name, + (unsigned long) archdata->segment_base, (unsigned long) archdata->gp, - (unsigned long) archdata->unw_start, - (unsigned long) archdata->unw_end); + archdata->unw_start, archdata->unw_end); #endif /* CONFIG_IA64_NEW_UNWIND */ return 0; } @@ -98,7 +98,7 @@ archdata = (struct archdata *)(mod->archdata_start); if (archdata->unw_table != NULL) - unw_remove_unwind_table(archdata->unw_table); + unw_remove_unwind_table((void *) archdata->unw_table); } #endif /* CONFIG_IA64_NEW_UNWIND */ diff -urN linux-2.4.0-test10/include/asm-ia64/page.h linux-2.4.0-test10-lia/include/asm-ia64/page.h --- linux-2.4.0-test10/include/asm-ia64/page.h Mon Oct 9 17:54:59 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/page.h Wed Nov 15 22:22:31 2000 @@ -58,7 +58,6 @@ #define pgprot_val(x) ((x).pgprot) #define __pte(x) ((pte_t) { (x) } ) -#define __pgd(x) ((pgd_t) { (x) } ) #define __pgprot(x) ((pgprot_t) { (x) } ) # else /* !STRICT_MM_TYPECHECKS */ @@ -102,7 +101,7 @@ #ifdef CONFIG_IA64_GENERIC # include # define virt_to_page(kaddr) (mem_map + platform_map_nr(kaddr)) -#elif defined (CONFIG_IA64_SN_SN1) +#elif defined (CONFIG_IA64_SN_SGI_SN1) # define virt_to_page(kaddr) (mem_map + MAP_NR_SN1(kaddr)) #else # define virt_to_page(kaddr) (mem_map + MAP_NR_DENSE(kaddr)) diff -urN linux-2.4.0-test10/include/asm-ia64/pci.h linux-2.4.0-test10-lia/include/asm-ia64/pci.h --- linux-2.4.0-test10/include/asm-ia64/pci.h Fri Oct 13 12:05:29 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/pci.h Wed Nov 15 22:23:22 2000 @@ -1,6 +1,7 @@ #ifndef _ASM_IA64_PCI_H #define _ASM_IA64_PCI_H +#include #include #include #include diff -urN linux-2.4.0-test10/include/asm-ia64/pgalloc.h linux-2.4.0-test10-lia/include/asm-ia64/pgalloc.h --- linux-2.4.0-test10/include/asm-ia64/pgalloc.h Mon Oct 9 17:54:59 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/pgalloc.h Wed Nov 15 22:22:34 2000 @@ -196,13 +196,6 @@ extern int do_check_pgt_cache (int, int); /* - * This establishes kernel virtual mappings (e.g., as a result of a - * vmalloc call). Since ia-64 uses a separate kernel page table, - * there is nothing to do here... :) - */ -#define set_pgdir(vmaddr, entry) do { } while(0) - -/* * Now for some TLB flushing routines. This is the kind of stuff that * can be very expensive, so try to avoid them whenever possible. */ diff -urN linux-2.4.0-test10/include/asm-ia64/pgtable.h linux-2.4.0-test10-lia/include/asm-ia64/pgtable.h --- linux-2.4.0-test10/include/asm-ia64/pgtable.h Wed Oct 18 14:25:46 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/pgtable.h Wed Nov 15 22:22:54 2000 @@ -24,6 +24,9 @@ * matches the VHPT short format, the firt doubleword of the VHPD long * format, and the first doubleword of the TLB insertion format. */ +#define _PAGE_A_BIT 5 +#define _PAGE_D_BIT 6 + #define _PAGE_P (1 << 0) /* page present bit */ #define _PAGE_MA_WB (0x0 << 2) /* write back memory attribute */ #define _PAGE_MA_UC (0x4 << 2) /* uncacheable memory attribute */ @@ -46,8 +49,8 @@ #define _PAGE_AR_X_RX (7 << 9) /* exec & promote / read & exec */ #define _PAGE_AR_MASK (7 << 9) #define _PAGE_AR_SHIFT 9 -#define _PAGE_A (1 << 5) /* page accessed bit */ -#define _PAGE_D (1 << 6) /* page dirty bit */ +#define _PAGE_A (1 << _PAGE_A_BIT) /* page accessed bit */ +#define _PAGE_D (1 << _PAGE_D_BIT) /* page dirty bit */ #define _PAGE_PPN_MASK (((__IA64_UL(1) << IA64_MAX_PHYS_BITS) - 1) & ~0xfffUL) #define _PAGE_ED (__IA64_UL(1) << 52) /* exception deferral */ #define _PAGE_PROTNONE (__IA64_UL(1) << 63) @@ -79,7 +82,7 @@ #define PGDIR_SIZE (__IA64_UL(1) << PGDIR_SHIFT) #define PGDIR_MASK (~(PGDIR_SIZE-1)) #define PTRS_PER_PGD (__IA64_UL(1) << (PAGE_SHIFT-3)) -#define USER_PTRS_PER_PGD PTRS_PER_PGD +#define USER_PTRS_PER_PGD (5*PTRS_PER_PGD/8) /* regions 0-4 are user regions */ #define FIRST_USER_PGD_NR 0 /* @@ -98,13 +101,11 @@ */ #define PTRS_PER_PTE (__IA64_UL(1) << (PAGE_SHIFT-3)) -/* Number of pointers that fit on a page: this will go away. */ -#define PTRS_PER_PAGE (__IA64_UL(1) << (PAGE_SHIFT-3)) - # ifndef __ASSEMBLY__ #include #include +#include #include /* @@ -132,19 +133,19 @@ #define __P001 PAGE_READONLY #define __P010 PAGE_READONLY /* write to priv pg -> copy & make writable */ #define __P011 PAGE_READONLY /* ditto */ -#define __P100 __pgprot(_PAGE_ED | _PAGE_A | _PAGE_P | _PAGE_PL_3 | _PAGE_AR_X_RX) -#define __P101 __pgprot(_PAGE_ED | _PAGE_A | _PAGE_P | _PAGE_PL_3 | _PAGE_AR_RX) -#define __P110 __pgprot(_PAGE_ED | _PAGE_A | _PAGE_P | _PAGE_PL_3 | _PAGE_AR_RX) -#define __P111 __pgprot(_PAGE_ED | _PAGE_A | _PAGE_P | _PAGE_PL_3 | _PAGE_AR_RX) +#define __P100 __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_X_RX) +#define __P101 PAGE_COPY + #define __P110 PAGE_COPY +#define __P111 PAGE_COPY #define __S000 PAGE_NONE #define __S001 PAGE_READONLY #define __S010 PAGE_SHARED /* we don't have (and don't need) write-only */ #define __S011 PAGE_SHARED -#define __S100 __pgprot(_PAGE_ED | _PAGE_A | _PAGE_P | _PAGE_PL_3 | _PAGE_AR_X_RX) -#define __S101 __pgprot(_PAGE_ED | _PAGE_A | _PAGE_P | _PAGE_PL_3 | _PAGE_AR_RX) -#define __S110 __pgprot(_PAGE_ED | _PAGE_A | _PAGE_P | _PAGE_PL_3 | _PAGE_AR_RWX) -#define __S111 __pgprot(_PAGE_ED | _PAGE_A | _PAGE_P | _PAGE_PL_3 | _PAGE_AR_RWX) +#define __S100 __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_X_RX) +#define __S101 __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RX) +#define __S110 __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RWX) +#define __S111 __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RWX) #define pgd_ERROR(e) printk("%s:%d: bad pgd %016lx.\n", __FILE__, __LINE__, pgd_val(e)) #define pmd_ERROR(e) printk("%s:%d: bad pmd %016lx.\n", __FILE__, __LINE__, pmd_val(e)) @@ -185,7 +186,7 @@ } while (0) /* Quick test to see if ADDR is a (potentially) valid physical address. */ -static __inline__ long +static inline long ia64_phys_addr_valid (unsigned long addr) { return (addr & (my_cpu_data.unimpl_pa_mask)) == 0; @@ -219,7 +220,7 @@ #define VMALLOC_START (0xa000000000000000+2*PAGE_SIZE) #define VMALLOC_VMADDR(x) ((unsigned long)(x)) -#define VMALLOC_END 0xbfffffffffffffff +#define VMALLOC_END (0xa000000000000000+ (1UL << (4*PAGE_SHIFT - 13))) /* * BAD_PAGETABLE is used when we need a bogus page-table, while @@ -281,8 +282,8 @@ */ #define pte_read(pte) (((pte_val(pte) & _PAGE_AR_MASK) >> _PAGE_AR_SHIFT) < 6) #define pte_write(pte) ((unsigned) (((pte_val(pte) & _PAGE_AR_MASK) >> _PAGE_AR_SHIFT) - 2) < 4) -#define pte_dirty(pte) (pte_val(pte) & _PAGE_D) -#define pte_young(pte) (pte_val(pte) & _PAGE_A) +#define pte_dirty(pte) ((pte_val(pte) & _PAGE_D) != 0) +#define pte_young(pte) ((pte_val(pte) & _PAGE_A) != 0) /* * Note: we convert AR_RWX to AR_RX and AR_RW to AR_R by clearing the * 2nd bit in the access rights: @@ -317,7 +318,7 @@ /* * Return the region index for virtual address ADDRESS. */ -static __inline__ unsigned long +static inline unsigned long rgn_index (unsigned long address) { ia64_va a; @@ -329,7 +330,7 @@ /* * Return the region offset for virtual address ADDRESS. */ -static __inline__ unsigned long +static inline unsigned long rgn_offset (unsigned long address) { ia64_va a; @@ -341,7 +342,7 @@ #define RGN_SIZE (1UL << 61) #define RGN_KERNEL 7 -static __inline__ unsigned long +static inline unsigned long pgd_index (unsigned long address) { unsigned long region = address >> 61; @@ -352,7 +353,7 @@ /* The offset in the 1-level directory is given by the 3 region bits (61..63) and the seven level-1 bits (33-39). */ -static __inline__ pgd_t* +static inline pgd_t* pgd_offset (struct mm_struct *mm, unsigned long address) { return mm->pgd + pgd_index(address); @@ -371,6 +372,80 @@ #define pte_offset(dir,addr) \ ((pte_t *) pmd_page(*(dir)) + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))) +/* atomic versions of the some PTE manipulations: */ + +static inline int +ptep_test_and_clear_young (pte_t *ptep) +{ +#ifdef CONFIG_SMP + return test_and_clear_bit(_PAGE_A_BIT, ptep); +#else + pte_t pte = *ptep; + if (!pte_young(pte)) + return 0; + set_pte(ptep, pte_mkold(pte)); + return 1; +#endif +} + +static inline int +ptep_test_and_clear_dirty (pte_t *ptep) +{ +#ifdef CONFIG_SMP + return test_and_clear_bit(_PAGE_D_BIT, ptep); +#else + pte_t pte = *ptep; + if (!pte_dirty(pte)) + return 0; + set_pte(ptep, pte_mkclean(pte)); + return 1; +#endif +} + +static inline pte_t +ptep_get_and_clear (pte_t *ptep) +{ +#ifdef CONFIG_SMP + return __pte(xchg((long *) ptep, 0)); +#else + pte_t pte = *ptep; + pte_clear(ptep); + return pte; +#endif +} + +static inline void +ptep_set_wrprotect (pte_t *ptep) +{ +#ifdef CONFIG_SMP + unsigned long new, old; + + do { + old = pte_val(*ptep); + new = pte_val(pte_wrprotect(__pte (old))); + } while (cmpxchg((unsigned long *) ptep, old, new) != old); +#else + pte_t old_pte = *ptep; + set_pte(ptep, pte_wrprotect(old_pte)); +#endif +} + +static inline void +ptep_mkdirty (pte_t *ptep) +{ +#ifdef CONFIG_SMP + set_bit(_PAGE_D_BIT, ptep); +#else + pte_t old_pte = *ptep; + set_pte(ptep, pte_mkdirty(old_pte)); +#endif +} + +static inline int +pte_same (pte_t a, pte_t b) +{ + return pte_val(a) == pte_val(b); +} extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; extern void paging_init (void); @@ -397,16 +472,13 @@ # define update_mmu_cache(vma,address,pte) \ do { \ /* \ - * XXX fix me!! \ - * \ - * It's not clear this is a win. We may end up pollute the \ + * This is usually not a win. We may end up polluting the \ * dtlb with itlb entries and vice versa (e.g., consider stack \ * pages that are normally marked executable). It would be \ * better to insert the TLB entry for the TLB cache that we \ * know needs the new entry. However, the update_mmu_cache() \ * arguments don't tell us whether we got here through a data \ - * access or through an instruction fetch. Talk to Linus to \ - * fix this. \ + * access or through an instruction fetch. \ * \ * If you re-enable this code, you must disable the ptc code in \ * Entry 20 of the ivt. \ @@ -420,7 +492,7 @@ #endif #define SWP_TYPE(entry) (((entry).val >> 1) & 0xff) -#define SWP_OFFSET(entry) ((entry).val >> 9) +#define SWP_OFFSET(entry) (((entry).val << 1) >> 10) #define SWP_ENTRY(type,offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 9) }) #define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define swp_entry_to_pte(x) ((pte_t) { (x).val }) @@ -436,8 +508,6 @@ */ extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)]; #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) - -#include # endif /* !__ASSEMBLY__ */ diff -urN linux-2.4.0-test10/include/asm-ia64/processor.h linux-2.4.0-test10-lia/include/asm-ia64/processor.h --- linux-2.4.0-test10/include/asm-ia64/processor.h Mon Oct 9 17:54:59 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/processor.h Wed Nov 15 22:22:31 2000 @@ -4,7 +4,7 @@ /* * Copyright (C) 1998-2000 Hewlett-Packard Co * Copyright (C) 1998-2000 David Mosberger-Tang - * Copyright (C) 1998, 1999 Stephane Eranian + * Copyright (C) 1998-2000 Stephane Eranian * Copyright (C) 1999 Asit Mallick * Copyright (C) 1999 Don Dugger * @@ -19,7 +19,13 @@ #include #define IA64_NUM_DBG_REGS 8 -#define IA64_NUM_PM_REGS 4 +/* + * Limits for PMC and PMD are set to less than maximum architected values + * but should be sufficient for a while + */ +#define IA64_NUM_PMC_REGS 32 +#define IA64_NUM_PMD_REGS 32 +#define IA64_NUM_PMD_COUNTERS 4 /* * TASK_SIZE really is a mis-named. It really is the maximum user @@ -242,6 +248,9 @@ __u64 usec_per_cyc; /* 2^IA64_USEC_PER_CYC_SHIFT*1000000/itc_freq */ __u64 unimpl_va_mask; /* mask of unimplemented virtual address bits (from PAL) */ __u64 unimpl_pa_mask; /* mask of unimplemented physical address bits (from PAL) */ + __u64 ptce_base; + __u32 ptce_count[2]; + __u32 ptce_stride[2]; #ifdef CONFIG_SMP __u64 loops_per_sec; __u64 ipi_count; @@ -288,10 +297,15 @@ __u64 dbr[IA64_NUM_DBG_REGS]; __u64 ibr[IA64_NUM_DBG_REGS]; #ifdef CONFIG_PERFMON - __u64 pmc[IA64_NUM_PM_REGS]; - __u64 pmd[IA64_NUM_PM_REGS]; - __u64 pmod[IA64_NUM_PM_REGS]; -# define INIT_THREAD_PM {0, }, {0, }, {0, }, + __u64 pmc[IA64_NUM_PMC_REGS]; + __u64 pmd[IA64_NUM_PMD_REGS]; + struct { + __u64 val; /* virtual 64bit counter */ + __u64 rval; /* reset value on overflow */ + int sig; /* signal used to notify */ + int pid; /* process to notify */ + } pmu_counters[IA64_NUM_PMD_COUNTERS]; +# define INIT_THREAD_PM {0, }, {0, }, {{ 0, 0, 0, 0}, }, #else # define INIT_THREAD_PM #endif @@ -423,8 +437,8 @@ #endif #ifdef CONFIG_PERFMON -extern void ia64_save_pm_regs (struct thread_struct *thread); -extern void ia64_load_pm_regs (struct thread_struct *thread); +extern void ia64_save_pm_regs (struct task_struct *task); +extern void ia64_load_pm_regs (struct task_struct *task); #endif #define ia64_fph_enable() __asm__ __volatile__ (";; rsm psr.dfh;; srlz.d;;" ::: "memory"); diff -urN linux-2.4.0-test10/include/asm-ia64/sal.h linux-2.4.0-test10-lia/include/asm-ia64/sal.h --- linux-2.4.0-test10/include/asm-ia64/sal.h Mon Oct 9 17:55:00 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/sal.h Wed Nov 15 22:22:30 2000 @@ -24,7 +24,9 @@ extern spinlock_t sal_lock; -#define __SAL_CALL(result,args...) result = (*ia64_sal)(args) +/* SAL spec _requires_ eight args for each call. */ +#define __SAL_CALL(result,a0,a1,a2,a3,a4,a5,a6,a7) \ + result = (*ia64_sal)(a0,a1,a2,a3,a4,a5,a6,a7) #ifdef CONFIG_SMP # define SAL_CALL(result,args...) do { \ @@ -60,10 +62,10 @@ * informational value should be printed (e.g., "reboot for * change to take effect"). */ - s64 status; - u64 v0; - u64 v1; - u64 v2; + s64 status; + u64 v0; + u64 v1; + u64 v2; }; typedef struct ia64_sal_retval (*ia64_sal_handler) (u64, ...); @@ -78,24 +80,27 @@ * The SAL system table is followed by a variable number of variable * length descriptors. The structure of these descriptors follows * below. + * The defininition follows SAL specs from July 2000 */ struct ia64_sal_systab { - char signature[4]; /* should be "SST_" */ - int size; /* size of this table in bytes */ - unsigned char sal_rev_minor; - unsigned char sal_rev_major; - unsigned short entry_count; /* # of entries in variable portion */ - unsigned char checksum; - char ia32_bios_present; - unsigned short reserved1; - char oem_id[32]; /* ASCII NUL terminated OEM id - (terminating NUL is missing if - string is exactly 32 bytes long). */ - char product_id[32]; /* ASCII product id */ - char reserved2[16]; + u8 signature[4]; /* should be "SST_" */ + u32 size; /* size of this table in bytes */ + u8 sal_rev_minor; + u8 sal_rev_major; + u16 entry_count; /* # of entries in variable portion */ + u8 checksum; + u8 reserved1[7]; + u8 sal_a_rev_minor; + u8 sal_a_rev_major; + u8 sal_b_rev_minor; + u8 sal_b_rev_major; + /* oem_id & product_id: terminating NUL is missing if string is exactly 32 bytes long. */ + u8 oem_id[32]; + u8 product_id[32]; /* ASCII product id */ + u8 reserved2[8]; }; -enum SAL_Systab_Entry_Type { +enum sal_systab_entry_type { SAL_DESC_ENTRY_POINT = 0, SAL_DESC_MEMORY = 1, SAL_DESC_PLATFORM_FEATURE = 2, @@ -115,75 +120,78 @@ */ #define SAL_DESC_SIZE(type) "\060\040\020\040\020\020"[(unsigned) type] -struct ia64_sal_desc_entry_point { - char type; - char reserved1[7]; - s64 pal_proc; - s64 sal_proc; - s64 gp; - char reserved2[16]; -}; - -struct ia64_sal_desc_memory { - char type; - char used_by_sal; /* needs to be mapped for SAL? */ - char mem_attr; /* current memory attribute setting */ - char access_rights; /* access rights set up by SAL */ - char mem_attr_mask; /* mask of supported memory attributes */ - char reserved1; - char mem_type; /* memory type */ - char mem_usage; /* memory usage */ - s64 addr; /* physical address of memory */ - unsigned int length; /* length (multiple of 4KB pages) */ - unsigned int reserved2; - char oem_reserved[8]; -}; +typedef struct ia64_sal_desc_entry_point { + u8 type; + u8 reserved1[7]; + u64 pal_proc; + u64 sal_proc; + u64 gp; + u8 reserved2[16]; +}ia64_sal_desc_entry_point_t; + +typedef struct ia64_sal_desc_memory { + u8 type; + u8 used_by_sal; /* needs to be mapped for SAL? */ + u8 mem_attr; /* current memory attribute setting */ + u8 access_rights; /* access rights set up by SAL */ + u8 mem_attr_mask; /* mask of supported memory attributes */ + u8 reserved1; + u8 mem_type; /* memory type */ + u8 mem_usage; /* memory usage */ + u64 addr; /* physical address of memory */ + u32 length; /* length (multiple of 4KB pages) */ + u32 reserved2; + u8 oem_reserved[8]; +} ia64_sal_desc_memory_t; #define IA64_SAL_PLATFORM_FEATURE_BUS_LOCK (1 << 0) #define IA64_SAL_PLATFORM_FEATURE_IRQ_REDIR_HINT (1 << 1) #define IA64_SAL_PLATFORM_FEATURE_IPI_REDIR_HINT (1 << 2) -struct ia64_sal_desc_platform_feature { - char type; - unsigned char feature_mask; - char reserved1[14]; -}; - -struct ia64_sal_desc_tr { - char type; - char tr_type; /* 0 == instruction, 1 == data */ - char regnum; /* translation register number */ - char reserved1[5]; - s64 addr; /* virtual address of area covered */ - s64 page_size; /* encoded page size */ - char reserved2[8]; -}; +typedef struct ia64_sal_desc_platform_feature { + u8 type; + u8 feature_mask; + u8 reserved1[14]; +} ia64_sal_desc_platform_feature_t; + +typedef struct ia64_sal_desc_tr { + u8 type; + u8 tr_type; /* 0 == instruction, 1 == data */ + u8 regnum; /* translation register number */ + u8 reserved1[5]; + u64 addr; /* virtual address of area covered */ + u64 page_size; /* encoded page size */ + u8 reserved2[8]; +} ia64_sal_desc_tr_t; typedef struct ia64_sal_desc_ptc { - char type; - char reserved1[3]; - unsigned int num_domains; /* # of coherence domains */ - s64 domain_info; /* physical address of domain info table */ + u8 type; + u8 reserved1[3]; + u32 num_domains; /* # of coherence domains */ + u64 domain_info; /* physical address of domain info table */ } ia64_sal_desc_ptc_t; typedef struct ia64_sal_ptc_domain_info { - unsigned long proc_count; /* number of processors in domain */ - long proc_list; /* physical address of LID array */ + u64 proc_count; /* number of processors in domain */ + u64 proc_list; /* physical address of LID array */ } ia64_sal_ptc_domain_info_t; typedef struct ia64_sal_ptc_domain_proc_entry { - unsigned char id; /* id of processor */ - unsigned char eid; /* eid of processor */ + u64 reserved : 16; + u64 eid : 8; /* eid of processor */ + u64 id : 8; /* id of processor */ + u64 ignored : 32; } ia64_sal_ptc_domain_proc_entry_t; + #define IA64_SAL_AP_EXTERNAL_INT 0 -struct ia64_sal_desc_ap_wakeup { - char type; - char mechanism; /* 0 == external interrupt */ - char reserved1[6]; - long vector; /* interrupt vector in range 0x10-0xff */ -}; +typedef struct ia64_sal_desc_ap_wakeup { + u8 type; + u8 mechanism; /* 0 == external interrupt */ + u8 reserved1[6]; + u64 vector; /* interrupt vector in range 0x10-0xff */ +} ia64_sal_desc_ap_wakeup_t ; extern ia64_sal_handler ia64_sal; extern struct ia64_sal_desc_ptc *ia64_ptc_domain_info; @@ -218,24 +226,24 @@ /* Encodings for vectors which can be registered by the OS with SAL */ enum { - SAL_VECTOR_OS_MCA = 0, - SAL_VECTOR_OS_INIT = 1, - SAL_VECTOR_OS_BOOT_RENDEZ = 2 + SAL_VECTOR_OS_MCA = 0, + SAL_VECTOR_OS_INIT = 1, + SAL_VECTOR_OS_BOOT_RENDEZ = 2 }; /* Definition of the SAL Error Log from the SAL spec */ /* Definition of timestamp according to SAL spec for logging purposes */ -typedef struct sal_log_timestamp_s { - u8 slh_century; /* Century (19, 20, 21, ...) */ - u8 slh_year; /* Year (00..99) */ - u8 slh_month; /* Month (1..12) */ - u8 slh_day; /* Day (1..31) */ - u8 slh_reserved; - u8 slh_hour; /* Hour (0..23) */ - u8 slh_minute; /* Minute (0..59) */ - u8 slh_second; /* Second (0..59) */ +typedef struct sal_log_timestamp { + u8 slh_century; /* Century (19, 20, 21, ...) */ + u8 slh_year; /* Year (00..99) */ + u8 slh_month; /* Month (1..12) */ + u8 slh_day; /* Day (1..31) */ + u8 slh_reserved; + u8 slh_hour; /* Hour (0..23) */ + u8 slh_minute; /* Minute (0..59) */ + u8 slh_second; /* Second (0..59) */ } sal_log_timestamp_t; @@ -243,126 +251,126 @@ #define MAX_TLB_ERRORS 6 #define MAX_BUS_ERRORS 1 -typedef struct sal_log_processor_info_s { +typedef struct sal_log_processor_info { struct { - u64 slpi_psi : 1, - slpi_cache_check: MAX_CACHE_ERRORS, - slpi_tlb_check : MAX_TLB_ERRORS, - slpi_bus_check : MAX_BUS_ERRORS, - slpi_reserved2 : (31 - (MAX_TLB_ERRORS + MAX_CACHE_ERRORS - + MAX_BUS_ERRORS)), - slpi_minstate : 1, - slpi_bank1_gr : 1, - slpi_br : 1, - slpi_cr : 1, - slpi_ar : 1, - slpi_rr : 1, - slpi_fr : 1, - slpi_reserved1 : 25; + u64 slpi_psi : 1, + slpi_cache_check: MAX_CACHE_ERRORS, + slpi_tlb_check : MAX_TLB_ERRORS, + slpi_bus_check : MAX_BUS_ERRORS, + slpi_reserved2 : (31 - (MAX_TLB_ERRORS + MAX_CACHE_ERRORS + + MAX_BUS_ERRORS)), + slpi_minstate : 1, + slpi_bank1_gr : 1, + slpi_br : 1, + slpi_cr : 1, + slpi_ar : 1, + slpi_rr : 1, + slpi_fr : 1, + slpi_reserved1 : 25; } slpi_valid; - pal_processor_state_info_t slpi_processor_state_info; + pal_processor_state_info_t slpi_processor_state_info; struct { - pal_cache_check_info_t slpi_cache_check; - u64 slpi_target_address; + pal_cache_check_info_t slpi_cache_check; + u64 slpi_target_address; } slpi_cache_check_info[MAX_CACHE_ERRORS]; - pal_tlb_check_info_t slpi_tlb_check_info[MAX_TLB_ERRORS]; + pal_tlb_check_info_t slpi_tlb_check_info[MAX_TLB_ERRORS]; struct { - pal_bus_check_info_t slpi_bus_check; - u64 slpi_requestor_addr; - u64 slpi_responder_addr; - u64 slpi_target_addr; + pal_bus_check_info_t slpi_bus_check; + u64 slpi_requestor_addr; + u64 slpi_responder_addr; + u64 slpi_target_addr; } slpi_bus_check_info[MAX_BUS_ERRORS]; - pal_min_state_area_t slpi_min_state_area; - u64 slpi_br[8]; - u64 slpi_cr[128]; - u64 slpi_ar[128]; - u64 slpi_rr[8]; - u64 slpi_fr[128]; + pal_min_state_area_t slpi_min_state_area; + u64 slpi_br[8]; + u64 slpi_cr[128]; + u64 slpi_ar[128]; + u64 slpi_rr[8]; + u64 slpi_fr[128]; } sal_log_processor_info_t; /* platform error log structures */ typedef struct platerr_logheader { - u64 nextlog; /* next log offset if present */ - u64 loglength; /* log length */ - u64 logsubtype; /* log subtype memory/bus/component */ - u64 eseverity; /* error severity */ + u64 nextlog; /* next log offset if present */ + u64 loglength; /* log length */ + u64 logsubtype; /* log subtype memory/bus/component */ + u64 eseverity; /* error severity */ } ehdr_t; typedef struct sysmem_errlog { - ehdr_t lhdr; /* header */ - u64 vflag; /* valid bits for each field in the log */ - u64 addr; /* memory address */ - u64 data; /* memory data */ - u64 cmd; /* command bus value if any */ - u64 ctrl; /* control bus value if any */ - u64 addrsyndrome; /* memory address ecc/parity syndrome bits */ - u64 datasyndrome; /* data ecc/parity syndrome */ - u64 cacheinfo; /* platform cache info as defined in pal spec. table 7-34 */ + ehdr_t lhdr; /* header */ + u64 vflag; /* valid bits for each field in the log */ + u64 addr; /* memory address */ + u64 data; /* memory data */ + u64 cmd; /* command bus value if any */ + u64 ctrl; /* control bus value if any */ + u64 addrsyndrome; /* memory address ecc/parity syndrome bits */ + u64 datasyndrome; /* data ecc/parity syndrome */ + u64 cacheinfo; /* platform cache info as defined in pal spec. table 7-34 */ } merrlog_t; typedef struct sysbus_errlog { - ehdr_t lhdr; /* linkded list header */ - u64 vflag; /* valid bits for each field in the log */ - u64 busnum; /* bus number in error */ - u64 reqaddr; /* requestor address */ - u64 resaddr; /* responder address */ - u64 taraddr; /* target address */ - u64 data; /* requester r/w data */ - u64 cmd; /* bus commands */ - u64 ctrl; /* bus controls (be# &-0) */ - u64 addrsyndrome; /* addr bus ecc/parity bits */ - u64 datasyndrome; /* data bus ecc/parity bits */ - u64 cmdsyndrome; /* command bus ecc/parity bits */ - u64 ctrlsyndrome; /* control bus ecc/parity bits */ + ehdr_t lhdr; /* linkded list header */ + u64 vflag; /* valid bits for each field in the log */ + u64 busnum; /* bus number in error */ + u64 reqaddr; /* requestor address */ + u64 resaddr; /* responder address */ + u64 taraddr; /* target address */ + u64 data; /* requester r/w data */ + u64 cmd; /* bus commands */ + u64 ctrl; /* bus controls (be# &-0) */ + u64 addrsyndrome; /* addr bus ecc/parity bits */ + u64 datasyndrome; /* data bus ecc/parity bits */ + u64 cmdsyndrome; /* command bus ecc/parity bits */ + u64 ctrlsyndrome; /* control bus ecc/parity bits */ } berrlog_t; /* platform error log structures */ typedef struct syserr_chdr { /* one header per component */ - u64 busnum; /* bus number on which the component resides */ - u64 devnum; /* same as device select */ - u64 funcid; /* function id of the device */ - u64 devid; /* pci device id */ - u64 classcode; /* pci class code for the device */ - u64 cmdreg; /* pci command reg value */ - u64 statreg; /* pci status reg value */ + u64 busnum; /* bus number on which the component resides */ + u64 devnum; /* same as device select */ + u64 funcid; /* function id of the device */ + u64 devid; /* pci device id */ + u64 classcode; /* pci class code for the device */ + u64 cmdreg; /* pci command reg value */ + u64 statreg; /* pci status reg value */ } chdr_t; typedef struct cfginfo { - u64 cfgaddr; - u64 cfgval; + u64 cfgaddr; + u64 cfgval; } cfginfo_t; typedef struct sys_comperr { /* per component */ - ehdr_t lhdr; /* linked list header */ - u64 vflag; /* valid bits for each field in the log */ - chdr_t scomphdr; - u64 numregpair; /* number of reg addr/value pairs */ + ehdr_t lhdr; /* linked list header */ + u64 vflag; /* valid bits for each field in the log */ + chdr_t scomphdr; + u64 numregpair; /* number of reg addr/value pairs */ cfginfo_t cfginfo; } cerrlog_t; typedef struct sel_records { - ehdr_t lhdr; - u64 seldata; + ehdr_t lhdr; + u64 seldata; } isel_t; typedef struct plat_errlog { - u64 mbcsvalid; /* valid bits for each type of log */ - merrlog_t smemerrlog; /* platform memory error logs */ - berrlog_t sbuserrlog; /* platform bus error logs */ - cerrlog_t scomperrlog; /* platform chipset error logs */ - isel_t selrecord; /* ipmi sel record */ + u64 mbcsvalid; /* valid bits for each type of log */ + merrlog_t smemerrlog; /* platform memory error logs */ + berrlog_t sbuserrlog; /* platform bus error logs */ + cerrlog_t scomperrlog; /* platform chipset error logs */ + isel_t selrecord; /* ipmi sel record */ } platforminfo_t; /* over all log structure (processor+platform) */ typedef union udev_specific_log { - sal_log_processor_info_t proclog; - platforminfo_t platlog; + sal_log_processor_info_t proclog; + platforminfo_t platlog; } devicelog_t; @@ -378,21 +386,18 @@ #define sal_log_processor_info_rr_valid slpi_valid.slpi_rr #define sal_log_processor_info_fr_valid slpi_valid.slpi_fr -typedef struct sal_log_header_s { - u64 slh_next_log; /* Offset of the next log from the - * beginning of this structure. - */ - uint slh_log_len; /* Length of this error log in bytes */ - ushort slh_log_type; /* Type of log (0 - cpu ,1 - platform) */ - ushort slh_log_sub_type; /* SGI specific sub type */ - sal_log_timestamp_t slh_log_timestamp; /* Timestamp */ +typedef struct sal_log_header { + u64 slh_next_log; /* Offset of the next log from the beginning of this structure */ + u32 slh_log_len; /* Length of this error log in bytes */ + u16 slh_log_type; /* Type of log (0 - cpu ,1 - platform) */ + u16 slh_log_sub_type; /* SGI specific sub type */ + sal_log_timestamp_t slh_log_timestamp; /* Timestamp */ } sal_log_header_t; /* SAL PSI log structure */ -typedef struct psilog -{ - sal_log_header_t sal_elog_header; - devicelog_t devlog; +typedef struct psilog { + sal_log_header_t sal_elog_header; + devicelog_t devlog; } ia64_psilog_t; /* @@ -405,7 +410,7 @@ { struct ia64_sal_retval isrv; - SAL_CALL(isrv, SAL_FREQ_BASE, which); + SAL_CALL(isrv, SAL_FREQ_BASE, which, 0, 0, 0, 0, 0, 0); *ticks_per_second = isrv.v0; *drift_info = isrv.v1; return isrv.status; @@ -416,7 +421,7 @@ ia64_sal_cache_flush (u64 cache_type) { struct ia64_sal_retval isrv; - SAL_CALL(isrv, SAL_CACHE_FLUSH, cache_type); + SAL_CALL(isrv, SAL_CACHE_FLUSH, cache_type, 0, 0, 0, 0, 0, 0); return isrv.status; } @@ -427,7 +432,7 @@ ia64_sal_cache_init (void) { struct ia64_sal_retval isrv; - SAL_CALL(isrv, SAL_CACHE_INIT); + SAL_CALL(isrv, SAL_CACHE_INIT, 0, 0, 0, 0, 0, 0, 0); return isrv.status; } @@ -438,7 +443,8 @@ ia64_sal_clear_state_info (u64 sal_info_type, u64 sal_info_sub_type) { struct ia64_sal_retval isrv; - SAL_CALL(isrv, SAL_CLEAR_STATE_INFO, sal_info_type, sal_info_sub_type); + SAL_CALL(isrv, SAL_CLEAR_STATE_INFO, sal_info_type, sal_info_sub_type, + 0, 0, 0, 0, 0); return isrv.status; } @@ -450,7 +456,8 @@ ia64_sal_get_state_info (u64 sal_info_type, u64 sal_info_sub_type, u64 *sal_info) { struct ia64_sal_retval isrv; - SAL_CALL(isrv, SAL_GET_STATE_INFO, sal_info_type, sal_info_sub_type, sal_info); + SAL_CALL(isrv, SAL_GET_STATE_INFO, sal_info_type, sal_info_sub_type, + sal_info, 0, 0, 0, 0); if (isrv.status) return 0; return isrv.v0; @@ -462,7 +469,8 @@ ia64_sal_get_state_info_size (u64 sal_info_type, u64 sal_info_sub_type) { struct ia64_sal_retval isrv; - SAL_CALL(isrv, SAL_GET_STATE_INFO_SIZE, sal_info_type, sal_info_sub_type); + SAL_CALL(isrv, SAL_GET_STATE_INFO_SIZE, sal_info_type, sal_info_sub_type, + 0, 0, 0, 0, 0); if (isrv.status) return 0; return isrv.v0; @@ -475,7 +483,7 @@ ia64_sal_mc_rendez (void) { struct ia64_sal_retval isrv; - SAL_CALL(isrv, SAL_MC_RENDEZ); + SAL_CALL(isrv, SAL_MC_RENDEZ, 0, 0, 0, 0, 0, 0, 0); return isrv.status; } @@ -487,7 +495,8 @@ ia64_sal_mc_set_params (u64 param_type, u64 i_or_m, u64 i_or_m_val, u64 timeout) { struct ia64_sal_retval isrv; - SAL_CALL(isrv, SAL_MC_SET_PARAMS, param_type, i_or_m, i_or_m_val, timeout); + SAL_CALL(isrv, SAL_MC_SET_PARAMS, param_type, i_or_m, i_or_m_val, timeout, + 0, 0, 0); return isrv.status; } @@ -505,7 +514,7 @@ */ spin_lock_irqsave(&ivr_read_lock, flags); #endif - SAL_CALL(isrv, SAL_PCI_CONFIG_READ, pci_config_addr, size); + SAL_CALL(isrv, SAL_PCI_CONFIG_READ, pci_config_addr, size, 0, 0, 0, 0, 0); #ifdef CONFIG_ITANIUM_A1_SPECIFIC spin_unlock_irqrestore(&ivr_read_lock, flags); #endif @@ -528,7 +537,8 @@ */ spin_lock_irqsave(&ivr_read_lock, flags); #endif - SAL_CALL(isrv, SAL_PCI_CONFIG_WRITE, pci_config_addr, size, value); + SAL_CALL(isrv, SAL_PCI_CONFIG_WRITE, pci_config_addr, size, value, + 0, 0, 0, 0); #ifdef CONFIG_ITANIUM_A1_SPECIFIC spin_unlock_irqrestore(&ivr_read_lock, flags); #endif @@ -543,7 +553,8 @@ ia64_sal_register_physical_addr (u64 phys_entry, u64 phys_addr) { struct ia64_sal_retval isrv; - SAL_CALL(isrv, SAL_REGISTER_PHYSICAL_ADDR, phys_entry, phys_addr); + SAL_CALL(isrv, SAL_REGISTER_PHYSICAL_ADDR, phys_entry, phys_addr, + 0, 0, 0, 0, 0); return isrv.status; } @@ -569,7 +580,8 @@ u64 *error_code, u64 *scratch_buf_size_needed) { struct ia64_sal_retval isrv; - SAL_CALL(isrv, SAL_UPDATE_PAL, param_buf, scratch_buf, scratch_buf_size); + SAL_CALL(isrv, SAL_UPDATE_PAL, param_buf, scratch_buf, scratch_buf_size, + 0, 0, 0, 0); if (error_code) *error_code = isrv.v0; if (scratch_buf_size_needed) diff -urN linux-2.4.0-test10/include/asm-ia64/spinlock.h linux-2.4.0-test10-lia/include/asm-ia64/spinlock.h --- linux-2.4.0-test10/include/asm-ia64/spinlock.h Mon Oct 9 17:55:00 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/spinlock.h Wed Nov 15 22:22:31 2000 @@ -18,8 +18,9 @@ #undef NEW_LOCK #ifdef NEW_LOCK + typedef struct { - volatile unsigned char lock; + volatile unsigned int lock; } spinlock_t; #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } @@ -38,7 +39,7 @@ "mov r30=1\n" \ "mov ar.ccv=r0\n" \ ";;\n" \ - IA64_SEMFIX"cmpxchg1.acq r30=[%0],r30,ar.ccv\n" \ + IA64_SEMFIX"cmpxchg4.acq r30=[%0],r30,ar.ccv\n" \ ";;\n" \ "cmp.ne p15,p0=r30,r0\n" \ "(p15) br.call.spnt.few b7=ia64_spinlock_contention\n" \ @@ -48,18 +49,16 @@ : "ar.ccv", "ar.pfs", "b7", "p15", "r28", "r29", "r30", "memory"); \ } -#define spin_trylock(x) \ -({ \ - register char *addr __asm__ ("r31") = (char *) &(x)->lock; \ - register long result; \ - \ - __asm__ __volatile__ ( \ - "mov r30=1\n" \ - "mov ar.ccv=r0\n" \ - ";;\n" \ - IA64_SEMFIX"cmpxchg1.acq %0=[%1],r30,ar.ccv\n" \ - : "=r"(result) : "r"(addr) : "ar.ccv", "r30", "memory"); \ - (result == 0); \ +#define spin_trylock(x) \ +({ \ + register long result; \ + \ + __asm__ __volatile__ ( \ + "mov ar.ccv=r0\n" \ + ";;\n" \ + IA64_SEMFIX"cmpxchg4.acq %0=[%2],%1,ar.ccv\n" \ + : "=r"(result) : "r"(1), "r"(&(x)->lock) : "ar.ccv", "memory"); \ + (result == 0); \ }) #define spin_is_locked(x) ((x)->lock != 0) diff -urN linux-2.4.0-test10/include/asm-ia64/system.h linux-2.4.0-test10-lia/include/asm-ia64/system.h --- linux-2.4.0-test10/include/asm-ia64/system.h Mon Oct 9 17:55:00 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/system.h Wed Nov 15 22:22:31 2000 @@ -27,7 +27,8 @@ #define GATE_ADDR (0xa000000000000000 + PAGE_SIZE) -#if defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) || defined(CONFIG_ITANIUM_BSTEP_SPECIFIC) +#if defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) \ + || defined(CONFIG_ITANIUM_B0_SPECIFIC) || defined(CONFIG_ITANIUM_B1_SPECIFIC) /* Workaround for Errata 97. */ # define IA64_SEMFIX_INSN mf; # define IA64_SEMFIX "mf;" diff -urN linux-2.4.0-test10/include/asm-ia64/uaccess.h linux-2.4.0-test10-lia/include/asm-ia64/uaccess.h --- linux-2.4.0-test10/include/asm-ia64/uaccess.h Mon Oct 9 17:55:00 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/uaccess.h Wed Nov 15 22:22:32 2000 @@ -125,46 +125,28 @@ struct __large_struct { unsigned long buf[100]; }; #define __m(x) (*(struct __large_struct *)(x)) -#define __get_user_64(addr) \ +/* We need to declare the __ex_table section before we can use it in .xdata. */ +__asm__ (".section \"__ex_table\", \"a\"\n\t.previous"); + +#define __get_user_64(addr) \ __asm__ ("\n1:\tld8 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n" \ - "2:\n" \ - "\t.section __ex_table,\"a\"\n" \ - "\t\tdata4 @gprel(1b)\n" \ - "\t\tdata4 (2b-1b)|1\n" \ - "\t.previous" \ - : "=r"(__gu_val), "=r"(__gu_err) \ - : "m"(__m(addr)), "1"(__gu_err)); + "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)|1\n" \ + : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err)); -#define __get_user_32(addr) \ +#define __get_user_32(addr) \ __asm__ ("\n1:\tld4 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n" \ - "2:\n" \ - "\t.section __ex_table,\"a\"\n" \ - "\t\tdata4 @gprel(1b)\n" \ - "\t\tdata4 (2b-1b)|1\n" \ - "\t.previous" \ - : "=r"(__gu_val), "=r"(__gu_err) \ - : "m"(__m(addr)), "1"(__gu_err)); + "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)|1\n" \ + : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err)); -#define __get_user_16(addr) \ +#define __get_user_16(addr) \ __asm__ ("\n1:\tld2 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n" \ - "2:\n" \ - "\t.section __ex_table,\"a\"\n" \ - "\t\tdata4 @gprel(1b)\n" \ - "\t\tdata4 (2b-1b)|1\n" \ - "\t.previous" \ - : "=r"(__gu_val), "=r"(__gu_err) \ - : "m"(__m(addr)), "1"(__gu_err)); + "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)|1\n" \ + : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err)); -#define __get_user_8(addr) \ +#define __get_user_8(addr) \ __asm__ ("\n1:\tld1 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n" \ - "2:\n" \ - "\t.section __ex_table,\"a\"\n" \ - "\t\tdata4 @gprel(1b)\n" \ - "\t\tdata4 (2b-1b)|1\n" \ - "\t.previous" \ - : "=r"(__gu_val), "=r"(__gu_err) \ - : "m"(__m(addr)), "1"(__gu_err)); - + "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)|1\n" \ + : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err)); extern void __put_user_unknown (void); @@ -206,46 +188,26 @@ #define __put_user_64(x,addr) \ __asm__ __volatile__ ( \ "\n1:\tst8 %1=%r2%P1\t// %0 gets overwritten by exception handler\n" \ - "2:\n" \ - "\t.section __ex_table,\"a\"\n" \ - "\t\tdata4 @gprel(1b)\n" \ - "\t\tdata4 2b-1b\n" \ - "\t.previous" \ - : "=r"(__pu_err) \ - : "m"(__m(addr)), "rO"(x), "0"(__pu_err)) + "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)\n" \ + : "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err)) #define __put_user_32(x,addr) \ __asm__ __volatile__ ( \ "\n1:\tst4 %1=%r2%P1\t// %0 gets overwritten by exception handler\n" \ - "2:\n" \ - "\t.section __ex_table,\"a\"\n" \ - "\t\tdata4 @gprel(1b)\n" \ - "\t\tdata4 2b-1b\n" \ - "\t.previous" \ - : "=r"(__pu_err) \ - : "m"(__m(addr)), "rO"(x), "0"(__pu_err)) + "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)\n" \ + : "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err)) #define __put_user_16(x,addr) \ __asm__ __volatile__ ( \ "\n1:\tst2 %1=%r2%P1\t// %0 gets overwritten by exception handler\n" \ - "2:\n" \ - "\t.section __ex_table,\"a\"\n" \ - "\t\tdata4 @gprel(1b)\n" \ - "\t\tdata4 2b-1b\n" \ - "\t.previous" \ - : "=r"(__pu_err) \ - : "m"(__m(addr)), "rO"(x), "0"(__pu_err)) + "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)\n" \ + : "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err)) #define __put_user_8(x,addr) \ __asm__ __volatile__ ( \ "\n1:\tst1 %1=%r2%P1\t// %0 gets overwritten by exception handler\n" \ - "2:\n" \ - "\t.section __ex_table,\"a\"\n" \ - "\t\tdata4 @gprel(1b)\n" \ - "\t\tdata4 2b-1b\n" \ - "\t.previous" \ - : "=r"(__pu_err) \ - : "m"(__m(addr)), "rO"(x), "0"(__pu_err)) + "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)\n" \ + : "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err)) /* * Complex access routines diff -urN linux-2.4.0-test10/include/asm-ia64/unistd.h linux-2.4.0-test10-lia/include/asm-ia64/unistd.h --- linux-2.4.0-test10/include/asm-ia64/unistd.h Mon Oct 9 17:55:01 2000 +++ linux-2.4.0-test10-lia/include/asm-ia64/unistd.h Tue Oct 31 00:18:03 2000 @@ -160,7 +160,7 @@ #define __NR_nanosleep 1168 #define __NR_nfsservctl 1169 #define __NR_prctl 1170 -#define __NR_getpagesize 1171 +/* 1171 is reserved for backwards compatibility with old __NR_getpagesize */ #define __NR_mmap2 1172 #define __NR_pciconfig_read 1173 #define __NR_pciconfig_write 1174 diff -urN linux-2.4.0-test10/include/asm-m68k/module.h linux-2.4.0-test10-lia/include/asm-m68k/module.h --- linux-2.4.0-test10/include/asm-m68k/module.h Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/include/asm-m68k/module.h Mon Oct 30 22:17:11 2000 @@ -0,0 +1,11 @@ +#ifndef _ASM_M68K_MODULE_H +#define _ASM_M68K_MODULE_H +/* + * This file contains the m68k architecture specific module code. + */ + +#define module_map(x) vmalloc(x) +#define module_unmap(x) vfree(x) +#define module_arch_init(x) (0) + +#endif /* _ASM_M68K_MODULE_H */ diff -urN linux-2.4.0-test10/include/asm-m68k/pgtable.h linux-2.4.0-test10-lia/include/asm-m68k/pgtable.h --- linux-2.4.0-test10/include/asm-m68k/pgtable.h Wed Oct 18 14:25:46 2000 +++ linux-2.4.0-test10-lia/include/asm-m68k/pgtable.h Wed Nov 1 14:58:17 2000 @@ -390,9 +390,6 @@ #endif /* __ASSEMBLY__ */ -#define module_map vmalloc -#define module_unmap vfree - /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ #define PageSkip(page) (0) #define kern_addr_valid(addr) (1) diff -urN linux-2.4.0-test10/include/asm-mips/module.h linux-2.4.0-test10-lia/include/asm-mips/module.h --- linux-2.4.0-test10/include/asm-mips/module.h Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/include/asm-mips/module.h Mon Oct 30 22:17:12 2000 @@ -0,0 +1,11 @@ +#ifndef _ASM_MIPS_MODULE_H +#define _ASM_MIPS_MODULE_H +/* + * This file contains the mips architecture specific module code. + */ + +#define module_map(x) vmalloc(x) +#define module_unmap(x) vfree(x) +#define module_arch_init(x) (0) + +#endif /* _ASM_MIPS_MODULE_H */ diff -urN linux-2.4.0-test10/include/asm-mips/pgtable.h linux-2.4.0-test10-lia/include/asm-mips/pgtable.h --- linux-2.4.0-test10/include/asm-mips/pgtable.h Wed Oct 18 14:25:46 2000 +++ linux-2.4.0-test10-lia/include/asm-mips/pgtable.h Wed Nov 1 14:58:17 2000 @@ -451,10 +451,6 @@ #define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define swp_entry_to_pte(x) ((pte_t) { (x).val }) - -#define module_map vmalloc -#define module_unmap vfree - /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ #define PageSkip(page) (0) #define kern_addr_valid(addr) (1) diff -urN linux-2.4.0-test10/include/asm-mips64/module.h linux-2.4.0-test10-lia/include/asm-mips64/module.h --- linux-2.4.0-test10/include/asm-mips64/module.h Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/include/asm-mips64/module.h Mon Oct 30 22:17:12 2000 @@ -0,0 +1,11 @@ +#ifndef _ASM_MIPS64_MODULE_H +#define _ASM_MIPS64_MODULE_H +/* + * This file contains the mips64 architecture specific module code. + */ + +#define module_map(x) vmalloc(x) +#define module_unmap(x) vfree(x) +#define module_arch_init(x) (0) + +#endif /* _ASM_MIPS64_MODULE_H */ diff -urN linux-2.4.0-test10/include/asm-mips64/pgtable.h linux-2.4.0-test10-lia/include/asm-mips64/pgtable.h --- linux-2.4.0-test10/include/asm-mips64/pgtable.h Wed Oct 18 14:25:46 2000 +++ linux-2.4.0-test10-lia/include/asm-mips64/pgtable.h Wed Nov 1 14:58:17 2000 @@ -525,9 +525,6 @@ #define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define swp_entry_to_pte(x) ((pte_t) { (x).val }) -#define module_map vmalloc -#define module_unmap vfree - /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ #define PageSkip(page) test_bit(PG_skip, &(page)->flags) #ifndef CONFIG_DISCONTIGMEM diff -urN linux-2.4.0-test10/include/asm-ppc/module.h linux-2.4.0-test10-lia/include/asm-ppc/module.h --- linux-2.4.0-test10/include/asm-ppc/module.h Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/include/asm-ppc/module.h Mon Oct 30 22:17:12 2000 @@ -0,0 +1,11 @@ +#ifndef _ASM_PPC_MODULE_H +#define _ASM_PPC_MODULE_H +/* + * This file contains the PPC architecture specific module code. + */ + +#define module_map(x) vmalloc(x) +#define module_unmap(x) vfree(x) +#define module_arch_init(x) (0) + +#endif /* _ASM_PPC_MODULE_H */ diff -urN linux-2.4.0-test10/include/asm-ppc/pgtable.h linux-2.4.0-test10-lia/include/asm-ppc/pgtable.h --- linux-2.4.0-test10/include/asm-ppc/pgtable.h Wed Oct 18 14:25:46 2000 +++ linux-2.4.0-test10-lia/include/asm-ppc/pgtable.h Wed Nov 1 14:58:17 2000 @@ -451,9 +451,6 @@ #define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define swp_entry_to_pte(x) ((pte_t) { (x).val }) -#define module_map vmalloc -#define module_unmap vfree - /* CONFIG_APUS */ /* For virtual address to physical address conversion */ extern void cache_clear(__u32 addr, int length); diff -urN linux-2.4.0-test10/include/asm-s390/module.h linux-2.4.0-test10-lia/include/asm-s390/module.h --- linux-2.4.0-test10/include/asm-s390/module.h Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/include/asm-s390/module.h Mon Oct 30 22:17:12 2000 @@ -0,0 +1,11 @@ +#ifndef _ASM_S390_MODULE_H +#define _ASM_S390_MODULE_H +/* + * This file contains the s390 architecture specific module code. + */ + +#define module_map(x) vmalloc(x) +#define module_unmap(x) vfree(x) +#define module_arch_init(x) (0) + +#endif /* _ASM_S390_MODULE_H */ diff -urN linux-2.4.0-test10/include/asm-s390/pgtable.h linux-2.4.0-test10-lia/include/asm-s390/pgtable.h --- linux-2.4.0-test10/include/asm-s390/pgtable.h Wed Oct 18 14:25:46 2000 +++ linux-2.4.0-test10-lia/include/asm-s390/pgtable.h Wed Nov 1 14:58:17 2000 @@ -405,9 +405,6 @@ #define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define swp_entry_to_pte(x) ((pte_t) { (x).val }) -#define module_map vmalloc -#define module_unmap vfree - #include #endif /* !__ASSEMBLY__ */ diff -urN linux-2.4.0-test10/include/asm-sh/module.h linux-2.4.0-test10-lia/include/asm-sh/module.h --- linux-2.4.0-test10/include/asm-sh/module.h Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/include/asm-sh/module.h Mon Oct 30 22:17:12 2000 @@ -0,0 +1,11 @@ +#ifndef _ASM_SH_MODULE_H +#define _ASM_SH_MODULE_H +/* + * This file contains the SH architecture specific module code. + */ + +#define module_map(x) vmalloc(x) +#define module_unmap(x) vfree(x) +#define module_arch_init(x) (0) + +#endif /* _ASM_SH_MODULE_H */ diff -urN linux-2.4.0-test10/include/asm-sh/pgtable.h linux-2.4.0-test10-lia/include/asm-sh/pgtable.h --- linux-2.4.0-test10/include/asm-sh/pgtable.h Wed Oct 18 14:25:46 2000 +++ linux-2.4.0-test10-lia/include/asm-sh/pgtable.h Wed Nov 1 14:58:17 2000 @@ -254,9 +254,6 @@ #define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define swp_entry_to_pte(x) ((pte_t) { (x).val }) -#define module_map vmalloc -#define module_unmap vfree - #include #endif /* !__ASSEMBLY__ */ diff -urN linux-2.4.0-test10/include/asm-sparc/module.h linux-2.4.0-test10-lia/include/asm-sparc/module.h --- linux-2.4.0-test10/include/asm-sparc/module.h Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/include/asm-sparc/module.h Mon Oct 30 22:17:12 2000 @@ -0,0 +1,11 @@ +#ifndef _ASM_SPARC_MODULE_H +#define _ASM_SPARC_MODULE_H +/* + * This file contains the sparc architecture specific module code. + */ + +#define module_map(x) vmalloc(x) +#define module_unmap(x) vfree(x) +#define module_arch_init(x) (0) + +#endif /* _ASM_SPARC_MODULE_H */ diff -urN linux-2.4.0-test10/include/asm-sparc/pgtable.h linux-2.4.0-test10-lia/include/asm-sparc/pgtable.h --- linux-2.4.0-test10/include/asm-sparc/pgtable.h Mon Oct 30 14:34:12 2000 +++ linux-2.4.0-test10-lia/include/asm-sparc/pgtable.h Wed Nov 1 14:58:18 2000 @@ -437,8 +437,6 @@ } } -#define module_map vmalloc -#define module_unmap vfree extern unsigned long *sparc_valid_addr_bitmap; /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ diff -urN linux-2.4.0-test10/include/asm-sparc64/module.h linux-2.4.0-test10-lia/include/asm-sparc64/module.h --- linux-2.4.0-test10/include/asm-sparc64/module.h Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test10-lia/include/asm-sparc64/module.h Mon Oct 30 22:17:12 2000 @@ -0,0 +1,11 @@ +#ifndef _ASM_SPARC64_MODULE_H +#define _ASM_SPARC64_MODULE_H +/* + * This file contains the sparc64 architecture specific module code. + */ + +extern void * module_map (unsigned long size); +extern void module_unmap (void *addr); +#define module_arch_init (x) (0) + +#endif /* _ASM_SPARC64_MODULE_H */ diff -urN linux-2.4.0-test10/include/asm-sparc64/pgtable.h linux-2.4.0-test10-lia/include/asm-sparc64/pgtable.h --- linux-2.4.0-test10/include/asm-sparc64/pgtable.h Mon Oct 23 15:48:28 2000 +++ linux-2.4.0-test10-lia/include/asm-sparc64/pgtable.h Wed Nov 1 14:58:18 2000 @@ -284,8 +284,6 @@ return ((sun4u_get_pte (addr) & 0xf0000000) >> 28); } -extern void * module_map (unsigned long size); -extern void module_unmap (void *addr); extern unsigned long *sparc64_valid_addr_bitmap; /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ diff -urN linux-2.4.0-test10/include/linux/irq.h linux-2.4.0-test10-lia/include/linux/irq.h --- linux-2.4.0-test10/include/linux/irq.h Tue Oct 31 11:18:05 2000 +++ linux-2.4.0-test10-lia/include/linux/irq.h Wed Nov 15 22:22:34 2000 @@ -56,6 +56,7 @@ #include /* the arch dependent stuff */ +extern unsigned int do_IRQ (unsigned long irq, struct pt_regs *regs); extern int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); extern int setup_irq(unsigned int , struct irqaction * ); diff -urN linux-2.4.0-test10/include/linux/mm.h linux-2.4.0-test10-lia/include/linux/mm.h --- linux-2.4.0-test10/include/linux/mm.h Tue Oct 31 11:18:05 2000 +++ linux-2.4.0-test10-lia/include/linux/mm.h Wed Nov 15 22:22:54 2000 @@ -96,6 +96,8 @@ #define VM_DONTCOPY 0x00020000 /* Do not copy this vma on fork */ #define VM_DONTEXPAND 0x00040000 /* Cannot expand with mremap() */ #define VM_RESERVED 0x00080000 /* Don't unmap it from swap_out */ +#define VM_WRITECOMBINED 0x00100000 /* Write-combined */ +#define VM_NONCACHED 0x00200000 /* Noncached access */ #define VM_STACK_FLAGS 0x00000177 diff -urN linux-2.4.0-test10/include/linux/module.h linux-2.4.0-test10-lia/include/linux/module.h --- linux-2.4.0-test10/include/linux/module.h Tue Oct 31 11:18:05 2000 +++ linux-2.4.0-test10-lia/include/linux/module.h Wed Nov 15 22:22:34 2000 @@ -83,6 +83,12 @@ const struct module_persist *persist_start; const struct module_persist *persist_end; int (*can_unload)(void); + int runsize; /* In modutils, not currently used */ + const char *kallsyms_start; /* All symbols for kernel debugging */ + const char *kallsyms_end; + const char *archdata_start; /* arch specific data for module */ + const char *archdata_end; + const char *kernel_data; /* Reserved for kernel internal use */ }; struct module_info @@ -122,6 +128,10 @@ #define mod_member_present(mod,member) \ ((unsigned long)(&((struct module *)0L)->member + 1) \ <= (mod)->size_of_struct) + +/* Check if an address p with number of entries n is within the body of module m */ +#define mod_bound(p, n, m) ((unsigned long)(p) >= ((unsigned long)(m) + ((m)->size_of_struct)) && \ + (unsigned long)((p)+(n)) <= (unsigned long)(m) + (m)->size) /* Backwards compatibility definition. */ diff -urN linux-2.4.0-test10/init/main.c linux-2.4.0-test10-lia/init/main.c --- linux-2.4.0-test10/init/main.c Thu Oct 26 13:49:15 2000 +++ linux-2.4.0-test10-lia/init/main.c Wed Nov 1 23:27:18 2000 @@ -74,7 +74,6 @@ * with a gcc that is known to be too old from the very beginning. */ #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 91) -#error Sorry, your GCC is too old. It builds incorrect kernels. #endif extern char _stext, _etext; @@ -111,6 +110,9 @@ #if defined(CONFIG_QUOTA) extern void dquot_init_hash(void); #endif +#ifdef CONFIG_PERFMON +extern void perfmon_init(void); +#endif /* * Boot command-line arguments @@ -552,6 +554,9 @@ #endif mem_init(); kmem_cache_sizes_init(); +#ifdef CONFIG_PERFMON + perfmon_init(); +#endif #ifdef CONFIG_3215_CONSOLE con3215_activate(); #endif diff -urN linux-2.4.0-test10/kernel/Makefile linux-2.4.0-test10-lia/kernel/Makefile --- linux-2.4.0-test10/kernel/Makefile Fri Jul 28 14:12:10 2000 +++ linux-2.4.0-test10-lia/kernel/Makefile Mon Oct 30 22:17:12 2000 @@ -30,6 +30,13 @@ OX_OBJS += pm.o endif +ifneq ($(CONFIG_IA64),y) +# According to Alan Modra , the -fno-omit-frame-pointer is +# needed for x86 only. Why this used to be enabled for all architectures is beyond +# me. I suspect most platforms don't need this, but until we know that for sure +# I turn this off for IA-64 only. Andreas Schwab says it's also needed on m68k +# to get a correct value for the wait-channel (WCHAN in ps). --davidm CFLAGS_sched.o := $(PROFILING) -fno-omit-frame-pointer +endif include $(TOPDIR)/Rules.make diff -urN linux-2.4.0-test10/kernel/fork.c linux-2.4.0-test10-lia/kernel/fork.c --- linux-2.4.0-test10/kernel/fork.c Tue Sep 5 14:48:59 2000 +++ linux-2.4.0-test10-lia/kernel/fork.c Mon Oct 30 22:17:12 2000 @@ -539,7 +539,7 @@ * arch/ia64/kernel/process.c. */ int do_fork(unsigned long clone_flags, unsigned long stack_start, - struct pt_regs *regs, unsigned long stack_top) + struct pt_regs *regs, unsigned long stack_size) { int retval = -ENOMEM; struct task_struct *p; @@ -634,7 +634,7 @@ goto bad_fork_cleanup_fs; if (copy_mm(clone_flags, p)) goto bad_fork_cleanup_sighand; - retval = copy_thread(0, clone_flags, stack_start, stack_top, p, regs); + retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs); if (retval) goto bad_fork_cleanup_sighand; p->semundo = NULL; diff -urN linux-2.4.0-test10/kernel/module.c linux-2.4.0-test10-lia/kernel/module.c --- linux-2.4.0-test10/kernel/module.c Mon Oct 16 12:25:18 2000 +++ linux-2.4.0-test10-lia/kernel/module.c Wed Nov 1 14:58:18 2000 @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -186,7 +187,7 @@ of righteousness. */ mod_tmp = *mod; - error = copy_from_user(mod, mod_user, sizeof(struct module)); + error = copy_from_user(mod, mod_user, mod_user_size); if (error) { error = -EFAULT; goto err2; @@ -203,32 +204,29 @@ /* Make sure all interesting pointers are sane. */ -#define bound(p, n, m) ((unsigned long)(p) >= (unsigned long)(m+1) && \ - (unsigned long)((p)+(n)) <= (unsigned long)(m) + (m)->size) - - if (!bound(mod->name, namelen, mod)) { + if (!mod_bound(mod->name, namelen, mod)) { printk(KERN_ERR "init_module: mod->name out of bounds.\n"); goto err2; } - if (mod->nsyms && !bound(mod->syms, mod->nsyms, mod)) { + if (mod->nsyms && !mod_bound(mod->syms, mod->nsyms, mod)) { printk(KERN_ERR "init_module: mod->syms out of bounds.\n"); goto err2; } - if (mod->ndeps && !bound(mod->deps, mod->ndeps, mod)) { + if (mod->ndeps && !mod_bound(mod->deps, mod->ndeps, mod)) { printk(KERN_ERR "init_module: mod->deps out of bounds.\n"); goto err2; } - if (mod->init && !bound(mod->init, 0, mod)) { + if (mod->init && !mod_bound(mod->init, 0, mod)) { printk(KERN_ERR "init_module: mod->init out of bounds.\n"); goto err2; } - if (mod->cleanup && !bound(mod->cleanup, 0, mod)) { + if (mod->cleanup && !mod_bound(mod->cleanup, 0, mod)) { printk(KERN_ERR "init_module: mod->cleanup out of bounds.\n"); goto err2; } if (mod->ex_table_start > mod->ex_table_end || (mod->ex_table_start && - !((unsigned long)mod->ex_table_start >= (unsigned long)(mod+1) + !((unsigned long)mod->ex_table_start >= ((unsigned long)mod + mod->size_of_struct) && ((unsigned long)mod->ex_table_end < (unsigned long)mod + mod->size))) || (((unsigned long)mod->ex_table_start @@ -242,24 +240,51 @@ goto err2; } #ifdef __alpha__ - if (!bound(mod->gp - 0x8000, 0, mod)) { + if (!mod_bound(mod->gp - 0x8000, 0, mod)) { printk(KERN_ERR "init_module: mod->gp out of bounds.\n"); goto err2; } #endif if (mod_member_present(mod, can_unload) - && mod->can_unload && !bound(mod->can_unload, 0, mod)) { + && mod->can_unload && !mod_bound(mod->can_unload, 0, mod)) { printk(KERN_ERR "init_module: mod->can_unload out of bounds.\n"); goto err2; } - -#undef bound + if (mod_member_present(mod, kallsyms_end)) { + if (mod->kallsyms_end && + (!mod_bound(mod->kallsyms_start, 0, mod) || + !mod_bound(mod->kallsyms_end, 0, mod))) { + printk(KERN_ERR "init_module: mod->kallsyms out of bounds.\n"); + goto err2; + } + if (mod->kallsyms_start > mod->kallsyms_end) { + printk(KERN_ERR "init_module: mod->kallsyms invalid.\n"); + goto err2; + } + } + if (mod_member_present(mod, archdata_end)) { + if (mod->archdata_end && + (!mod_bound(mod->archdata_start, 0, mod) || + !mod_bound(mod->archdata_end, 0, mod))) { + printk(KERN_ERR "init_module: mod->archdata out of bounds.\n"); + goto err2; + } + if (mod->archdata_start > mod->archdata_end) { + printk(KERN_ERR "init_module: mod->archdata invalid.\n"); + goto err2; + } + } + if (mod_member_present(mod, kernel_data) && mod->kernel_data) { + printk(KERN_ERR "init_module: mod->kernel_data must be zero.\n"); + goto err2; + } /* Check that the user isn't doing something silly with the name. */ if ((n_namelen = get_mod_name(mod->name - (unsigned long)mod + (unsigned long)mod_user, &n_name)) < 0) { + printk(KERN_ERR "init_module: get_mod_name failure.\n"); error = n_namelen; goto err2; } @@ -276,6 +301,9 @@ error = -EFAULT; goto err3; } + + if (module_arch_init(mod)) + goto err3; /* On some machines it is necessary to do something here to make the I and D caches consistent. */ diff -urN linux-2.4.0-test10/kernel/printk.c linux-2.4.0-test10-lia/kernel/printk.c --- linux-2.4.0-test10/kernel/printk.c Mon Oct 16 12:58:51 2000 +++ linux-2.4.0-test10-lia/kernel/printk.c Wed Nov 15 19:49:26 2000 @@ -14,6 +14,8 @@ * manfreds@colorfullife.com */ +#include + #include #include #include @@ -296,6 +298,12 @@ break; } } +#ifdef CONFIG_IA64_EARLY_PRINTK + if (!console_drivers) { + static void early_printk (const char *str); + early_printk(msg); + } else +#endif if (msg_level < console_loglevel && console_drivers) { struct console *c = console_drivers; while(c) { @@ -412,6 +420,10 @@ } if ((console->flags & CON_PRINTBUFFER) == 0) goto done; +#ifdef CONFIG_IA64_EARLY_PRINTK + goto done; +#endif + /* * Print out buffered log messages. */ @@ -495,3 +507,47 @@ tty->driver.write(tty, 0, msg, strlen(msg)); return; } + +#ifdef CONFIG_IA64_EARLY_PRINTK + +#include + +#define VGABASE ((char *)0xc0000000000b8000) + +static int current_ypos = 50, current_xpos = 0; + +void +early_printk (const char *str) +{ + char c; + int i, k, j; + + while ((c = *str++) != '\0') { + if (current_ypos >= 50) { + /* scroll 1 line up */ + for (k = 1, j = 0; k < 50; k++, j++) { + for (i = 0; i < 80; i++) { + writew(readw(VGABASE + 2*(80*k + i)), + VGABASE + 2*(80*j + i)); + } + } + for (i = 0; i < 80; i++) { + writew(0x720, VGABASE + 2*(80*j + i)); + } + current_ypos = 49; + } + if (c == '\n') { + current_xpos = 0; + current_ypos++; + } else if (c != '\r') { + writew(((0x7 << 8) | (unsigned short) c), + VGABASE + 2*(80*current_ypos + current_xpos++)); + if (current_xpos >= 80) { + current_xpos = 0; + current_ypos++; + } + } + } +} + +#endif /* CONFIG_IA64_EARLY_PRINTK */ diff -urN linux-2.4.0-test10/kernel/timer.c linux-2.4.0-test10-lia/kernel/timer.c --- linux-2.4.0-test10/kernel/timer.c Mon Oct 16 12:58:51 2000 +++ linux-2.4.0-test10-lia/kernel/timer.c Wed Nov 1 14:58:18 2000 @@ -674,7 +674,7 @@ void do_timer(struct pt_regs *regs) { - (*(unsigned long *)&jiffies)++; + (*(volatile unsigned long *)&jiffies)++; #ifndef CONFIG_SMP /* SMP process accounting uses the local APIC timer */ diff -urN linux-2.4.0-test10/mm/memory.c linux-2.4.0-test10-lia/mm/memory.c --- linux-2.4.0-test10/mm/memory.c Mon Oct 30 14:32:57 2000 +++ linux-2.4.0-test10-lia/mm/memory.c Wed Nov 15 19:49:41 2000 @@ -227,7 +227,7 @@ /* If it's a COW mapping, write protect it both in the parent and the child */ if (cow) { - ptep_clear_wrprotect(src_pte); + ptep_set_wrprotect(src_pte); pte = *src_pte; } diff -urN linux-2.4.0-test10/mm/mmap.c linux-2.4.0-test10-lia/mm/mmap.c --- linux-2.4.0-test10/mm/mmap.c Fri Oct 13 12:10:30 2000 +++ linux-2.4.0-test10-lia/mm/mmap.c Wed Nov 1 14:58:18 2000 @@ -151,6 +151,12 @@ _trans(prot, PROT_WRITE, VM_WRITE) | _trans(prot, PROT_EXEC, VM_EXEC); flag_bits = +#ifdef MAP_WRITECOMBINED + _trans(flags, MAP_WRITECOMBINED, VM_WRITECOMBINED) | +#endif +#ifdef MAP_NONCACHED + _trans(flags, MAP_NONCACHED, VM_NONCACHED) | +#endif _trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN) | _trans(flags, MAP_DENYWRITE, VM_DENYWRITE) | _trans(flags, MAP_EXECUTABLE, VM_EXECUTABLE);