From bd9c53824bb23e22becbad932132493875c34546 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:17:35 -0500 Subject: [PATCH] pre-2.1.132-2.. ..is out there, and has everybodys favourite fix, ie the version number has been bumped this time. In addition, compared to pre-1, it has: - autofs fix (uninitialized inode number could lead to "interesting" problems) - some more NFS fixes (file truncation with pending write-backs this time) - disable_irq()/enable_irq() now nests properly, as Alan convinced me (quite rightly) that they have to nest in order to work sanely with shared interrupt and multiple CPU's and various other schenarios. - more merges from Alan, we're getting closer to being synched up. Most of the bulk of the thing is the irda stuff, that most people can ignore. Linus --- Documentation/networking/irda.txt | 13 + Makefile | 18 +- arch/arm/Makefile | 7 +- arch/arm/config.in | 32 +- arch/arm/kernel/Makefile | 54 +- arch/arm/kernel/calls.S | 2 +- arch/arm/kernel/dec21285.c | 100 +- arch/arm/kernel/dma-a5k.c | 2 +- arch/arm/kernel/dma-ebsa285.c | 123 +- arch/arm/kernel/dma-isa.c | 107 + arch/arm/kernel/dma-isa.h | 25 + arch/arm/kernel/dma-vnc.c | 51 + arch/arm/kernel/dma.c | 20 + arch/arm/kernel/ecard.c | 360 +- arch/arm/kernel/entry-armo.S | 52 +- arch/arm/kernel/entry-armv.S | 87 +- arch/arm/kernel/entry-common.S | 2 +- arch/arm/kernel/fiq.c | 9 +- arch/arm/kernel/head-armo.S | 3 - arch/arm/kernel/head-armv.S | 49 +- arch/arm/kernel/hw-ebsa285.c | 161 + arch/arm/kernel/init_task.c | 1 - arch/arm/kernel/irq.c | 4 + arch/arm/kernel/setup.c | 65 +- arch/arm/kernel/sys_arm.c | 3 +- arch/arm/kernel/traps.c | 4 +- arch/arm/lib/Makefile | 4 + arch/arm/lib/io-ebsa285.S | 71 +- arch/arm/mm/fault-armo.c | 2 +- arch/arm/mm/fault-armv.c | 2 +- arch/arm/mm/init.c | 9 + arch/arm/mm/mm-ebsa285.c | 62 +- arch/arm/mm/mm-rpc.c | 3 +- arch/arm/mm/mm-vnc.c | 19 +- arch/arm/mm/proc-sa110.S | 16 +- arch/i386/config.in | 14 +- arch/i386/kernel/irq.c | 21 +- arch/i386/kernel/irq.h | 3 +- arch/i386/kernel/sys_i386.c | 32 +- arch/m68k/Makefile | 1 + arch/m68k/amiga/pcmcia.c | 3 +- arch/m68k/atari/atakeyb.c | 2 +- arch/m68k/bvme6000/bvmeints.c | 9 +- arch/m68k/bvme6000/config.c | 9 +- arch/m68k/config.in | 19 +- arch/m68k/defconfig | 2 - arch/m68k/kernel/Makefile | 9 +- arch/m68k/kernel/m68k_defs.c | 2 +- arch/m68k/kernel/m68k_ksyms.c | 1 + arch/m68k/kernel/process.c | 1 - arch/m68k/mac/config.c | 34 +- arch/m68k/mac/debug.c | 150 +- arch/m68k/mac/macints.c | 38 +- arch/m68k/mac/mackeyb.c | 69 +- arch/m68k/mac/via6522.c | 23 +- arch/m68k/mm/fault.c | 47 +- arch/m68k/mvme16x/16xints.c | 9 +- drivers/acorn/block/ide-ics.c | 8 + drivers/acorn/char/Config.in | 11 + drivers/acorn/char/Makefile | 13 + drivers/acorn/char/keyb_ps2.c | 355 + drivers/acorn/char/mouse_rpc.c | 86 + drivers/acorn/net/etherh.c | 10 +- drivers/acorn/scsi/acornscsi.c | 142 +- drivers/acorn/scsi/cumana_2.c | 2 - drivers/acorn/scsi/eesox.c | 2 - drivers/acorn/scsi/powertec.c | 2 - drivers/char/serial.c | 40 +- drivers/char/tty_ioctl.c | 1 - drivers/net/3c505.c | 88 +- drivers/net/3c509.c | 52 +- drivers/net/3c515.c | 13 +- drivers/net/3c523.c | 19 +- drivers/net/Makefile | 20 +- drivers/net/ac3200.c | 1 - drivers/net/acenic.c | 236 +- drivers/net/acenic.h | 18 +- drivers/net/acenic_firmware.h | 7991 +++++++++++---------- drivers/net/apne.c | 30 +- drivers/net/ariadne2.c | 2 +- drivers/net/cosa.c | 1890 +++++ drivers/net/cosa.h | 102 + drivers/net/daynaport.c | 4 +- drivers/net/epic100.c | 1267 ++-- drivers/net/irda/Config.in | 16 + drivers/net/irda/Makefile | 72 + drivers/net/irda/actisys.c | 315 + drivers/net/irda/esi.c | 196 + drivers/net/irda/irport.c | 361 + drivers/net/irda/irtty.c | 748 ++ drivers/net/irda/pc87108.c | 1502 ++++ drivers/net/irda/tekram.c | 313 + drivers/net/irda/w83977af_ir.c | 1275 ++++ drivers/net/rrunner.c | 247 +- drivers/net/rrunner.h | 3 + drivers/net/wd.c | 1 - drivers/pci/oldproc.c | 6 + drivers/sound/Config.in | 9 +- drivers/sound/dmasound.c | 122 +- drivers/sound/es1370.c | 7 +- drivers/sound/es1371.c | 7 +- drivers/sound/opl3sa2.c | 585 +- drivers/sound/sonicvibes.c | 5 +- fs/autofs/inode.c | 11 +- fs/autofs/root.c | 13 +- fs/nfs/inode.c | 5 +- fs/nfs/write.c | 41 +- fs/nls/Config.in | 52 +- fs/umsdos/mangle.c | 20 +- include/asm-arm/arch-arc/dma.h | 15 +- include/asm-arm/arch-arc/hardware.h | 50 +- include/asm-arm/arch-arc/ide.h | 60 +- include/asm-arm/arch-arc/keyboard.h | 2 + include/asm-arm/arch-arc/processor.h | 4 - include/asm-arm/arch-ebsa110/hardware.h | 3 +- include/asm-arm/arch-ebsa110/processor.h | 4 - include/asm-arm/arch-ebsa285/hardware.h | 8 +- include/asm-arm/arch-ebsa285/ide.h | 39 +- include/asm-arm/arch-ebsa285/irq.h | 112 +- include/asm-arm/arch-ebsa285/irqs.h | 15 +- include/asm-arm/arch-ebsa285/keyboard.h | 41 +- include/asm-arm/arch-ebsa285/mmu.h | 7 +- include/asm-arm/arch-ebsa285/processor.h | 4 - include/asm-arm/arch-ebsa285/serial.h | 40 +- include/asm-arm/arch-ebsa285/time.h | 92 +- include/asm-arm/arch-nexuspci/hardware.h | 2 - include/asm-arm/arch-nexuspci/processor.h | 4 - include/asm-arm/arch-rpc/hardware.h | 60 +- include/asm-arm/arch-rpc/ide.h | 55 +- include/asm-arm/arch-rpc/keyboard.h | 1 + include/asm-arm/arch-rpc/processor.h | 4 - include/asm-arm/arch-vnc/hardware.h | 87 +- include/asm-arm/arch-vnc/ide.h | 43 +- include/asm-arm/arch-vnc/io.h | 4 +- include/asm-arm/arch-vnc/irq.h | 57 +- include/asm-arm/arch-vnc/irqs.h | 4 +- include/asm-arm/arch-vnc/keyboard.h | 44 +- include/asm-arm/arch-vnc/mmu.h | 4 +- include/asm-arm/arch-vnc/processor.h | 1 + include/asm-arm/arch-vnc/system.h | 29 +- include/asm-arm/arch-vnc/time.h | 146 +- include/asm-arm/byteorder.h | 5 +- include/asm-arm/dec21285.h | 127 + include/asm-arm/dma.h | 17 +- include/asm-arm/ecard.h | 102 +- include/asm-arm/elf.h | 9 +- include/asm-arm/hardware.h | 2 +- include/asm-arm/ide.h | 52 +- include/asm-arm/irq.h | 2 + include/asm-arm/keyboard.h | 2 - include/asm-arm/linux_logo.h | 5 +- include/asm-arm/md.h | 13 + include/asm-arm/posix_types.h | 8 +- include/asm-arm/proc-armo/elf.h | 19 + include/asm-arm/proc-armo/pgtable.h | 7 - include/asm-arm/proc-armo/processor.h | 7 +- include/asm-arm/proc-armo/system.h | 1 + include/asm-arm/proc-armv/elf.h | 21 + include/asm-arm/proc-armv/io.h | 24 +- include/asm-arm/proc-armv/processor.h | 7 +- include/asm-arm/proc-armv/uaccess.h | 11 +- include/asm-arm/signal.h | 19 + include/asm-arm/socket.h | 4 + include/asm-arm/spinlock.h | 9 +- include/asm-arm/system.h | 25 + include/asm-i386/mca_dma.h | 126 + include/asm-i386/smp.h | 2 +- include/asm-m68k/bvme6000hw.h | 22 +- include/asm-m68k/ipc.h | 3 + include/asm-m68k/pgtable.h | 2 +- include/asm-m68k/semaphore.h | 1 + include/asm-m68k/spinlock.h | 13 +- include/asm-m68k/string.h | 6 +- include/asm-m68k/uaccess.h | 5 +- include/linux/isicom.h | 3 +- include/linux/nfs_fs.h | 2 +- include/linux/pci.h | 6 + include/linux/proc_fs.h | 3 + include/net/br.h | 2 + include/net/irda/crc.h | 30 + include/net/irda/dongle.h | 48 + include/net/irda/ircomm_common.h | 233 + include/net/irda/irda.h | 153 + include/net/irda/irda_device.h | 152 + include/net/irda/irdacall.h | 2 + include/net/irda/iriap.h | 123 + include/net/irda/iriap_event.h | 84 + include/net/irda/irias_object.h | 107 + include/net/irda/irlan_cli.h | 65 + include/net/irda/irlan_common.h | 199 + include/net/irda/irlan_eth.h | 40 + include/net/irda/irlan_event.h | 86 + include/net/irda/irlan_srv.h | 62 + include/net/irda/irlap.h | 232 + include/net/irda/irlap_comp.h | 47 + include/net/irda/irlap_event.h | 119 + include/net/irda/irlap_frame.h | 155 + include/net/irda/irlmp.h | 239 + include/net/irda/irlmp_event.h | 113 + include/net/irda/irlmp_frame.h | 57 + include/net/irda/irmod.h | 263 + include/net/irda/irobex.h | 134 + include/net/irda/irport.h | 61 + include/net/irda/irqueue.h | 106 + include/net/irda/irttp.h | 136 + include/net/irda/irtty.h | 68 + include/net/irda/irvtd.h | 104 + include/net/irda/irvtd_driver.h | 122 + include/net/irda/pc87108.h | 194 + include/net/irda/qos.h | 104 + include/net/irda/smc_ircc.h | 123 + include/net/irda/timer.h | 79 + include/net/irda/w83977af.h | 54 + include/net/irda/w83977af_ir.h | 158 + include/net/irda/wrapper.h | 57 + net/Makefile | 12 +- net/appletalk/ddp.c | 4 +- net/bridge/br.c | 40 + net/bridge/br_tree.c | 43 + net/decnet/README | 3 +- net/irda/Config.in | 35 + net/irda/Makefile | 80 + net/irda/af_irda.c | 738 ++ net/irda/compressors/Config.in | 9 + net/irda/compressors/Makefile | 26 + net/irda/compressors/irda_deflate.c | 636 ++ net/irda/crc.c | 65 + net/irda/ircomm/Config.in | 3 + net/irda/ircomm/Makefile | 31 + net/irda/ircomm/attach.c | 364 + net/irda/ircomm/ircomm_common.c | 1290 ++++ net/irda/ircomm/irvtd.c | 154 + net/irda/ircomm/irvtd_driver.c | 1869 +++++ net/irda/irda_device.c | 578 ++ net/irda/iriap.c | 922 +++ net/irda/iriap_event.c | 529 ++ net/irda/irias_object.c | 500 ++ net/irda/irlan/Config.in | 7 + net/irda/irlan/Makefile | 52 + net/irda/irlan/irlan_cli.c | 678 ++ net/irda/irlan/irlan_cli_event.c | 494 ++ net/irda/irlan/irlan_common.c | 896 +++ net/irda/irlan/irlan_eth.c | 396 + net/irda/irlan/irlan_event.c | 48 + net/irda/irlan/irlan_srv.c | 915 +++ net/irda/irlan/irlan_srv_event.c | 268 + net/irda/irlap.c | 1184 +++ net/irda/irlap_comp.c | 353 + net/irda/irlap_event.c | 1831 +++++ net/irda/irlap_frame.c | 1420 ++++ net/irda/irlmp.c | 1341 ++++ net/irda/irlmp_event.c | 693 ++ net/irda/irlmp_frame.c | 373 + net/irda/irmod.c | 397 + net/irda/irobex/Config.in | 3 + net/irda/irobex/Makefile | 19 + net/irda/irobex/irobex.c | 1110 +++ net/irda/irproc.c | 386 + net/irda/irqueue.c | 770 ++ net/irda/irsysctl.c | 88 + net/irda/irttp.c | 1442 ++++ net/irda/qos.c | 448 ++ net/irda/timer.c | 216 + net/irda/wrapper.c | 318 + net/protocols.c | 8 + net/rose/rose_dev.c | 12 +- net/wanrouter/wanmain.c | 2 - scripts/checkhelp.pl | 30 + 268 files changed, 44091 insertions(+), 6259 deletions(-) create mode 100644 Documentation/networking/irda.txt create mode 100644 arch/arm/kernel/dma-isa.c create mode 100644 arch/arm/kernel/dma-isa.h create mode 100644 arch/arm/kernel/dma-vnc.c create mode 100644 arch/arm/kernel/hw-ebsa285.c create mode 100644 drivers/acorn/char/keyb_ps2.c create mode 100644 drivers/acorn/char/mouse_rpc.c create mode 100644 drivers/net/cosa.c create mode 100644 drivers/net/cosa.h create mode 100644 drivers/net/irda/Config.in create mode 100644 drivers/net/irda/Makefile create mode 100644 drivers/net/irda/actisys.c create mode 100644 drivers/net/irda/esi.c create mode 100644 drivers/net/irda/irport.c create mode 100644 drivers/net/irda/irtty.c create mode 100644 drivers/net/irda/pc87108.c create mode 100644 drivers/net/irda/tekram.c create mode 100644 drivers/net/irda/w83977af_ir.c create mode 100644 include/asm-arm/dec21285.h create mode 100644 include/asm-arm/md.h create mode 100644 include/asm-arm/proc-armo/elf.h create mode 100644 include/asm-arm/proc-armv/elf.h create mode 100644 include/asm-i386/mca_dma.h create mode 100644 include/net/irda/crc.h create mode 100644 include/net/irda/dongle.h create mode 100644 include/net/irda/ircomm_common.h create mode 100644 include/net/irda/irda.h create mode 100644 include/net/irda/irda_device.h create mode 100644 include/net/irda/irdacall.h create mode 100644 include/net/irda/iriap.h create mode 100644 include/net/irda/iriap_event.h create mode 100644 include/net/irda/irias_object.h create mode 100644 include/net/irda/irlan_cli.h create mode 100644 include/net/irda/irlan_common.h create mode 100644 include/net/irda/irlan_eth.h create mode 100644 include/net/irda/irlan_event.h create mode 100644 include/net/irda/irlan_srv.h create mode 100644 include/net/irda/irlap.h create mode 100644 include/net/irda/irlap_comp.h create mode 100644 include/net/irda/irlap_event.h create mode 100644 include/net/irda/irlap_frame.h create mode 100644 include/net/irda/irlmp.h create mode 100644 include/net/irda/irlmp_event.h create mode 100644 include/net/irda/irlmp_frame.h create mode 100644 include/net/irda/irmod.h create mode 100644 include/net/irda/irobex.h create mode 100644 include/net/irda/irport.h create mode 100644 include/net/irda/irqueue.h create mode 100644 include/net/irda/irttp.h create mode 100644 include/net/irda/irtty.h create mode 100644 include/net/irda/irvtd.h create mode 100644 include/net/irda/irvtd_driver.h create mode 100644 include/net/irda/pc87108.h create mode 100644 include/net/irda/qos.h create mode 100644 include/net/irda/smc_ircc.h create mode 100644 include/net/irda/timer.h create mode 100644 include/net/irda/w83977af.h create mode 100644 include/net/irda/w83977af_ir.h create mode 100644 include/net/irda/wrapper.h create mode 100644 net/irda/Config.in create mode 100644 net/irda/Makefile create mode 100644 net/irda/af_irda.c create mode 100644 net/irda/compressors/Config.in create mode 100644 net/irda/compressors/Makefile create mode 100644 net/irda/compressors/irda_deflate.c create mode 100644 net/irda/crc.c create mode 100644 net/irda/ircomm/Config.in create mode 100644 net/irda/ircomm/Makefile create mode 100644 net/irda/ircomm/attach.c create mode 100644 net/irda/ircomm/ircomm_common.c create mode 100644 net/irda/ircomm/irvtd.c create mode 100644 net/irda/ircomm/irvtd_driver.c create mode 100644 net/irda/irda_device.c create mode 100644 net/irda/iriap.c create mode 100644 net/irda/iriap_event.c create mode 100644 net/irda/irias_object.c create mode 100644 net/irda/irlan/Config.in create mode 100644 net/irda/irlan/Makefile create mode 100644 net/irda/irlan/irlan_cli.c create mode 100644 net/irda/irlan/irlan_cli_event.c create mode 100644 net/irda/irlan/irlan_common.c create mode 100644 net/irda/irlan/irlan_eth.c create mode 100644 net/irda/irlan/irlan_event.c create mode 100644 net/irda/irlan/irlan_srv.c create mode 100644 net/irda/irlan/irlan_srv_event.c create mode 100644 net/irda/irlap.c create mode 100644 net/irda/irlap_comp.c create mode 100644 net/irda/irlap_event.c create mode 100644 net/irda/irlap_frame.c create mode 100644 net/irda/irlmp.c create mode 100644 net/irda/irlmp_event.c create mode 100644 net/irda/irlmp_frame.c create mode 100644 net/irda/irmod.c create mode 100644 net/irda/irobex/Config.in create mode 100644 net/irda/irobex/Makefile create mode 100644 net/irda/irobex/irobex.c create mode 100644 net/irda/irproc.c create mode 100644 net/irda/irqueue.c create mode 100644 net/irda/irsysctl.c create mode 100644 net/irda/irttp.c create mode 100644 net/irda/qos.c create mode 100644 net/irda/timer.c create mode 100644 net/irda/wrapper.c create mode 100644 scripts/checkhelp.pl diff --git a/Documentation/networking/irda.txt b/Documentation/networking/irda.txt new file mode 100644 index 000000000000..1a49505e1ae4 --- /dev/null +++ b/Documentation/networking/irda.txt @@ -0,0 +1,13 @@ +To use the IrDA protocols within Linux you will need to get a suitable copy +of the IrDA Utilities. More detailed information about these and associated +programs can be found on http://www.cs.uit.no/~dagb/irda/. + +For more information about the IrDA protocol stack, see the IR-HOWTO +written by Werner Heuser + +There is an active mailing list for discussing Linux IrDA matters called +linux-irda. To subscribe to it, send a message to Majordomo@list.uit.no +with the words "subscribe linux-irda" in the body of the message, the +subject field is ignored. + +Dag Brattli diff --git a/Makefile b/Makefile index 78dea7f6319c..e3389755e8b5 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 131 +SUBLEVEL = 132 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) @@ -180,6 +180,18 @@ ifdef CONFIG_HAMRADIO DRIVERS := $(DRIVERS) drivers/net/hamradio/hamradio.a endif +ifeq ($(CONFIG_USB),y) +DRIVERS := $(DRIVERS) drivers/uusbd/usb.a +endif + +ifeq ($(CONFIG_I2O),y) +DRIVERS := $(DRIVERS) drivers/i2o/i2o.a +endif + +ifeq ($(CONFIG_IRDA),y) +DRIVERS := $(DRIVERS) drivers/net/irda/irda_drivers.a +endif + include arch/$(ARCH)/Makefile .S.s: @@ -195,11 +207,13 @@ boot: vmlinux vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o \ + --start-group \ $(CORE_FILES) \ $(FILESYSTEMS) \ $(NETWORKS) \ $(DRIVERS) \ $(LIBS) \ + --end-group \ -o vmlinux $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aU] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map @@ -307,6 +321,7 @@ modules_install: mkdir -p $$MODLIB/$$2; cp $$These $$MODLIB/$$2; \ echo Installing modules under $$MODLIB/$$2; \ }; \ + mkdir -p $$MODLIB; \ \ if [ -f BLOCK_MODULES ]; then inst_mod BLOCK_MODULES block; fi; \ if [ -f NET_MODULES ]; then inst_mod NET_MODULES net; fi; \ @@ -320,6 +335,7 @@ modules_install: if [ -f SOUND_MODULES ]; then inst_mod SOUND_MODULES sound; fi; \ if [ -f VIDEO_MODULES ]; then inst_mod VIDEO_MODULES video; fi; \ if [ -f FC4_MODULES ]; then inst_mod FC4_MODULES fc4; fi; \ + if [ -f IRDA_MODULES ]; then inst_mod IRDA_MODULES net; fi; \ \ ls *.o > $$MODLIB/.allmods; \ echo $$MODULES | tr ' ' '\n' | sort | comm -23 $$MODLIB/.allmods - > $$MODLIB/.misc; \ diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 5ef8ea75e434..967ee67661c2 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -120,6 +120,7 @@ COMPRESSED_HEAD = head-nexuspci.o endif ifeq ($(CONFIG_ARCH_VNC),y) +TEXTADDR = 0xC000C000 MACHINE = vnc ARCHDIR = vnc endif @@ -141,7 +142,7 @@ OBJCOPY = $(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S OBJDUMP = $(CROSS_COMPILE)objdump CPP = $(CC) -E ARCHCC := $(word 1,$(CC)) -GCCLIB := `$(ARCHCC) $(CFLAGS_PROC) --print-libgcc-file-name` +GCCLIB := `$(CC) $(CFLAGS_PROC) --print-libgcc-file-name` #GCCARCH := -B/usr/bin/arm-linuxelf- HOSTCFLAGS := $(CFLAGS:-fomit-frame-pointer=) ifeq ($(CONFIG_FRAME_POINTER),y) @@ -160,10 +161,10 @@ LIBS := arch/arm/lib/lib.a $(LIBS) $(GCCLIB) BLOCK_DRIVERS := drivers/block/block.a CDROM_DRIVERS := drivers/cdrom/cdrom.a ifeq ($(CONFIG_FB),y) -CHAR_DRIVERS := arch/arm/drivers/char1/char.a +CHAR_DRIVERS := arch/arm/drivers/char1/char1.a drivers/char/char.a arch/arm/drivers/char1/char1.a else ifeq ($(CONFIG_VGA_CONSOLE),y) -CHAR_DRIVERS := arch/arm/drivers/char1/char.a +CHAR_DRIVERS := arch/arm/drivers/char1/char1.a drivers/char/char.a arch/arm/drivers/char1/char1.a else CHAR_DRIVERS := arch/arm/drivers/char/char.a endif diff --git a/arch/arm/config.in b/arch/arm/config.in index 2b59a964c8e5..af7b3fc94eb8 100644 --- a/arch/arm/config.in +++ b/arch/arm/config.in @@ -38,15 +38,22 @@ if [ "$CONFIG_ARCH_TBOX" = "y" ]; then define_bool CONFIG_BUS_I2C y fi -# These machines have PCI/may have PCI +# These machines always have PCI if [ "$CONFIG_ARCH_NEXUSPCI" = "y" -o \ "$CONFIG_ARCH_VNC" = "y" ]; then define_bool CONFIG_PCI y +fi +if [ "$CONFIG_ARCH_EBSA285" = "y" ]; then + bool "PCI support" CONFIG_PCI +fi + +# These machines have ISA-DMA +if [ "$CONFIG_CATS" = "y" -o \ + "$CONFIG_ARCH_VNC" = "y" ]; then + define_bool CONFIG_ISA_DMA y else - if [ "$CONFIG_ARCH_EBSA285" = "y" ]; then - bool "PCI support" CONFIG_PCI - fi + define_bool CONFIG_ISA_DMA n fi # Figure out whether this system uses 26-bit or 32-bit CPUs. Nobody has @@ -122,6 +129,11 @@ if [ "$CONFIG_PARPORT" != "n" ]; then fi fi fi +if [ "$CONFIG_ARCH_EBSA285" = "y" -o \ + "$CONFIG_ARCH_EBSA110" = "y" -o \ + "$CONFIG_ARCH_VNC" = "y" ]; then + string 'Initial kernel command string' CONFIG_CMDLINE +fi endmenu source drivers/pnp/Config.in @@ -132,16 +144,20 @@ if [ "$CONFIG_ARCH_ACORN" = "y" ]; then source drivers/acorn/block/Config.in fi -source arch/arm/drivers/char/Config.in +if [ "$CONFIG_VGA_CONSOLE" = "n" -a "$CONFIG_FB" = "n" ]; then + source arch/arm/drivers/char/Config.in +else + source drivers/char/Config.in +fi +if [ "$CONFIG_ARCH_ACORN" = "y" ]; then + source drivers/acorn/char/Config.in +fi if [ "$CONFIG_VT" = "y" ]; then mainmenu_option next_comment comment 'Console drivers' if [ "$CONFIG_ARCH_ACORN" != "y" -a "$CONFIG_ARCH_EBSA110" != "y" ]; then bool 'VGA text console' CONFIG_VGA_CONSOLE - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool 'Video mode selection support' CONFIG_VIDEO_SELECT - fi fi bool 'Support Frame buffer devices' CONFIG_FB source drivers/video/Config.in diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 542ca995a0a8..23b2c12671ec 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -10,44 +10,54 @@ ENTRY_OBJ = entry-$(PROCESSOR).o O_TARGET := kernel.o O_OBJS := $(ENTRY_OBJ) ioport.o irq.o process.o ptrace.o setup.o \ - signal.o sys_arm.o time.o traps.o fiq.o + signal.o sys_arm.o time.o traps.o + +DMA_OBJS_arc = dma-arc.o +DMA_OBJS_a5k = dma-a5k.o +DMA_OBJS_rpc = dma-rpc.o +DMA_OBJS_ebsa110 = dma-dummy.o +DMA_OBJS_ebsa285 = dma-ebsa285.o +DMA_OBJS_nexuspci = +DMA_OBJS_vnc = dma-vnc.o + +O_OBJS_arc = ecard.o iic.o fiq.o oldlatches.o +O_OBJS_a5k = ecard.o iic.o fiq.o +O_OBJS_rpc = ecard.o iic.o fiq.o +O_OBJS_ebsa110 = leds-ebsa110.o +O_OBJS_ebsa285 = leds-ebsa285.o hw-ebsa285.o +O_OBJS_nexuspci = +O_OBJS_vnc = leds-ebsa285.o hw-vnc.o all: lib kernel.o $(HEAD_OBJ) init_task.o ifeq ($(CONFIG_MODULES),y) -OX_OBJS = armksyms.o + OX_OBJS = armksyms.o else -O_OBJS += armksyms.o + O_OBJS += armksyms.o endif -ifdef CONFIG_ARCH_ACORN - O_OBJS += ecard.o iic.o - ifdef CONFIG_ARCH_ARC - O_OBJS += oldlatches.o +ifeq ($(MACHINE),nexuspci) + ifdef CONFIG_PCI + O_OBJS += plx9080.o endif - O_OBJS += dma-$(MACHINE).o - OX_OBJS += dma.o -endif - -ifeq ($(MACHINE),ebsa110) - O_OBJS += dma-dummy.o leds-ebsa110.o -endif - -ifeq ($(MACHINE),ebsa285) - OX_OBJS += dma.o - O_OBJS += dma-ebsa285.o leds-ebsa285.o +else ifdef CONFIG_PCI O_OBJS += dec21285.o endif endif -ifeq ($(MACHINE),nexuspci) - O_OBJS += dma-dummy.o - ifdef CONFIG_PCI - O_OBJS += plx9080.o +ifneq ($(DMA_OBJS_$(MACHINE)),) + OX_OBJS += dma.o + O_OBJS += $(DMA_OBJS_$(MACHINE)) + ifeq ($(CONFIG_ISA_DMA),y) + O_OBJS += dma-isa.o endif +else + O_OBJS += dma-dummy.o endif +O_OBJS += $(O_OBJS_$(MACHINE)) + $(HEAD_OBJ): $(HEAD_OBJ:.o=.S) $(CC) -D__ASSEMBLY__ -DTEXTADDR=$(TEXTADDR) -traditional -c $(HEAD_OBJ:.o=.S) -o $@ diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 751f9616a144..46f71fa927f6 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S @@ -9,7 +9,7 @@ #define NR_syscalls 256 #else -/* 0 */ .long SYMBOL_NAME(sys_setup) +/* 0 */ .long SYMBOL_NAME(sys_ni_syscall) .long SYMBOL_NAME(sys_exit) .long SYMBOL_NAME(sys_fork_wrapper) .long SYMBOL_NAME(sys_read) diff --git a/arch/arm/kernel/dec21285.c b/arch/arm/kernel/dec21285.c index de4861b82a33..aa66ee04a534 100644 --- a/arch/arm/kernel/dec21285.c +++ b/arch/arm/kernel/dec21285.c @@ -3,14 +3,23 @@ * * Copyright (C) 1998 Russell King, Phil Blundell */ +#include #include #include +#include +#include #include +#include #include #define MAX_SLOTS 20 +extern void pcibios_fixup_ebsa285(struct pci_dev *dev); +extern void pcibios_init_ebsa285(void); +extern void pcibios_fixup_vnc(struct pci_dev *dev); +extern void pcibios_init_vnc(void); + int pcibios_present(void) { @@ -24,12 +33,11 @@ pcibios_base_address(unsigned char bus, unsigned char dev_fn) int slot = PCI_SLOT(dev_fn); if (slot < MAX_SLOTS) - return 0xf8c00000 + (slot << 11); + return 0xf8c00000 + (slot << 11) + (PCI_FUNC(dev_fn) << 8); else return 0; - } else { + } else return 0xf9000000 | (bus << 16) | (dev_fn << 8); - } } int @@ -119,56 +127,35 @@ pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, return PCIBIOS_SUCCESSFUL; } -static int irqmap_ebsa[] __initdata = { 9, 8, 18, 11 }; -static int irqmap_cats[] __initdata = { 18, 8, 9, 11 }; - -__initfunc(static int ebsa_irqval(struct pci_dev *dev)) +__initfunc(void pci_set_cmd(struct pci_dev *dev, unsigned short clear, unsigned short set)) { - unsigned char pin; - - pcibios_read_config_byte(dev->bus->number, - dev->devfn, - PCI_INTERRUPT_PIN, - &pin); - - return irqmap_ebsa[(PCI_SLOT(dev->devfn) + pin) & 3]; + unsigned short cmd; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd = (cmd & ~clear) | set; + pci_write_config_word(dev, PCI_COMMAND, cmd); } -__initfunc(static int cats_irqval(struct pci_dev *dev)) +__initfunc(void pci_set_base_addr(struct pci_dev *dev, int idx, unsigned int addr)) { - if (dev->irq >= 128) - return 32 + (dev->irq & 0x1f); - - switch (dev->irq) { - case 1: - case 2: - case 3: - case 4: - return irqmap_cats[dev->irq - 1]; - case 0: - return 0; - } + int reg = PCI_BASE_ADDRESS_0 + (idx << 2); - printk("PCI: device %02x:%02x has unknown irq line %x\n", - dev->bus->number, dev->devfn, dev->irq); - return 0; + pci_write_config_dword(dev, reg, addr); + pci_read_config_dword(dev, reg, &addr); + + dev->base_address[idx] = addr; } __initfunc(void pcibios_fixup(void)) { struct pci_dev *dev; - unsigned char cmd; for (dev = pci_devices; dev; dev = dev->next) { - /* sort out the irq mapping for this device */ - switch (machine_type) { - case MACH_TYPE_EBSA285: - dev->irq = ebsa_irqval(dev); - break; - case MACH_TYPE_CATS: - dev->irq = cats_irqval(dev); - break; - } + if (machine_is_ebsa285() || machine_is_cats()) + pcibios_fixup_ebsa285(dev); + if (machine_is_netwinder()) + pcibios_fixup_vnc(dev); + pcibios_write_config_byte(dev->bus->number, dev->devfn, PCI_INTERRUPT_LINE, dev->irq); @@ -176,34 +163,19 @@ __initfunc(void pcibios_fixup(void)) "PCI: %02x:%02x [%04x/%04x] on irq %d\n", dev->bus->number, dev->devfn, dev->vendor, dev->device, dev->irq); - - /* Turn on bus mastering - boot loader doesn't - * - perhaps it should! - dag - */ - pcibios_read_config_byte(dev->bus->number, dev->devfn, - PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_MASTER; - pcibios_write_config_byte(dev->bus->number, dev->devfn, - PCI_COMMAND, cmd); } + if (machine_is_netwinder()) + hw_init(); } __initfunc(void pcibios_init(void)) { - int rev; - - rev = *(unsigned char *)0xfe000008; - printk("DEC21285 PCI revision %02X\n", rev); - - /* - * Map our SDRAM at a known address in PCI space, just in case - * the firmware had other ideas. Using a nonzero base is slightly - * bizarre but apparently necessary to avoid problems with some - * video cards. - * - * We should really only do this if we are the configuration master. - */ - *((unsigned long *)0xfe000018) = 0x10000000; + if (machine_is_ebsa285() || machine_is_cats()) + pcibios_init_ebsa285(); + if (machine_is_netwinder()) + pcibios_init_vnc(); + + printk("DEC21285 PCI revision %02X\n", *(unsigned char *)0xfe000008); } __initfunc(void pcibios_fixup_bus(struct pci_bus *bus)) diff --git a/arch/arm/kernel/dma-a5k.c b/arch/arm/kernel/dma-a5k.c index 50ee4243566c..18bbf0c9c45a 100644 --- a/arch/arm/kernel/dma-a5k.c +++ b/arch/arm/kernel/dma-a5k.c @@ -16,7 +16,7 @@ #include "dma.h" -static struct fiq_handler fh = { "floppydma", NULL }; +static struct fiq_handler fh = { NULL, "floppydma", NULL, NULL }; int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_id) { diff --git a/arch/arm/kernel/dma-ebsa285.c b/arch/arm/kernel/dma-ebsa285.c index 74af95584f08..f1c42dac21a0 100644 --- a/arch/arm/kernel/dma-ebsa285.c +++ b/arch/arm/kernel/dma-ebsa285.c @@ -4,6 +4,9 @@ * Copyright (C) 1998 Phil Blundell * * DMA functions specific to EBSA-285/CATS architectures + * + * Changelog: + * 09/11/1998 RMK Split out ISA DMA functions to dma-isa.c */ #include @@ -19,44 +22,19 @@ #include #include "dma.h" - -/* 8237 DMA controllers */ -#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ -#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */ - -/* 8237 DMA controller registers */ -#define DMA1_CMD_REG 0x08 /* command register (w) */ -#define DMA1_STAT_REG 0x08 /* status register (r) */ -#define DMA1_REQ_REG 0x09 /* request register (w) */ -#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */ -#define DMA1_MODE_REG 0x0B /* mode register (w) */ -#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */ -#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */ -#define DMA1_RESET_REG 0x0D /* Master Clear (w) */ -#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */ -#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */ - -#define DMA2_CMD_REG 0xD0 /* command register (w) */ -#define DMA2_STAT_REG 0xD0 /* status register (r) */ -#define DMA2_REQ_REG 0xD2 /* request register (w) */ -#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */ -#define DMA2_MODE_REG 0xD6 /* mode register (w) */ -#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */ -#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */ -#define DMA2_RESET_REG 0xDA /* Master Clear (w) */ -#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */ -#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */ +#include "dma-isa.h" int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_name) { - /* 21285 internal channels */ - if (channel == 0 || channel == 1) + switch (channel) { + case 0: + case 1: /* 21285 internal channels */ return 0; - /* ISA channels */ -// if (machine_is_cats() && ((channel >= 2 && channel <= 5) || -// (channel >= 7 && channel <= 9))) -// return 0; + case 2 ... 9: + if (machine_is_cats()) + return isa_request_dma(channel - 2, dma, dev_name); + } return -EINVAL; } @@ -75,14 +53,9 @@ int arch_get_dma_residue(dmach_t channel, dma_t *dma) case 1: break; #ifdef CONFIG_CATS - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: + case 2 ... 9: + if (machine_is_cats()) + residue = isa_get_dma_residue(channel - 2); #endif } return residue; @@ -98,56 +71,9 @@ void arch_enable_dma(dmach_t channel, dma_t *dma) */ break; #ifdef CONFIG_CATS - case 2: - case 3: - case 4: - case 5: - case 7: - case 8: - case 9: - if (dma->invalid) { - static unsigned char dma_page[] = { 0x87, 0x83, 0x81, 0x82, - 0x00, 0x8b, 0x89, 0x8a }; - unsigned long int address = dma->buf.address, - length = dma->buf.length - 1; - outb(address >> 24, dma_page[channel - DMA_ISA_BASE] | 0x400); - outb(address >> 16, dma_page[channel - DMA_ISA_BASE]); - if (channel >= DMA_ISA_BASE + 5) { - outb(0, DMA2_CLEAR_FF_REG); - outb(address >> 1, - IO_DMA2_BASE + ((channel - DMA_ISA_BASE - 4) << 2)); - outb(address >> 9, - IO_DMA2_BASE + ((channel - DMA_ISA_BASE - 4) << 2)); - outb((length >> 1) & 0xfe, - IO_DMA2_BASE + 1 + ((channel - DMA_ISA_BASE - 4) << 2)); - outb(length >> 9, - IO_DMA2_BASE + 1 + ((channel - DMA_ISA_BASE - 4) << 2)); - outb(dma->dma_mode | (channel - DMA_ISA_BASE - 4), DMA2_MODE_REG); - } else { - outb(0, DMA1_CLEAR_FF_REG); - outb(address >> 0, IO_DMA1_BASE + ((channel - DMA_ISA_BASE) << 1)); - outb(address >> 8, IO_DMA1_BASE + ((channel - DMA_ISA_BASE) << 1)); - outb(length >> 0, - IO_DMA1_BASE + 1 + ((channel - DMA_ISA_BASE) << 1)); - outb(length >> 8, - IO_DMA1_BASE + 1 + ((channel - DMA_ISA_BASE) << 1)); - outb(dma->dma_mode | (channel - DMA_ISA_BASE), DMA1_MODE_REG); - } - switch (dma->dma_mode) { - case DMA_MODE_READ: - dma_cache_inv(__bus_to_virt(address), length + 1); - break; - case DMA_MODE_WRITE: - dma_cache_wback(__bus_to_virt(address), length + 1); - break; - } - dma->invalid = 0; - } - - if (channel >= DMA_ISA_BASE + 5) - outb(channel - DMA_ISA_BASE - 4, DMA2_MASK_REG); - else - outb(channel - DMA_ISA_BASE, DMA1_MASK_REG); + case 2 ... 9: + if (machine_is_cats()) + isa_enable_dma(channel - 2, dma); #endif } } @@ -162,18 +88,9 @@ void arch_disable_dma(dmach_t channel, dma_t *dma) */ break; #ifdef CONFIG_CATS - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - if (channel >= DMA_ISA_BASE + 5) - outb(channel - DMA_ISA_BASE, DMA2_MASK_REG); - else - outb((channel - DMA_ISA_BASE) | 4, DMA1_MASK_REG); + case 2 ... 9: + if (machine_is_cats()) + isa_disable_dma(channel - 2, dma); #endif } } diff --git a/arch/arm/kernel/dma-isa.c b/arch/arm/kernel/dma-isa.c new file mode 100644 index 000000000000..bdf7c614730e --- /dev/null +++ b/arch/arm/kernel/dma-isa.c @@ -0,0 +1,107 @@ +/* + * arch/arm/kernel/dma-isa.c: ISA DMA primitives + * + * Copyright (C) Russell King + * + * Taken from various sources, including: + * linux/include/asm/dma.h: Defines for using and allocating dma channels. + * Written by Hennus Bergman, 1992. + * High DMA channel support & info by Hannu Savolainen and John Boyd, Nov. 1992. + * arch/arm/kernel/dma-ebsa285.c + * Copyright (C) 1998 Phil Blundell + */ +#include + +#include +#include + +#include "dma.h" +#include "dma-isa.h" + +#define ISA_DMA_MASK 0 +#define ISA_DMA_MODE 1 +#define ISA_DMA_CLRFF 2 +#define ISA_DMA_PGHI 3 +#define ISA_DMA_PGLO 4 +#define ISA_DMA_ADDR 5 +#define ISA_DMA_COUNT 6 + +static unsigned int isa_dma_port[8][7] = { + /* MASK MODE CLRFF PAGE_HI PAGE_LO ADDR COUNT */ + { 0x0a, 0x0b, 0x0c, 0x487, 0x087, 0x00, 0x01 }, + { 0x0a, 0x0b, 0x0c, 0x483, 0x083, 0x02, 0x03 }, + { 0x0a, 0x0b, 0x0c, 0x481, 0x081, 0x04, 0x05 }, + { 0x0a, 0x0b, 0x0c, 0x482, 0x082, 0x06, 0x07 }, + { 0xd4, 0xd6, 0xd8, 0x000, 0x000, 0xc0, 0xc2 }, + { 0xd4, 0xd6, 0xd8, 0x48b, 0x08b, 0xc4, 0xc6 }, + { 0xd4, 0xd6, 0xd8, 0x489, 0x089, 0xc8, 0xca }, + { 0xd4, 0xd6, 0xd8, 0x48a, 0x08a, 0xcc, 0xce } +}; + +int isa_request_dma(int channel, dma_t *dma, const char *dev_name) +{ + if (channel != 4) + return 0; + + return -EINVAL; +} + +void isa_free_dma(int channel, dma_t *dma) +{ + /* nothing to do */ +} + +int isa_get_dma_residue(int channel, dma_t *dma) +{ + unsigned int io_port = isa_dma_port[channel][ISA_DMA_COUNT]; + int count; + + count = 1 + inb(io_port) + (inb(io_port) << 8); + + return channel < 4 ? count : (count << 1); +} + +void isa_enable_dma(int channel, dma_t *dma) +{ + unsigned long address, length; + + if (dma->invalid) { + address = dma->buf.address; + length = dma->buf.length - 1; + + outb(address >> 24, isa_dma_port[channel][ISA_DMA_PGHI]); + outb(address >> 16, isa_dma_port[channel][ISA_DMA_PGLO]); + + if (channel >= 4) { + address >>= 1; + length = (length >> 1) & 0xfe; /* why &0xfe? */ + } + + outb(0, isa_dma_port[channel][ISA_DMA_CLRFF]); + + outb(address, isa_dma_port[channel][ISA_DMA_ADDR]); + outb(address >> 8, isa_dma_port[channel][ISA_DMA_ADDR]); + + outb(length, isa_dma_port[channel][ISA_DMA_COUNT]); + outb(length >> 8, isa_dma_port[channel][ISA_DMA_COUNT]); + + outb(dma->dma_mode | (channel & 3), isa_dma_port[channel][ISA_DMA_MODE]); + + switch (dma->dma_mode) { + case DMA_MODE_READ: + dma_cache_inv(__bus_to_virt(dma->buf.address), dma->buf.length); + break; + + case DMA_MODE_WRITE: + dma_cache_wback(__bus_to_virt(dma->buf.address), dma->buf.length); + break; + } + dma->invalid = 0; + } + outb(channel & 3, isa_dma_port[channel][ISA_DMA_MASK]); +} + +void isa_disable_dma(int channel, dma_t *dma) +{ + outb(channel | 4, isa_dma_port[channel][ISA_DMA_MASK]); +} diff --git a/arch/arm/kernel/dma-isa.h b/arch/arm/kernel/dma-isa.h new file mode 100644 index 000000000000..3fcbdb3c73bd --- /dev/null +++ b/arch/arm/kernel/dma-isa.h @@ -0,0 +1,25 @@ +/* + * Request an ISA DMA channel + */ +int isa_request_dma(int channel, dma_t *dma, const char *dev_name); + +/* + * Free an ISA DMA channel + */ +void isa_free_dma(int channel, dma_t *dma); + +/* + * Get ISA DMA channel residue + */ +int isa_get_dma_residue(int channel, dma_t *dma); + +/* + * Enable (and set up) an ISA DMA channel + */ +void isa_enable_dma(int channel, dma_t *dma); + +/* + * Disable an ISA DMA channel + */ +void isa_disable_dma(int channel, dma_t *dma); + diff --git a/arch/arm/kernel/dma-vnc.c b/arch/arm/kernel/dma-vnc.c new file mode 100644 index 000000000000..132fa627a2c4 --- /dev/null +++ b/arch/arm/kernel/dma-vnc.c @@ -0,0 +1,51 @@ +/* + * arch/arm/kernel/dma-vnc.c + * + * Copyright (C) 1998 Russell King + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "dma.h" +#include "dma-isa.h" + +int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_name) +{ + if (channel < 8) + return isa_request_dma(channel, dma, dev_name); + return -EINVAL; +} + +void arch_free_dma(dmach_t channel, dma_t *dma) +{ + isa_free_dma(channel, dma); +} + +int arch_get_dma_residue(dmach_t channel, dma_t *dma) +{ + return isa_get_dma_residue(channel, dma); +} + +void arch_enable_dma(dmach_t channel, dma_t *dma) +{ + isa_enable_dma(channel, dma); +} + +void arch_disable_dma(dmach_t channel, dma_t *dma) +{ + isa_disable_dma(channel, dma); +} + +__initfunc(void arch_dma_init(dma_t *dma)) +{ + /* Nothing to do */ +} + diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c index 592cc979c3de..a164073ae41d 100644 --- a/arch/arm/kernel/dma.c +++ b/arch/arm/kernel/dma.c @@ -26,6 +26,26 @@ #include #include #include +#include + + +/* A note on resource allocation: + * + * All drivers needing DMA channels, should allocate and release them + * through the public routines `request_dma()' and `free_dma()'. + * + * In order to avoid problems, all processes should allocate resources in + * the same sequence and release them in the reverse order. + * + * So, when allocating DMAs and IRQs, first allocate the IRQ, then the DMA. + * When releasing them, first release the DMA, then release the IRQ. + * If you don't, you may cause allocation requests to fail unnecessarily. + * This doesn't really matter now, but it will once we get real semaphores + * in the kernel. + */ + + +spinlock_t dma_spin_lock = SPIN_LOCK_UNLOCKED; #include "dma.h" diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index f7d204787b8e..a2c702501a6c 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -3,7 +3,7 @@ * * Find all installed expansion cards, and handle interrupts from them. * - * Copyright 1995,1996,1997 Russell King + * Copyright 1995-1998 Russell King * * Created from information from Acorns RiscOS3 PRMs * @@ -14,6 +14,7 @@ * 29-Sep-1997 RMK Expansion card interrupt hardware not being re-enabled on reset from * Linux. (Caused cards not to respond under RiscOS without hard reset). * 15-Feb-1998 RMK Added DMA support + * 12-Sep-1998 RMK Added EASI support */ #define ECARD_C @@ -79,7 +80,7 @@ static signed char irqno_to_expcard[16]; static unsigned int ecard_numcards, ecard_numirqcards; static unsigned int have_expmask; -static void ecard_def_irq_enable (ecard_t *ec, int irqnr) +static void ecard_def_irq_enable(ecard_t *ec, int irqnr) { #ifdef HAS_EXPMASK if (irqnr < 4 && have_expmask) { @@ -89,7 +90,7 @@ static void ecard_def_irq_enable (ecard_t *ec, int irqnr) #endif } -static void ecard_def_irq_disable (ecard_t *ec, int irqnr) +static void ecard_def_irq_disable(ecard_t *ec, int irqnr) { #ifdef HAS_EXPMASK if (irqnr < 4 && have_expmask) { @@ -99,14 +100,14 @@ static void ecard_def_irq_disable (ecard_t *ec, int irqnr) #endif } -static void ecard_def_fiq_enable (ecard_t *ec, int fiqnr) +static void ecard_def_fiq_enable(ecard_t *ec, int fiqnr) { - panic ("ecard_def_fiq_enable called - impossible"); + panic("ecard_def_fiq_enable called - impossible"); } -static void ecard_def_fiq_disable (ecard_t *ec, int fiqnr) +static void ecard_def_fiq_disable(ecard_t *ec, int fiqnr) { - panic ("ecard_def_fiq_disable called - impossible"); + panic("ecard_def_fiq_disable called - impossible"); } static expansioncard_ops_t ecard_default_ops = { @@ -122,7 +123,7 @@ static expansioncard_ops_t ecard_default_ops = { * * They are not meant to be called directly, but via enable/disable_irq. */ -void ecard_enableirq (unsigned int irqnr) +void ecard_enableirq(unsigned int irqnr) { irqnr &= 7; if (irqnr < MAX_ECARDS && irqno_to_expcard[irqnr] != -1) { @@ -132,14 +133,14 @@ void ecard_enableirq (unsigned int irqnr) ec->ops = &ecard_default_ops; if (ec->claimed && ec->ops->irqenable) - ec->ops->irqenable (ec, irqnr); + ec->ops->irqenable(ec, irqnr); else - printk (KERN_ERR "ecard: rejecting request to " + printk(KERN_ERR "ecard: rejecting request to " "enable IRQs for %d\n", irqnr); } } -void ecard_disableirq (unsigned int irqnr) +void ecard_disableirq(unsigned int irqnr) { irqnr &= 7; if (irqnr < MAX_ECARDS && irqno_to_expcard[irqnr] != -1) { @@ -149,11 +150,11 @@ void ecard_disableirq (unsigned int irqnr) ec->ops = &ecard_default_ops; if (ec->ops && ec->ops->irqdisable) - ec->ops->irqdisable (ec, irqnr); + ec->ops->irqdisable(ec, irqnr); } } -void ecard_enablefiq (unsigned int fiqnr) +void ecard_enablefiq(unsigned int fiqnr) { fiqnr &= 7; if (fiqnr < MAX_ECARDS && irqno_to_expcard[fiqnr] != -1) { @@ -163,14 +164,14 @@ void ecard_enablefiq (unsigned int fiqnr) ec->ops = &ecard_default_ops; if (ec->claimed && ec->ops->fiqenable) - ec->ops->fiqenable (ec, fiqnr); + ec->ops->fiqenable(ec, fiqnr); else - printk (KERN_ERR "ecard: rejecting request to " + printk(KERN_ERR "ecard: rejecting request to " "enable FIQs for %d\n", fiqnr); } } -void ecard_disablefiq (unsigned int fiqnr) +void ecard_disablefiq(unsigned int fiqnr) { fiqnr &= 7; if (fiqnr < MAX_ECARDS && irqno_to_expcard[fiqnr] != -1) { @@ -180,7 +181,7 @@ void ecard_disablefiq (unsigned int fiqnr) ec->ops = &ecard_default_ops; if (ec->ops->fiqdisable) - ec->ops->fiqdisable (ec, fiqnr); + ec->ops->fiqdisable(ec, fiqnr); } } @@ -198,8 +199,27 @@ static void ecard_irq_noexpmask(int intr_no, void *dev_id, struct pt_regs *regs) } } cli(); - if (called == 0) - printk (KERN_WARNING "Wild interrupt from backplane?\n"); + if (called == 0) { + static int last, lockup; + + if (last == jiffies) { + lockup += 1; + if (lockup > 1000000) { + printk(KERN_ERR "\nInterrupt lockup detected - disabling expansion card IRQs\n"); + disable_irq(intr_no); + printk("Expansion card IRQ state:\n"); + for (i = 0; i < num_cards; i++) + printk(" %d: %sclaimed, irqaddr = %p, irqmask = %X, status=%X\n", expcard[i].irq - 32, + expcard[i].claimed ? "" : "not", expcard[i].irqaddr, expcard[i].irqmask, *expcard[i].irqaddr); + } + } else + lockup = 0; + + if (!last || last + 500 < jiffies) { + last = jiffies; + printk(KERN_ERR "\nUnrecognised interrupt from backplane\n"); + } + } } #ifdef HAS_EXPMASK @@ -214,7 +234,7 @@ static unsigned char first_set[] = 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00 }; -static void ecard_irq_expmask (int intr_no, void *dev_id, struct pt_regs *regs) +static void ecard_irq_expmask(int intr_no, void *dev_id, struct pt_regs *regs) { const unsigned int statusmask = 15; unsigned int status; @@ -239,22 +259,22 @@ again: */ oldexpmask = have_expmask; EXPMASK_ENABLE = (have_expmask &= priority_masks[irqno]); - sti (); - do_ecard_IRQ (ec->irq, regs); - cli (); + sti(); + do_ecard_IRQ(ec->irq, regs); + cli(); EXPMASK_ENABLE = have_expmask = oldexpmask; status = EXPMASK_STATUS & statusmask; if (status) goto again; } else { - printk (KERN_WARNING "card%d: interrupt from unclaimed card???\n", irqno); + printk(KERN_WARNING "card%d: interrupt from unclaimed card???\n", irqno); EXPMASK_ENABLE = (have_expmask &= ~(1 << irqno)); } } else - printk (KERN_WARNING "Wild interrupt from backplane (masks)\n"); + printk(KERN_WARNING "Wild interrupt from backplane (masks)\n"); } -static int ecard_checkirqhw (void) +static int ecard_checkirqhw(void) { int found; @@ -267,7 +287,7 @@ static int ecard_checkirqhw (void) } #endif -static void ecard_readbytes (void *addr, ecard_t *ec, int off, int len, int useld) +static void ecard_readbytes(void *addr, ecard_t *ec, int off, int len, int useld) { extern int ecard_loader_read(int off, volatile unsigned int pa, loader_t loader); unsigned char *a = (unsigned char *)addr; @@ -287,7 +307,7 @@ static void ecard_readbytes (void *addr, ecard_t *ec, int off, int len, int usel * If we require a low address or address 0, then reset, and start again... */ if (!off || lowaddress > laddr) { - outb (0, ec->podaddr); + outb(0, ec->podaddr); lowaddress = 0; } while (lowaddress <= laddr) { @@ -314,15 +334,136 @@ static void ecard_readbytes (void *addr, ecard_t *ec, int off, int len, int usel } } +static int ecard_prints(char *buffer, ecard_t *ec) +{ + char *start = buffer; + + buffer += sprintf(buffer, "\n %d: ", ec->slot_no); + + if (ec->cid.id == 0) { + struct in_chunk_dir incd; + + buffer += sprintf(buffer, "[%04X:%04X] ", + ec->cid.manufacturer, ec->cid.product); + + if (!ec->card_desc && ec->cid.is && ec->cid.cd && + ecard_readchunk(&incd, ec, 0xf5, 0)) + ec->card_desc = incd.d.string; + + if (!ec->card_desc) + ec->card_desc = "*unknown*"; + + buffer += sprintf(buffer, "%s", ec->card_desc); + } else + buffer += sprintf(buffer, "Simple card %d", ec->cid.id); + + return buffer - start; +} + +static inline unsigned short ecard_getu16(unsigned char *v) +{ + return v[0] | v[1] << 8; +} + +static inline signed long ecard_gets24(unsigned char *v) +{ + return v[0] | v[1] << 8 | v[2] << 16 | ((v[2] & 0x80) ? 0xff000000 : 0); +} + +/* + * Probe for an expansion card. + * + * If bit 1 of the first byte of the card is set, then the + * card does not exist. + */ +__initfunc(static int ecard_probe(int card, int freeslot, card_type_t type)) +{ + ecard_t *ec = expcard + freeslot; + struct ex_ecid cid; + char buffer[200]; + int i; + + irqno_to_expcard[card] = -1; + + ec->slot_no = card; + ec->irq = NO_IRQ; + ec->fiq = NO_IRQ; + ec->dma = NO_DMA; + ec->card_desc = NULL; + ec->ops = &ecard_default_ops; + + if ((ec->podaddr = ecard_address(ec, type, ECARD_SYNC)) == 0) + return 0; + + cid.r_zero = 1; + ecard_readbytes(&cid, ec, 0, 16, 0); + if (cid.r_zero) + return 0; + + irqno_to_expcard[card] = freeslot; + + ec->type = type; + ec->cid.id = cid.r_id; + ec->cid.cd = cid.r_cd; + ec->cid.is = cid.r_is; + ec->cid.w = cid.r_w; + ec->cid.manufacturer = ecard_getu16(cid.r_manu); + ec->cid.product = ecard_getu16(cid.r_prod); + ec->cid.country = cid.r_country; + ec->cid.irqmask = cid.r_irqmask; + ec->cid.irqoff = ecard_gets24(cid.r_irqoff); + ec->cid.fiqmask = cid.r_fiqmask; + ec->cid.fiqoff = ecard_gets24(cid.r_fiqoff); + ec->fiqaddr = + ec->irqaddr = (unsigned char *)BUS_ADDR(ec->podaddr); + + if (ec->cid.cd && ec->cid.is) { + ec->irqmask = ec->cid.irqmask; + ec->irqaddr += ec->cid.irqoff; + ec->fiqmask = ec->cid.fiqmask; + ec->fiqaddr += ec->cid.fiqoff; + } else { + ec->irqmask = 1; + ec->fiqmask = 4; + } + + for (i = 0; i < sizeof(blacklist) / sizeof(*blacklist); i++) + if (blacklist[i].manufacturer == ec->cid.manufacturer && + blacklist[i].product == ec->cid.product) { + ec->loader = blacklist[i].loader; + ec->card_desc = blacklist[i].type; + break; + } + + ecard_prints(buffer, ec); + printk("%s", buffer); + + ec->irq = 32 + card; +#ifdef IO_EC_MEMC8_BASE + if (card == 8) + ec->irq = 11; +#endif +#ifdef CONFIG_ARCH_RPC + /* On RiscPC, only first two slots have DMA capability */ + if (card < 2) + ec->dma = 2 + card; +#endif +#if 0 /* We don't support FIQs on expansion cards at the moment */ + ec->fiq = 96 + card; +#endif + + return 1; +} + /* * This is called to reset the loaders for each expansion card on reboot. * * This is required to make sure that the card is in the correct state * that RiscOS expects it to be. */ -void ecard_reset (int card) +void ecard_reset(int card) { - extern int ecard_loader_reset (volatile unsigned int pa, loader_t loader); + extern int ecard_loader_reset(volatile unsigned int pa, loader_t loader); if (card >= ecard_numcards) return; @@ -330,11 +471,11 @@ void ecard_reset (int card) if (card < 0) { for (card = 0; card < ecard_numcards; card++) if (expcard[card].loader) - ecard_loader_reset (BUS_ADDR(expcard[card].podaddr), + ecard_loader_reset(BUS_ADDR(expcard[card].podaddr), expcard[card].loader); } else if (expcard[card].loader) - ecard_loader_reset (BUS_ADDR(expcard[card].podaddr), + ecard_loader_reset(BUS_ADDR(expcard[card].podaddr), expcard[card].loader); #ifdef HAS_EXPMASK @@ -347,18 +488,19 @@ void ecard_reset (int card) static unsigned int ecard_startcard; -void ecard_startfind (void) +void ecard_startfind(void) { ecard_startcard = 0; } -ecard_t *ecard_find (int cld, const card_ids *cids) +ecard_t *ecard_find(int cid, const card_ids *cids) { int card; + if (!cids) { for (card = ecard_startcard; card < ecard_numcards; card++) if (!expcard[card].claimed && - ((expcard[card].cld.ecld ^ cld) & 0x78) == 0) + (expcard[card].cid.id ^ cid) == 0) break; } else { for (card = ecard_startcard; card < ecard_numcards; card++) { @@ -368,8 +510,8 @@ ecard_t *ecard_find (int cld, const card_ids *cids) if (expcard[card].claimed) continue; - manufacturer = expcard[card].cld.manufacturer; - product = expcard[card].cld.product; + manufacturer = expcard[card].cid.manufacturer; + product = expcard[card].cid.product; for (i = 0; cids[i].manufacturer != 65535; i++) if (manufacturer == cids[i].manufacturer && @@ -380,16 +522,21 @@ ecard_t *ecard_find (int cld, const card_ids *cids) break; } } + ecard_startcard = card + 1; + return card < ecard_numcards ? &expcard[card] : NULL; } -int ecard_readchunk (struct in_chunk_dir *cd, ecard_t *ec, int id, int num) +int ecard_readchunk(struct in_chunk_dir *cd, ecard_t *ec, int id, int num) { struct ex_chunk_dir excd; int index = 16; int useld = 0; + if (!ec->cid.is || !ec->cid.cd) + return 0; + while(1) { ecard_readbytes(&excd, ec, index, 8, useld); index += 8; @@ -427,124 +574,49 @@ int ecard_readchunk (struct in_chunk_dir *cd, ecard_t *ec, int id, int num) } } cd->start_offset = c_start(&excd); - memcpy (cd->d.string, excd.d.string, 256); + memcpy(cd->d.string, excd.d.string, 256); return 1; } -unsigned int ecard_address (ecard_t *ec, card_type_t type, card_speed_t speed) +unsigned int ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed) { switch (ec->slot_no) { case 0 ... 3: switch (type) { case ECARD_MEMC: - return MEMCECIO_BASE + (ec->slot_no << 12); + return IO_EC_MEMC_BASE + (ec->slot_no << 12); case ECARD_IOC: - return IOCECIO_BASE + (speed << 17) + (ec->slot_no << 12); + return IO_EC_IOC_BASE + (speed << 17) + (ec->slot_no << 12); - default: - return 0; +#ifdef IO_EC_EASI_BASE + case ECARD_EASI: + return IO_EC_EASI_BASE + (ec->slot_no << 22); +#endif } + break; -#ifdef IOCEC4IO_BASE case 4 ... 7: - if (type != ECARD_IOC) - return 0; - - return IOCEC4IO_BASE + (speed << 17) + ((ec->slot_no - 4) << 12); + switch (type) { +#ifdef IO_EC_IOC4_BASE + case ECARD_IOC: + return IO_EC_IOC4_BASE + (speed << 17) + ((ec->slot_no - 4) << 12); #endif -#ifdef MEMCEC8IO_BASE - case 8: - return MEMCEC8IO_BASE; +#ifdef IO_EC_EASI_BASE + case ECARD_EASI: + return IO_EC_EASI_BASE + (ec->slot_no << 22); #endif - } - return 0; -} - -/* - * Probe for an expansion card. - * - * If bit 1 of the first byte of the card is set, - * then the card does not exist. - */ -__initfunc(static int ecard_probe (int card, int freeslot)) -{ - ecard_t *ec = expcard + freeslot; - struct ex_ecld excld; - const char *card_desc = NULL; - int i; - - irqno_to_expcard[card] = -1; - - ec->slot_no = card; - if ((ec->podaddr = ecard_address (ec, ECARD_IOC, ECARD_SYNC)) == 0) - return 0; - - excld.r_ecld = 2; - ecard_readbytes (&excld, ec, 0, 16, 0); - if (excld.r_ecld & 2) - return 0; - - irqno_to_expcard[card] = freeslot; - - ec->irq = NO_IRQ; - ec->fiq = NO_IRQ; - ec->dma = NO_DMA; - ec->cld.ecld = e_ecld(&excld); - ec->cld.manufacturer = e_manu(&excld); - ec->cld.product = e_prod(&excld); - ec->cld.country = e_country(&excld); - ec->cld.fiqmask = e_fiqmask(&excld); - ec->cld.irqmask = e_irqmask(&excld); - ec->cld.fiqaddr = e_fiqaddr(&excld); - ec->cld.irqaddr = e_irqaddr(&excld); - ec->fiqaddr = - ec->irqaddr = (unsigned char *)BUS_ADDR(ec->podaddr); - ec->fiqmask = 4; - ec->irqmask = 1; - ec->ops = &ecard_default_ops; - - for (i = 0; i < sizeof (blacklist) / sizeof (*blacklist); i++) - if (blacklist[i].manufacturer == ec->cld.manufacturer && - blacklist[i].product == ec->cld.product) { - ec->loader = blacklist[i].loader; - card_desc = blacklist[i].type; + default: break; } + break; - ec->irq = 32 + card; -#if 0 - /* We don't support FIQs on expansion cards at the moment */ - ec->fiq = 96 + card; -#endif -#ifdef CONFIG_ARCH_RPC - if (card != 8) { - /* On RiscPC, only first two slots have DMA capability - */ - if (card < 2) - ec->dma = 2 + card; - } else - ec->irq = 11; +#ifdef IO_EC_MEMC8_BASE + case 8: + return IO_EC_MEMC8_BASE; #endif - - if ((ec->cld.ecld & 0x78) == 0) { - struct in_chunk_dir incd; - printk ("\n %d: [%04X:%04X] ", card, ec->cld.manufacturer, ec->cld.product); - if (e_is (&excld)) { - ec->fiqmask = e_fiqmask (&excld); - ec->irqmask = e_irqmask (&excld); - ec->fiqaddr += e_fiqaddr (&excld); - ec->irqaddr += e_irqaddr (&excld); - } - if (!card_desc && e_cd (&excld) && ecard_readchunk (&incd, ec, 0xf5, 0)) - card_desc = incd.d.string; - if (card_desc) - printk ("%s", card_desc); - else - printk ("*Unknown*"); - } else - printk("\n %d: Simple card %d\n", card, (ec->cld.ecld >> 3) & 15); - return 1; + } + return 0; } static struct irqaction irqexpansioncard = { @@ -565,11 +637,11 @@ __initfunc(void ecard_init(void)) { int i, nc = 0; - memset (expcard, 0, sizeof (expcard)); + memset(expcard, 0, sizeof(expcard)); #ifdef HAS_EXPMASK if (ecard_checkirqhw()) { - printk (KERN_DEBUG "Expansion card interrupt management hardware found\n"); + printk(KERN_DEBUG "Expansion card interrupt management hardware found\n"); irqexpansioncard.handler = ecard_irq_expmask; irqexpansioncard.flags |= SA_IRQNOMASK; have_expmask = -1; @@ -581,8 +653,8 @@ __initfunc(void ecard_init(void)) /* * First of all, probe all cards on the expansion card interrupt line */ - for (i = 0; i < 4; i++) - if (ecard_probe (i, nc)) + for (i = 0; i < 8; i++) + if (ecard_probe(i, nc, ECARD_IOC) || ecard_probe(i, nc, ECARD_EASI)) nc += 1; else have_expmask &= ~(1<used_math + mov r8, #1 + strb r8, [r10, #TSK_USED_MATH] @ set current->used_math add r10, r10, #TSS_FPESAVE @ r10 = workspace ldr r4, .LC2 ldr pc, [r4] @ Call FP module USR entry point @@ -742,6 +750,43 @@ __und_invalid: sub sp, sp, #S_FRAME_SIZE and r2, r6, #31 @ int mode b SYMBOL_NAME(bad_mode) @ Does not ever return... +/* We get here if an undefined instruction happens and the floating + * point emulator is not present. If the offending instruction was + * a WFS, we just perform a normal return as if we had emulated the + * operation. This is a hack to allow some basic userland binaries + * to run so that the emulator module proper can be loaded. --philb + */ +fpe_not_present: + adr r10, wfs_mask_data + ldmia r10, {r4, r5, r6, r7, r8} + ldr r10, [sp, #S_PC] @ Load PC + sub r10, r10, #4 + mask_pc r10, r10 + ldrt r10, [r10] @ get instruction + and r5, r10, r5 + teq r5, r4 @ Is it WFS? + moveq pc, r9 + and r5, r10, r8 + teq r5, r6 @ Is it LDF/STF on sp or fp? + teqne r5, r7 + movne pc, lr + tst r10, #0x00200000 @ Does it have WB + moveq pc, r9 + and r4, r10, #255 @ get offset + and r6, r10, #0x000f0000 + tst r10, #0x00800000 @ +/- + rsbeq r4, r4, #0 + ldr r5, [sp, r6, lsr #14] @ Load reg + add r5, r5, r4, lsl #2 + str r5, [sp, r6, lsr #14] @ Save reg + mov pc, r9 + +wfs_mask_data: .word 0x0e200110 @ WFS + .word 0x0fff0fff + .word 0x0d0d0100 @ LDF [sp]/STF [sp] + .word 0x0d0b0100 @ LDF [fp]/STF [fp] + .word 0x0f0f0f00 + #include "entry-common.S" .data diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 6e0e9e38ce5c..c77c0ea5142c 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -288,4 +288,4 @@ ENTRY(trap_init) .data ENTRY(fp_enter) - .word fpundefinstr + .word fpe_not_present diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index c32fef3c88f7..a5da15c7fc67 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c @@ -106,14 +106,7 @@ void set_fiq_handler(void *start, unsigned int length) memcpy((void *)FIQ_VECTOR, start, length); protect_page_0(); -#if 0 - /* This doesn'w work correctly. Ok, it's a misuse - * of the DMA flushing code, but it ought to work. - * More investigation required. Maybe it really - * needs the cache flushed. - */ - dma_cache_wback(FIQ_VECTOR, length); -#else +#ifdef CONFIG_CPU_32 processor.u.armv3v4._flush_cache_area(FIQ_VECTOR, FIQ_VECTOR + length, 1); #endif } diff --git a/arch/arm/kernel/head-armo.S b/arch/arm/kernel/head-armo.S index 1dc4fde13540..d6b2b79e633c 100644 --- a/arch/arm/kernel/head-armo.S +++ b/arch/arm/kernel/head-armo.S @@ -58,6 +58,3 @@ Loldparams: mov r4, #0x02000000 cmp r4, r3 blt 1b movs pc, lr - - .align 13 -ENTRY(this_must_match_init_task) diff --git a/arch/arm/kernel/head-armv.S b/arch/arm/kernel/head-armv.S index 88e71adab180..cd4be86cb2fb 100644 --- a/arch/arm/kernel/head-armv.S +++ b/arch/arm/kernel/head-armv.S @@ -8,9 +8,23 @@ #include #include +#ifndef CONFIG_ARCH_VNC #if (TEXTADDR & 0xffff) != 0x8000 #error TEXTADDR must start at 0xXXXX8000 #endif +#else + .text + mov r0, r0 + mov r0, r0 + mov r0, r0 + mov r0, r0 + mov r0, r0 + mov r0, r0 + mov r0, r0 + mov r0, r0 + mov r0, #0 + mov r1, #5 +#endif #define DEBUG @@ -97,6 +111,15 @@ __entry: teq r0, #0 @ check for illegal entry... add r3, r3, #1 << 20 teq r0, r2 bne 1b +#ifdef CONFIG_ARCH_VNC + add r0, r4, #0x3f00 + add r0, r0, #0x00f8 + mov r3, #0x7c000000 + orr r3, r3, r8 + str r3, [r0], #4 + add r3, r3, #1 << 20 + str r3, [r0], #4 +#endif #endif #ifdef CONFIG_ARCH_RPC /* Map in screen at 0x02000000 & SCREEN2_BASE @@ -339,7 +362,7 @@ __entry: teq r0, #0 @ check for illegal entry... beq 1001b .endm -#elif defined(CONFIG_ARCH_EBSA285) || defined(CONFIG_ARCH_VNC) +#elif defined(CONFIG_ARCH_EBSA285) .macro addruart,rx mov \rx, #0xfe000000 .endm @@ -374,6 +397,30 @@ __entry: teq r0, #0 @ check for illegal entry... .macro waituart,rd,rx .endm + +#elif defined(CONFIG_ARCH_VNC) + .macro addruart,rx + mov \rx, #0xff000000 + orr \rx, \rx, #0x00e00000 + orr \rx, \rx, #0x000003f8 + .endm + + .macro senduart,rd,rx + strb \rd, [\rx] + .endm + + .macro busyuart,rd,rx +1002: ldrb \rd, [\rx, #0x5] + and \rd, \rd, #0x60 + teq \rd, #0x60 + bne 1002b + .endm + + .macro waituart,rd,rx +1001: ldrb \rd, [\rx, #0x6] + tst \rd, #0x10 + beq 1001b + .endm #else #error Unknown architecture #endif diff --git a/arch/arm/kernel/hw-ebsa285.c b/arch/arm/kernel/hw-ebsa285.c new file mode 100644 index 000000000000..d88ca6ce99a3 --- /dev/null +++ b/arch/arm/kernel/hw-ebsa285.c @@ -0,0 +1,161 @@ +/* + * arch/arm/kernel/hw-ebsa286.c + * + * EBSA285 hardware specific functions + * + * Copyright (C) 1998 Russell King, Phil Blundel + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +extern int setup_arm_irq(int, struct irqaction *); + +extern void pci_set_cmd(struct pci_dev *dev, unsigned short clear, unsigned short set); +extern void pci_set_base_addr(struct pci_dev *dev, int idx, unsigned int addr); +extern void pci_set_irq_line(struct pci_dev *dev, unsigned int irq); + +static int irqmap_ebsa[] __initdata = { 9, 8, 18, 11 }; +static int irqmap_cats[] __initdata = { 18, 8, 9, 11 }; + +__initfunc(static int ebsa_irqval(struct pci_dev *dev)) +{ + unsigned char pin; + + pcibios_read_config_byte(dev->bus->number, + dev->devfn, + PCI_INTERRUPT_PIN, + &pin); + + return irqmap_ebsa[(PCI_SLOT(dev->devfn) + pin) & 3]; +} + +__initfunc(static int cats_irqval(struct pci_dev *dev)) +{ + if (dev->irq >= 128) + return 32 + (dev->irq & 0x1f); + + switch (dev->irq) { + case 1: + case 2: + case 3: + case 4: + return irqmap_cats[dev->irq - 1]; + case 0: + return 0; + } + + printk("PCI: device %02x:%02x has unknown irq line %x\n", + dev->bus->number, dev->devfn, dev->irq); + return 0; +} + +__initfunc(void pcibios_fixup_ebsa285(struct pci_dev *dev)) +{ + char cmd; + + /* sort out the irq mapping for this device */ + switch (machine_type) { + case MACH_TYPE_EBSA285: + dev->irq = ebsa_irqval(dev); + break; + case MACH_TYPE_CATS: + dev->irq = cats_irqval(dev); + break; + } + + /* Turn on bus mastering - boot loader doesn't + * - perhaps it should! - dag + */ + pci_read_config_byte(dev, PCI_COMMAND, &cmd); + pci_write_config_byte(dev, PCI_COMMAND, cmd | PCI_COMMAND_MASTER); +} + +static void irq_pci_err(int irq, void *dev_id, struct pt_regs *regs) +{ + const char *err = "unknown"; + unsigned long cmd = *(unsigned long *)0xfe000004 & 0xffff; + unsigned long ctrl = *(unsigned long *)0xfe00013c & 0xffffde07; + static unsigned long next_warn[7]; + int idx = 6; + + switch(irq) { + case IRQ_PCIPARITY: + *(unsigned long *)0xfe000004 = cmd | 1 << 31; + idx = 0; + err = "parity"; + break; + + case IRQ_PCITARGETABORT: + *(unsigned long *)0xfe000004 = cmd | 1 << 28; + idx = 1; + err = "target abort"; + break; + + case IRQ_PCIMASTERABORT: + *(unsigned long *)0xfe000004 = cmd | 1 << 29; + idx = 2; + err = "master abort"; + break; + + case IRQ_PCIDATAPARITY: + *(unsigned long *)0xfe000004 = cmd | 1 << 24; + idx = 3; + err = "data parity"; + break; + + case IRQ_DISCARDTIMER: + *(unsigned long *)0xfe00013c = ctrl | 1 << 8; + idx = 4; + err = "discard timer"; + break; + + case IRQ_SERR: + *(unsigned long *)0xfe00013c = ctrl | 1 << 3; + idx = 5; + err = "system"; + break; + } + if (next_warn[idx] <= jiffies) { + next_warn[idx] = jiffies + 3 * HZ / 100; + printk(KERN_ERR "PCI %s error detected\n", err); + } +} + +static struct irqaction irq_pci_error = { + irq_pci_err, SA_INTERRUPT, 0, "PCI error", NULL, NULL +}; + +__initfunc(void pcibios_init_ebsa285(void)) +{ + setup_arm_irq(IRQ_PCIPARITY, &irq_pci_error); + setup_arm_irq(IRQ_PCITARGETABORT, &irq_pci_error); + setup_arm_irq(IRQ_PCIMASTERABORT, &irq_pci_error); + setup_arm_irq(IRQ_PCIDATAPARITY, &irq_pci_error); + setup_arm_irq(IRQ_DISCARDTIMER, &irq_pci_error); + setup_arm_irq(IRQ_SERR, &irq_pci_error); + + /* + * Map our SDRAM at a known address in PCI space, just in case + * the firmware had other ideas. Using a nonzero base is slightly + * bizarre but apparently necessary to avoid problems with some + * video cards. + * + * We should really only do this if the central function is enabled. + */ + *(unsigned long *)0xfe000010 = 0; + *(unsigned long *)0xfe000018 = 0xe0000000; + *(unsigned long *)0xfe0000f8 = 0; + *(unsigned long *)0xfe0000fc = 0; + *(unsigned long *)0xfe000100 = 0x01fc0000; + *(unsigned long *)0xfe000104 = 0; + *(unsigned long *)0xfe000108 = 0x80000000; + *(unsigned long *)0xfe000004 = 0x17; +} diff --git a/arch/arm/kernel/init_task.c b/arch/arm/kernel/init_task.c index 689c435897c0..99577f1b7d73 100644 --- a/arch/arm/kernel/init_task.c +++ b/arch/arm/kernel/init_task.c @@ -6,7 +6,6 @@ static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; -static struct file * init_fd_array[NR_OPEN] = { NULL, }; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; struct mm_struct init_mm = INIT_MM; diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index b4950ace2c3e..4c2063ae5e62 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -119,7 +119,9 @@ int get_irq_list(char *buf) *p++ = '\n'; } +#ifdef CONFIG_ACORN p += get_fiq_list(p); +#endif return p - buf; } @@ -424,6 +426,8 @@ __initfunc(void init_IRQ(void)) } irq_init_irq(); +#ifdef CONFIG_ARCH_ACORN init_FIQ(); +#endif init_dma(); } diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 767faff9e6d8..cddc3fab3f71 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -57,13 +57,15 @@ #endif #ifndef CONFIG_CMDLINE -#define CONFIG_CMDLINE "root=nfs rw console=ttyS1,38400n8" +#define CONFIG_CMDLINE "root=/dev/nfs rw" #endif #define MEM_SIZE (16*1024*1024) #define COMMAND_LINE_SIZE 256 struct drive_info_struct { char dummy[32]; } drive_info; struct screen_info screen_info = { + orig_video_lines: 30, + orig_video_cols: 80, orig_video_mode: 0, orig_video_ega_bx: 0, orig_video_isVGA: 1, @@ -210,6 +212,8 @@ setup_params(unsigned long *mem_end_p)) #ifdef CONFIG_ARCH_ACORN *mem_end_p = GET_MEMORY_END(params); +#elif defined(CONFIG_ARCH_EBSA285) + *mem_end_p = PAGE_OFFSET + params->u1.s.page_size * params->u1.s.nr_pages; #else *mem_end_p = PAGE_OFFSET + MEM_SIZE; #endif @@ -305,18 +309,18 @@ static char command_line[COMMAND_LINE_SIZE] = { 0, }; __initfunc(static void setup_mem(char *cmd_line, unsigned long *mem_start, unsigned long *mem_end)) { - char c = ' ', *to = command_line; + char c, *to = command_line; int len = 0; *mem_start = (unsigned long)&_end; for (;;) { - if (c == ' ' && - cmd_line[0] == 'm' && - cmd_line[1] == 'e' && - cmd_line[2] == 'm' && - cmd_line[3] == '=') { - *mem_end = simple_strtoul(cmd_line+4, &cmd_line, 0); + if (cmd_line[0] == ' ' && + cmd_line[1] == 'm' && + cmd_line[2] == 'e' && + cmd_line[3] == 'm' && + cmd_line[4] == '=') { + *mem_end = simple_strtoul(cmd_line+5, &cmd_line, 0); switch(*cmd_line) { case 'M': case 'm': @@ -336,7 +340,7 @@ setup_mem(char *cmd_line, unsigned long *mem_start, unsigned long *mem_end)) *to++ = c; } - *to = '\0'; + *to = '\0'; } __initfunc(void @@ -381,33 +385,27 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * mem conswitchp = &dummy_con; #endif #endif -printascii("setup_arch done\n"); } +static const struct { + char *machine_name; + char *bus_name; +} machine_desc[] = { + { "DEC-EBSA110", "DEC" }, + { "Acorn-RiscPC", "Acorn" }, + { "Nexus-NexusPCI", "PCI" }, + { "DEC-EBSA285", "PCI" }, + { "Corel-Netwinder", "PCI/ISA" }, + { "Chalice-CATS", "PCI" }, + { "unknown-TBOX", "PCI" } +}; + #if defined(CONFIG_ARCH_ARC) #define HARDWARE "Acorn-Archimedes" #define IO_BUS "Acorn" #elif defined(CONFIG_ARCH_A5K) #define HARDWARE "Acorn-A5000" #define IO_BUS "Acorn" -#elif defined(CONFIG_ARCH_RPC) -#define HARDWARE "Acorn-RiscPC" -#define IO_BUS "Acorn" -#elif defined(CONFIG_ARCH_EBSA110) -#define HARDWARE "DEC-EBSA110" -#define IO_BUS "DEC" -#elif defined(CONFIG_ARCH_EBSA285) -#define HARDWARE "DEC-EBSA285" -#define IO_BUS "PCI" -#elif defined(CONFIG_ARCH_NEXUSPCI) -#define HARDWARE "Nexus-NexusPCI" -#define IO_BUS "PCI" -#elif defined(CONFIG_ARCH_VNC) -#define HARDWARE "Corel-VNC" -#define IO_BUS "PCI" -#else -#define HARDWARE "unknown" -#define IO_BUS "unknown" #endif #if defined(CONFIG_CPU_ARM2) @@ -439,8 +437,17 @@ int get_cpuinfo(char * buffer) (int)processor_id & 15, (loops_per_sec+2500) / 500000, ((loops_per_sec+2500) / 5000) % 100, +#ifdef HARDWARE HARDWARE, +#else + machine_desc[machine_type].machine_name, +#endif OPTIMISATION, - IO_BUS); +#ifdef IO_BUS + IO_BUS +#else + machine_desc[machine_type].bus_name +#endif + ); return len; } diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index 56ada1dc7782..5996398f8390 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c @@ -77,7 +77,8 @@ asmlinkage int old_mmap(struct mmap_arg_struct *arg) goto out; if (!(a.flags & MAP_ANONYMOUS)) { error = -EBADF; - if (a.fd >= NR_OPEN || !(file = current->files->fd[a.fd])) + if (a.fd >= current->files->max_fds || + !(file = current->files->fd[a.fd])) goto out; } a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 6da813aa2370..5d04f325bd3f 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -51,7 +51,7 @@ static int verify_stack_pointer (unsigned long stackptr, int size) if (stackptr < 0x02048000 || stackptr + size > 0x03000000) return -EFAULT; #else - if (stackptr < 0xc0000000 || stackptr + size > (unsigned long)high_memory) + if (stackptr < PAGE_OFFSET || stackptr + size > (unsigned long)high_memory) return -EFAULT; #endif return 0; @@ -175,7 +175,7 @@ void die_if_kernel(char *str, struct pt_regs *regs, int err, int ret) printk("(sp underflow)"); printk("\n"); - dump_mem(cstack, sstack + 4096); + dump_mem(cstack - 16, sstack + 4096); frameptr = regs->ARM_fp; if (frameptr) { diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index d47a092cb393..684db2a47799 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -26,6 +26,10 @@ ifeq ($(MACHINE),ebsa110) L_OBJS += io-ebsa110.o endif +ifeq ($(MACHINE),vnc) + L_OBJS += io-ebsa285.o +endif + ifeq ($(MACHINE),ebsa285) L_OBJS += io-ebsa285.o endif diff --git a/arch/arm/lib/io-ebsa285.S b/arch/arm/lib/io-ebsa285.S index 0ee1e37fc59c..a86983d4350a 100644 --- a/arch/arm/lib/io-ebsa285.S +++ b/arch/arm/lib/io-ebsa285.S @@ -104,24 +104,75 @@ ENTRY(outswb) ENTRY(outsw) add r0, r0, #0xff000000 add r0, r0, #0x00e00000 -1: teq r2, #0 - ldrneh r3, [r1], #2 - strneh r3, [r0] - subne r2, r2, #1 - bne 1b +1: subs r2, r2, #1 + ldrgeh r3, [r1], #2 + strgeh r3, [r0] + bgt 1b mov pc, lr ENTRY(inswb) mov r2, r2, lsr #1 ENTRY(insw) + stmfd sp!, {r4, r5, lr} add r0, r0, #0xff000000 add r0, r0, #0x00e00000 -1: teq r2, #0 + @ + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 + subs ip, r2, #8 + blo too_little + @ + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + ands lr, r1, #3 @ check alignment + beq 1f + + ldrh r3, [r0] + strh r3, [r1], #2 + sub ip, ip, #1 + cmn ip, #8 + blo too_little + +1: ldrh r2, [r0] + ldrh r3, [r0] + orr r2, r2, r3, lsl #16 + ldrh r3, [r0] + ldrh r4, [r0] + orr r3, r3, r4, lsl #16 + ldrh r4, [r0] + ldrh r5, [r0] + orr r4, r4, r5, lsl #16 + ldrh r5, [r0] + ldrh lr, [r0] + orr r5, r5, lr, lsl #16 + stmia r1!, {r2, r3, r4, r5} + subs ip, ip, #8 + @ - 8 - 7 - 6 - 5 - 4 - 3 - 2 - 1 + 0 + 1 + bhs 1b + @ - 8 - 7 - 6 - 5 - 4 - 3 - 2 - 1 - 8 - 7 + cmn ip, #4 + ldrhsh r2, [r0] @ ... ... ... ... - 4 - 3 - 2 - 1 ... ... + ldrhsh r3, [r0] + orrhs r2, r2, r3, lsl #16 + ldrhsh r3, [r0] + ldrhsh r4, [r0] + orrhs r3, r3, r4, lsl #16 + stmhsia r1!, {r2, r3} + + tst ip, #2 + ldrneh r2, [r0] @ ... ... - 6 - 5 ... ... - 2 - 1 ... ... ldrneh r3, [r0] - strneh r3, [r1], #2 - subne r2, r2, #1 - bne 1b - mov pc, lr + orrne r2, r2, r3, lsl #16 + strne r2, [r1], #4 + + tst ip, #1 + ldrneh r2, [r0] + strneh r2, [r1], #2 + + ldmfd sp!, {r4, r5, pc} + +too_little: subs r2, r2, #1 + ldrgeh r3, [r0] + strgeh r3, [r1], #2 + bgt too_little + + ldmfd sp!, {r4, r5, pc} ENTRY(insb) diff --git a/arch/arm/mm/fault-armo.c b/arch/arm/mm/fault-armo.c index 4e244a297d15..6fe1f30ffc65 100644 --- a/arch/arm/mm/fault-armo.c +++ b/arch/arm/mm/fault-armo.c @@ -174,7 +174,7 @@ bad_area: } /* Are we prepared to handle this kernel fault? */ - if ((fixup = search_exception_table(regs->ARM_pc)) != 0) { + if ((fixup = search_exception_table(instruction_pointer(regs))) != 0) { printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n", tsk->comm, regs->ARM_pc, addr, fixup); regs->ARM_pc = fixup; diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 98134abac7c3..f090c5f2c8a1 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c @@ -208,7 +208,7 @@ bad_area: } /* Are we prepared to handle this kernel fault? */ - if ((fixup = search_exception_table(regs->ARM_pc)) != 0) { + if ((fixup = search_exception_table(instruction_pointer(regs))) != 0) { printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n", tsk->comm, regs->ARM_pc, addr, fixup); regs->ARM_pc = fixup; diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 613fefce16c2..b3b0ecf566eb 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -192,6 +192,15 @@ __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem)) reservedpages << (PAGE_SHIFT-10), datapages << (PAGE_SHIFT-10), initpages << (PAGE_SHIFT-10)); + +#ifdef CONFIG_CPU_26 + if (max_mapnr <= 128) { + extern int sysctl_overcommit_memory; + /* On a machine this small we won't get anywhere without + overcommit, so turn it on by default. */ + sysctl_overcommit_memory = 1; + } +#endif } void free_initmem (void) diff --git a/arch/arm/mm/mm-ebsa285.c b/arch/arm/mm/mm-ebsa285.c index 82bbce899dbf..a5b17c6b950e 100644 --- a/arch/arm/mm/mm-ebsa285.c +++ b/arch/arm/mm/mm-ebsa285.c @@ -5,7 +5,6 @@ * * Copyright (C) 1998 Russell King, Dave Gilbert. */ -#include #include #include #include @@ -14,46 +13,7 @@ #include #include #include - -/* - * These two functions convert PCI bus addresses to virtual addresses - * and back again. - */ -unsigned long __virt_to_bus(unsigned long res) -{ - if (res < PAGE_OFFSET || res >= 0xD0000000) { - printk("__virt_to_bus: invalid address 0x%08lx\n", res); -#ifdef CONFIG_DEBUG_ERRORS - __backtrace(); -#endif - } else - res = (res - PAGE_OFFSET) + 0x10000000; - - return res; -} - -unsigned long __bus_to_virt(unsigned long res) -{ - if (res < 0x10000000 || res >= 0x20000000) { - printk("__bus_to_virt: invalid address 0x%08lx\n", res); -#ifdef CONFIG_DEBUG_ERRORS - __backtrace(); -#endif - } else - res = (res - 0x10000000) + PAGE_OFFSET; - - return res; -} - -/* Logical Physical - * 0xfff00000 0x40000000 X-Bus - * 0xffe00000 0x7c000000 PCI I/O space - * 0xfe000000 0x42000000 CSR - * 0xfd000000 0x78000000 Outbound write flush - * 0xfc000000 0x79000000 PCI IACK/special space - * 0xf9000000 0x7a000000 PCI Config type 1 - * 0xf8000000 0x7b000000 PCI Config type 0 - */ +#include /* * This is to allow us to fiddle with the EEPROM @@ -65,15 +25,15 @@ unsigned long __bus_to_virt(unsigned long res) * until we're happy with them... */ #define MAPPING \ - { 0xd8000000, 0x41000000, 0x00400000, DOMAIN_USER, 1, 1 }, /* EEPROM */ \ - { 0xdc000000, 0x7c000000, 0x00100000, DOMAIN_USER, 1, 1 }, /* VGA */ \ - { 0xe0000000, 0x80000000, 0x10000000, DOMAIN_USER, 1, 1 }, /* VGA */ \ - { 0xf8000000, 0x7b000000, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 0 Config */ \ - { 0xf9000000, 0x7a000000, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 1 Config */ \ - { 0xfc000000, 0x79000000, 0x01000000, DOMAIN_IO , 0, 1 }, /* PCI IACK */ \ - { 0xfd000000, 0x78000000, 0x01000000, DOMAIN_IO , 0, 1 }, /* Outbound wflsh*/ \ - { 0xfe000000, 0x42000000, 0x01000000, DOMAIN_IO , 0, 1 }, /* CSR */ \ - { 0xffe00000, 0x7c000000, 0x00100000, DOMAIN_IO , 0, 1 }, /* PCI I/O */ \ - { 0xfff00000, 0x40000000, 0x00100000, DOMAIN_IO , 0, 1 }, /* X-Bus */ + { 0xd8000000, DC21285_FLASH, 0x00400000, DOMAIN_USER, 1, 1 }, /* EEPROM */ \ + { 0xdc000000, 0x7c000000, 0x00100000, DOMAIN_USER, 1, 1 }, /* VGA */ \ + { 0xe0000000, DC21285_PCI_MEM, 0x18000000, DOMAIN_USER, 1, 1 }, /* VGA */ \ + { 0xf8000000, DC21285_PCI_TYPE_0_CONFIG, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 0 Config */ \ + { 0xf9000000, DC21285_PCI_TYPE_1_CONFIG, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 1 Config */ \ + { PCI_IACK, DC21285_PCI_IACK, 0x01000000, DOMAIN_IO , 0, 1 }, /* PCI IACK */ \ + { 0xfd000000, DC21285_OUTBOUND_WRITE_FLUSH, 0x01000000, DOMAIN_IO , 0, 1 }, /* Out wrflsh */ \ + { 0xfe000000, DC21285_ARMCSR_BASE, 0x01000000, DOMAIN_IO , 0, 1 }, /* CSR */ \ + { 0xffe00000, DC21285_PCI_IO, 0x00100000, DOMAIN_IO , 0, 1 }, /* PCI I/O */ \ + { 0xfff00000, 0x40000000, 0x00100000, DOMAIN_IO , 0, 1 }, /* X-Bus */ #include "mm-armv.c" diff --git a/arch/arm/mm/mm-rpc.c b/arch/arm/mm/mm-rpc.c index 18ebe4a47713..1c755faaf6e8 100644 --- a/arch/arm/mm/mm-rpc.c +++ b/arch/arm/mm/mm-rpc.c @@ -91,7 +91,8 @@ init_dram_banks(struct param_struct *params)) #define MAPPING \ { SCREEN2_BASE, SCREEN_START, 2*1048576, DOMAIN_IO, 0, 1 }, /* VRAM */ \ - { IO_BASE, IO_START, IO_SIZE , DOMAIN_IO, 0, 1 } /* IO space */ + { IO_BASE, IO_START, IO_SIZE , DOMAIN_IO, 0, 1 }, /* IO space */ \ + { EASI_BASE, EASI_START, EASI_SIZE, DOMAIN_IO, 0, 1 } /* EASI space */ /* * Include common routine to set up page tables */ diff --git a/arch/arm/mm/mm-vnc.c b/arch/arm/mm/mm-vnc.c index eed49eb291c2..94e03748509b 100644 --- a/arch/arm/mm/mm-vnc.c +++ b/arch/arm/mm/mm-vnc.c @@ -13,20 +13,19 @@ #include #include #include +#include /* Table describing the MMU translation mapping * mainly used to set up the I/O mappings. */ #define MAPPING \ - { 0xe0000000, DC21285_PCI_IO, 0x00100000, DOMAIN_IO, 0, 1 }, /* PCI I/O */ \ - { 0xe0100000, DC21285_PCI_TYPE_0_CONFIG, 0x00f00000, DOMAIN_IO, 0, 1 }, /* Type 0 Config */ \ - { 0xe1000000, DC21285_ARMCSR_BASE, 0x00100000, DOMAIN_IO, 0, 1 }, /* ARM CSR */ \ - { 0xe1100000, DC21285_PCI_IACK, 0x00100000, DOMAIN_IO, 0, 1 }, /* PCI IACK */ \ - { 0xe1300000, DC21285_OUTBOUND_WRITE_FLUSH, 0x00100000, DOMAIN_IO, 0, 1 }, /* Out wrflsh */ \ - { 0xe1400000, DC21285_OUTBOUND_WRITE_FLUSH, 0x00100000, DOMAIN_IO, 0, 1 }, /* Out wrflsh */ \ - { 0xe1500000, DC21285_OUTBOUND_WRITE_FLUSH, 0x00100000, DOMAIN_IO, 0, 1 }, /* Out wrflsh */ \ - { 0xe1600000, DC21285_OUTBOUND_WRITE_FLUSH, 0x00100000, DOMAIN_IO, 0, 1 }, /* Out wrflsh */ \ - { 0xe1700000, DC21285_OUTBOUND_WRITE_FLUSH, 0x00100000, DOMAIN_IO, 0, 1 }, /* Out wrflsh */ \ - { 0xe1800000, DC21285_FLASH, 0x00800000, DOMAIN_IO, 0, 1 } /* Flash */ + { 0xd0000000, DC21285_FLASH, 0x00800000, DOMAIN_IO , 0, 1 }, /* Flash */ \ + { 0xe0000000, DC21285_PCI_MEM, 0x18000000, DOMAIN_IO , 0, 1 }, /* PCI Mem */ \ + { 0xf8000000, DC21285_PCI_TYPE_0_CONFIG, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 0 Config */ \ + { 0xf9000000, DC21285_PCI_TYPE_1_CONFIG, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 1 Config */ \ + { PCI_IACK, DC21285_PCI_IACK, 0x01000000, DOMAIN_IO , 0, 1 }, /* PCI IACK */ \ + { 0xfd000000, DC21285_OUTBOUND_WRITE_FLUSH, 0x01000000, DOMAIN_IO , 0, 1 }, /* Out wrflsh */ \ + { 0xfe000000, DC21285_ARMCSR_BASE, 0x01000000, DOMAIN_IO , 0, 1 }, /* CSR */ \ + { 0xffe00000, DC21285_PCI_IO, 0x00100000, DOMAIN_IO , 0, 1 }, /* PCI I/O */ \ #include "mm-armv.c" diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S index d077ab1d2d5a..221797862611 100644 --- a/arch/arm/mm/proc-sa110.S +++ b/arch/arm/mm/proc-sa110.S @@ -10,6 +10,11 @@ #include #include "../lib/constants.h" +/* This is the maximum size of an area which will be flushed. If the area + * is larger than this, then we flush the whole cache + */ +#define MAX_AREA_SIZE 32768 + .data Lclean_switch: .long 0 .text @@ -52,7 +57,7 @@ _sa110_flush_cache_all_r2: .align 5 _sa110_flush_cache_area: sub r3, r1, r0 - cmp r3, #32768 + cmp r3, #MAX_AREA_SIZE bgt _sa110_flush_cache_all_r2 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry mcr p15, 0, r0, c7, c6, 1 @ flush D entry @@ -79,16 +84,17 @@ _sa110_flush_cache_area: .align 5 _sa110_cache_wback_area: sub r3, r1, r0 - cmp r3, #32768 - movgt r2, #0 - bgt _sa110_flush_cache_all + cmp r3, #MAX_AREA_SIZE + mov r2, #0 + bgt _sa110_flush_cache_all_r2 + bic r0, r0, #31 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry add r0, r0, #32 mcr p15, 0, r0, c7, c10, 1 @ clean D entry add r0, r0, #32 cmp r0, r1 blt 1b - mcr p15, 0, r0, c7, c10, 4 @ drain WB + mcr p15, 0, r2, c7, c10, 4 @ drain WB mov pc, lr /* diff --git a/arch/i386/config.in b/arch/i386/config.in index a22692bcab5e..ca8c263e1476 100644 --- a/arch/i386/config.in +++ b/arch/i386/config.in @@ -39,6 +39,9 @@ bool 'PCI support' CONFIG_PCI if [ "$CONFIG_PCI" = "y" ]; then bool ' PCI BIOS support' CONFIG_PCI_BIOS bool ' PCI direct access support' CONFIG_PCI_DIRECT + if [ "$CONFIG_PCI_BIOS" = "n" -a "$CONFIG_PCI_DIRECT" = "n" ]; then + define_bool CONFIG_PCI_BIOS "y" + fi bool ' PCI quirks' CONFIG_PCI_QUIRKS if [ "$CONFIG_PCI_QUIRKS" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then bool ' PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE @@ -108,12 +111,15 @@ fi source net/ax25/Config.in +source net/irda/Config.in + mainmenu_option next_comment comment 'ISDN subsystem' - -tristate 'ISDN support' CONFIG_ISDN -if [ "$CONFIG_ISDN" != "n" ]; then - source drivers/isdn/Config.in +if [ "$CONFIG_NET" != "n" ]; then + tristate 'ISDN support' CONFIG_ISDN + if [ "$CONFIG_ISDN" != "n" ]; then + source drivers/isdn/Config.in + fi fi endmenu diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c index e0fd62653d99..d8224f0f6178 100644 --- a/arch/i386/kernel/irq.c +++ b/arch/i386/kernel/irq.c @@ -691,8 +691,10 @@ void disable_irq(unsigned int irq) unsigned long flags; spin_lock_irqsave(&irq_controller_lock, flags); - irq_desc[irq].status |= IRQ_DISABLED; - irq_desc[irq].handler->disable(irq); + if (!irq_desc[irq].depth++) { + irq_desc[irq].status |= IRQ_DISABLED; + irq_desc[irq].handler->disable(irq); + } spin_unlock_irqrestore(&irq_controller_lock, flags); if (irq_desc[irq].status & IRQ_INPROGRESS) @@ -704,16 +706,10 @@ void enable_irq(unsigned int irq) unsigned long flags; spin_lock_irqsave(&irq_controller_lock, flags); - /* - * In contrast to the above, we should _not_ have any concurrent - * interrupt activity here, so we just clear both disabled bits. - * - * This allows us to have IRQ_INPROGRESS set until we actually - * install a handler for this interrupt (make irq autodetection - * work by just looking at the status field for the irq) - */ - irq_desc[irq].status &= ~(IRQ_DISABLED | IRQ_INPROGRESS); - irq_desc[irq].handler->enable(irq); + if (!--irq_desc[irq].depth) { + irq_desc[irq].status &= ~IRQ_DISABLED; + irq_desc[irq].handler->enable(irq); + } spin_unlock_irqrestore(&irq_controller_lock, flags); } @@ -798,6 +794,7 @@ int setup_x86_irq(unsigned int irq, struct irqaction * new) *p = new; if (!shared) { + irq_desc[irq].depth = 0; irq_desc[irq].status &= ~(IRQ_DISABLED | IRQ_INPROGRESS); irq_desc[irq].handler->startup(irq); } diff --git a/arch/i386/kernel/irq.h b/arch/i386/kernel/irq.h index 9f0b3e457513..658bda7f2664 100644 --- a/arch/i386/kernel/irq.h +++ b/arch/i386/kernel/irq.h @@ -37,7 +37,8 @@ typedef struct { unsigned int status; /* IRQ status - IRQ_INPROGRESS, IRQ_DISABLED */ struct hw_interrupt_type *handler; /* handle/enable/disable functions */ struct irqaction *action; /* IRQ action list */ - unsigned int unused[3]; + unsigned int depth; /* Disable depth for nested irq disables */ + unsigned int unused[2]; } irq_desc_t; #define IRQ0_TRAP_VECTOR 0x51 diff --git a/arch/i386/kernel/sys_i386.c b/arch/i386/kernel/sys_i386.c index 92bd3b293605..f7987718b952 100644 --- a/arch/i386/kernel/sys_i386.c +++ b/arch/i386/kernel/sys_i386.c @@ -109,10 +109,11 @@ asmlinkage int old_select(struct sel_arg_struct *arg) * This is really horribly ugly. */ asmlinkage int sys_ipc (uint call, int first, int second, - int third, void *ptr, long fifth) + int third, void *ptr, long fifth) { int version, ret; + version = call >> 16; /* hack for backward compatibility */ call &= 0xffff; if (call <= SEMCTL) @@ -126,14 +127,13 @@ asmlinkage int sys_ipc (uint call, int first, int second, if (!ptr) return -EINVAL; if (get_user(fourth.__pad, (void **) ptr)) - return -EFAULT; + return -EFAULT; return sys_semctl (first, second, third, fourth); } default: return -EINVAL; } - version = call >> 16; /* hack for backward compatibility */ if (call <= MSGCTL) switch (call) { case MSGSND: @@ -144,25 +144,25 @@ asmlinkage int sys_ipc (uint call, int first, int second, case 0: { struct ipc_kludge tmp; if (!ptr) - return -EINVAL; + return -EINVAL; if (copy_from_user(&tmp, - (struct ipc_kludge *) ptr, - sizeof (tmp))) + (struct ipc_kludge *) ptr, + sizeof (tmp))) return -EFAULT; return sys_msgrcv (first, tmp.msgp, second, - tmp.msgtyp, third); + tmp.msgtyp, third); } default: return sys_msgrcv (first, - (struct msgbuf *) ptr, - second, fifth, third); + (struct msgbuf *) ptr, + second, fifth, third); } case MSGGET: return sys_msgget ((key_t) first, second); case MSGCTL: return sys_msgctl (first, second, - (struct msqid_ds *) ptr); + (struct msqid_ds *) ptr); default: return -EINVAL; } @@ -170,10 +170,10 @@ asmlinkage int sys_ipc (uint call, int first, int second, switch (call) { case SHMAT: switch (version) { - default: { + default: { ulong raddr; ret = sys_shmat (first, (char *) ptr, - second, &raddr); + second, &raddr); if (ret) return ret; return put_user (raddr, (ulong *) third); @@ -182,7 +182,7 @@ asmlinkage int sys_ipc (uint call, int first, int second, if (!segment_eq(get_fs(), get_ds())) return -EINVAL; return sys_shmat (first, (char *) ptr, - second, (ulong *) third); + second, (ulong *) third); } case SHMDT: return sys_shmdt ((char *)ptr); @@ -190,12 +190,12 @@ asmlinkage int sys_ipc (uint call, int first, int second, return sys_shmget (first, second, third); case SHMCTL: return sys_shmctl (first, second, - (struct shmid_ds *) ptr); + (struct shmid_ds *) ptr); default: return -EINVAL; } - - return -EINVAL; + + return -EINVAL; } /* diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile index 9cd2d1838dd7..d74e7d1f4d65 100644 --- a/arch/m68k/Makefile +++ b/arch/m68k/Makefile @@ -116,6 +116,7 @@ endif archclean: rm -f vmlinux.gz + rm -f kernel/m68k_defs.h kernel/m68k_defs.d archmrproper: diff --git a/arch/m68k/amiga/pcmcia.c b/arch/m68k/amiga/pcmcia.c index 3faac7eda041..e1b29387ac97 100644 --- a/arch/m68k/amiga/pcmcia.c +++ b/arch/m68k/amiga/pcmcia.c @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -26,7 +27,7 @@ void pcmcia_reset(void) unsigned char b; gayle_reset = 0x00; - while (jiffies - reset_start_time < 1*HZ/100); + while (time_before(jiffies, reset_start_time + 1*HZ/100)); b = gayle_reset; } diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c index e6535f6ffdd3..18399bc1f79e 100644 --- a/arch/m68k/atari/atakeyb.c +++ b/arch/m68k/atari/atakeyb.c @@ -825,7 +825,7 @@ __initfunc(int atari_keyb_init(void)) /* wait for a period of inactivity (here: 0.25s), then assume the IKBD's * self-test is finished */ self_test_last_rcv = jiffies; - while( jiffies < self_test_last_rcv + HZ/4 ) + while (time_before(jiffies, self_test_last_rcv + HZ/4)) barrier(); /* if not incremented: no 0xf1 received */ if (ikbd_self_test == 1) diff --git a/arch/m68k/bvme6000/bvmeints.c b/arch/m68k/bvme6000/bvmeints.c index a79f5555de0b..04633375f144 100644 --- a/arch/m68k/bvme6000/bvmeints.c +++ b/arch/m68k/bvme6000/bvmeints.c @@ -119,9 +119,12 @@ void bvme6000_free_irq(unsigned int irq, void *dev_id) void bvme6000_process_int (unsigned long vec, struct pt_regs *fp) { if (vec > 255) - panic ("bvme6000_process_int: Illegal vector %ld", vec); - irq_tab[vec].count++; - irq_tab[vec].handler(vec, irq_tab[vec].dev_id, fp); + printk ("bvme6000_process_int: Illegal vector %ld", vec); + else + { + irq_tab[vec].count++; + irq_tab[vec].handler(vec, irq_tab[vec].dev_id, fp); + } } int bvme6000_get_irq_list (char *buf) diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c index 74d15e995bb4..543b04c74996 100644 --- a/arch/m68k/bvme6000/config.c +++ b/arch/m68k/bvme6000/config.c @@ -91,8 +91,7 @@ void bvme6000_reset() static void bvme6000_get_model(char *model) { - /* XXX Need to detect if BVME4000 or BVME6000 */ - sprintf(model, "BVME6000"); + sprintf(model, "BVME%d000", m68k_cputype == CPU_68060 ? 6 : 4); } @@ -152,13 +151,17 @@ __initfunc(void config_bvme6000(void)) pit->pbddr = 0xf3; /* Mostly outputs */ pit->pcdr = 0x01; /* PA transceiver disabled */ pit->pcddr = 0x03; /* WDOG disable */ + + /* Disable snooping for Ethernet and VME accesses */ + + bvme_acr_addrctl = 0; } void bvme6000_abort_int (int irq, void *dev_id, struct pt_regs *fp) { unsigned long *new = (unsigned long *)vectors; - unsigned long *old = (unsigned long *)0xf8000000;; + unsigned long *old = (unsigned long *)0xf8000000; /* Wait for button release */ while (*config_reg_ptr & BVME_ABORT_STATUS) diff --git a/arch/m68k/config.in b/arch/m68k/config.in index 8fe84aecd4cc..48b70f025717 100644 --- a/arch/m68k/config.in +++ b/arch/m68k/config.in @@ -53,22 +53,11 @@ bool '68020 support' CONFIG_M68020 bool '68030 support' CONFIG_M68030 bool '68040 support' CONFIG_M68040 bool '68060 support' CONFIG_M68060 -if [ "$CONFIG_M68020" = "n" -a "$CONFIG_M68030" = "n" ]; then - if [ "$CONFIG_M68040" = "y" -a "$CONFIG_M68060" = "n" ]; then - bool 'Use 68040 specific optimizations' CONFIG_OPTIMIZE_040 - fi - if [ "$CONFIG_M68040" = "n" -a "$CONFIG_M68060" = "y" ]; then - bool 'Use 68060 specific optimizations' CONFIG_OPTIMIZE_060 - fi -fi -if [ "$CONFIG_VME" = "y" -a "$CONFIG_M68060" = "y" ]; then - define_bool CONFIG_060_WRITETHROUGH y -fi bool 'Advanced configuration options' CONFIG_ADVANCED if [ "$CONFIG_ADVANCED" = "y" ]; then bool 'Use read-modify-write instructions' CONFIG_RMW_INSNS bool 'Use one physical chunk of memory only' CONFIG_SINGLE_MEMORY_CHUNK - if [ "$CONFIG_M68060" = "y" -a "$CONFIG_VME" = "n" ]; then + if [ "$CONFIG_M68060" = "y" ]; then bool 'Use write-through caching for 68060 supervisor accesses' CONFIG_060_WRITETHROUGH fi fi @@ -157,7 +146,7 @@ if [ "$CONFIG_ZORRO" = "y" ]; then bool 'A4091 SCSI support' CONFIG_A4091_SCSI bool 'WarpEngine SCSI support' CONFIG_WARPENGINE_SCSI bool 'Blizzard PowerUP 603e+ SCSI' CONFIG_BLZ603EPLUS_SCSI - bool 'Cyberstorm Mk III SCSI support' CONFIG_CYBERSTORMIII_SCSI +# bool 'Cyberstorm Mk III SCSI support' CONFIG_CYBERSTORMIII_SCSI # bool 'GVP Turbo 040/060 SCSI support' CONFIG_GVP_TURBO_SCSI fi fi @@ -230,10 +219,10 @@ if [ "$CONFIG_MAC" = "y" ]; then bool 'Macintosh onboard SONIC ethernet' CONFIG_MACSONIC fi if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME16x" = "y" ]; then - bool 'MVME16x Ethernet support' CONFIG_MVME16x_NET + tristate 'MVME16x Ethernet support' CONFIG_MVME16x_NET fi if [ "$CONFIG_VME" = "y" -a "$CONFIG_BVME6000" = "y" ]; then - bool 'BVME6000 Ethernet support' CONFIG_BVME6000_NET + tristate 'BVME6000 Ethernet support' CONFIG_BVME6000_NET fi if [ "$CONFIG_ATARI" = "y" ]; then tristate 'Atari Lance support' CONFIG_ATARILANCE diff --git a/arch/m68k/defconfig b/arch/m68k/defconfig index 5a9f39e52382..f64768e15d78 100644 --- a/arch/m68k/defconfig +++ b/arch/m68k/defconfig @@ -28,8 +28,6 @@ CONFIG_M68020=y CONFIG_M68030=y CONFIG_M68040=y # CONFIG_M68060 is not set -# CONFIG_OPTIMIZE_040 is not set -# CONFIG_OPTIMIZE_060 is not set # CONFIG_ADVANCED is not set # CONFIG_SINGLE_MEMORY_CHUNK is not set # CONFIG_RMW_INSNS is not set diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile index 977120c1e621..280a5b4500d0 100644 --- a/arch/m68k/kernel/Makefile +++ b/arch/m68k/kernel/Makefile @@ -26,10 +26,13 @@ endif head.o: head.S m68k_defs.h -m68k_defs.h: m68k_defs.c m68k_defs.head $(TOPDIR)/include/linux/sched.h - $(CC) ${CFLAGS} -S m68k_defs.c +m68k_defs.h: m68k_defs.c m68k_defs.head + rm -f m68k_defs.d + SUNPRO_DEPENDENCIES="m68k_defs.d m68k_defs.h" \ + $(CC) $(filter-out -MD,$(CFLAGS)) -S m68k_defs.c cp m68k_defs.head m68k_defs.h - sed -n < m68k_defs.s >> m68k_defs.h '/^#define/s/ #/ /p' + grep '^#define' m68k_defs.s >> m68k_defs.h rm m68k_defs.s +-include m68k_defs.d include $(TOPDIR)/Rules.make diff --git a/arch/m68k/kernel/m68k_defs.c b/arch/m68k/kernel/m68k_defs.c index 122bf63be4fd..e5086edbe220 100644 --- a/arch/m68k/kernel/m68k_defs.c +++ b/arch/m68k/kernel/m68k_defs.c @@ -12,7 +12,7 @@ #include #define DEFINE(sym, val) \ - asm volatile("\n#define " #sym " %0" : : "i" (val)) + asm volatile("\n#define " #sym " %c0" : : "i" (val)) int main(void) { diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c index 40b692e0c3cf..9c20abe81448 100644 --- a/arch/m68k/kernel/m68k_ksyms.c +++ b/arch/m68k/kernel/m68k_ksyms.c @@ -49,6 +49,7 @@ EXPORT_SYMBOL(local_irq_count); EXPORT_SYMBOL(local_bh_count); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); +EXPORT_SYMBOL(kernel_set_cachemode); /* Networking helper routines. */ EXPORT_SYMBOL(csum_partial_copy); diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index fb9bac4000e4..1eb287ed2e56 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -40,7 +40,6 @@ */ static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; -static struct file * init_fd_array[NR_OPEN] = { NULL, }; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; struct mm_struct init_mm = INIT_MM; diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c index f410182e043e..415122f3a96e 100644 --- a/arch/m68k/mac/config.c +++ b/arch/m68k/mac/config.c @@ -100,17 +100,15 @@ extern void mac_debug_init(void); extern void mac_debugging_long(int, long); #ifdef CONFIG_MAGIC_SYSRQ - -/* XXX FIXME: Atari scancodes still */ static char mac_sysrq_xlate[128] = - "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ - "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ - "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ - "bnm,./\000\000\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ - "\206\207\210\211\212\000\000\000\000\000-\000\000\000+\000"/* 0x40 - 0x4f */ - "\000\000\000\177\000\000\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ - "\000\000\000()/*789456123" /* 0x60 - 0x6f */ - "0.\r\000\000\000\000\000\000\000\000\000\000\000\000\000"; /* 0x70 - 0x7f */ + "\000sdfghzxcv\000bqwer" /* 0x00 - 0x0f */ + "yt123465=97-80)o" /* 0x10 - 0x1f */ + "u(ip\rlj'k;\\,/nm." /* 0x20 - 0x2f */ + "\t `\000\033\000\000\000\000\000\000\000\000\000\000\000" /* 0x30 - 0x3f */ + "\000.\000*\000+\000\000\000\000\000/\r\000-\000" /* 0x40 - 0x4f */ + "\000\00001234567a89\000\000\000" /* 0x50 - 0x5f */ + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" /* 0x60 - 0x6f */ + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"; /* 0x70 - 0x7f */ #endif extern void (*kd_mksound)(unsigned int, unsigned int); @@ -336,7 +334,7 @@ __initfunc(void config_mac(void)) #endif kd_mksound = mac_mksound; #ifdef CONFIG_MAGIC_SYSRQ - mach_sysrq_key = 98; /* HELP */ + mach_sysrq_key = 114; /* HELP */ mach_sysrq_shift_state = 8; /* Alt */ mach_sysrq_shift_mask = 0xff; /* all modifiers except CapsLock */ mach_sysrq_xlate = mac_sysrq_xlate; @@ -399,10 +397,10 @@ static struct mac_model mac_data_table[]= * */ - { MAC_MODEL_II, "II", MAC_ADB_II, MAC_VIA_II, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_NUBUS}, - { MAC_MODEL_IIX, "IIx", MAC_ADB_II, MAC_VIA_II, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_NUBUS}, - { MAC_MODEL_IICX, "IIcx", MAC_ADB_II, MAC_VIA_II, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_NUBUS}, - { MAC_MODEL_SE30, "SE/30", MAC_ADB_II, MAC_VIA_II, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_NUBUS}, + { MAC_MODEL_II, "II", MAC_ADB_II, MAC_VIA_II, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_IIX, "IIx", MAC_ADB_II, MAC_VIA_II, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_IICX, "IIcx", MAC_ADB_II, MAC_VIA_II, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_SE30, "SE/30", MAC_ADB_II, MAC_VIA_II, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, /* * Weirdified MacII hardware - all subtley different. Gee thanks @@ -461,11 +459,11 @@ static struct mac_model mac_data_table[]= * Performa - more LC type machines */ - { MAC_MODEL_P460, "Performa 460", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P460, "Performa 460", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_P475, "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_P475F, "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_P520, "Performa 520", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_P550, "Performa 550", MAC_ADB_CUDA, MAC_VIA_IIci, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P550, "Performa 550", MAC_ADB_CUDA, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_P575, "Performa 575", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_P588, "Performa 588", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_TV, "TV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, @@ -551,7 +549,7 @@ void mac_identify(void) m++; } if(m->ident==-1) - mac_boom(5); + panic("mac model config data corrupt!\n"); } /* diff --git a/arch/m68k/mac/debug.c b/arch/m68k/mac/debug.c index 62a8a6187fbe..fc99409eed48 100644 --- a/arch/m68k/mac/debug.c +++ b/arch/m68k/mac/debug.c @@ -36,6 +36,9 @@ extern unsigned long mac_videobase; extern unsigned long mac_videodepth; extern unsigned long mac_rowbytes; +extern void mac_serial_print(char *); + +#define DEBUG_HEADS #define DEBUG_SCREEN #define DEBUG_SERIAL @@ -129,121 +132,6 @@ void mac_debugging_long(int pos, long addr) #endif } -/* - * Penguin - used by head.S console; obsolete - */ -char that_penguin[]={ -#include "that_penguin.h" -}; - -#ifdef DEBUG_SCREEN -/* - * B/W version of penguin, unfinished - any takers?? - */ -static char bw_penguin[]={ -#include "bw_penguin.h" -}; -#endif - -void mac_debugging_penguin(int peng) -{ -#ifdef DEBUG_SCREEN - unsigned char *pengoffset; - unsigned char *pptr; - unsigned char *bwpdptr=bw_penguin; - int i; -#endif - -#ifdef DEBUG_SERIAL - printk("Penguin: #%d !\n", peng); -#endif - -#ifdef DEBUG_SCREEN - if (!MACH_IS_MAC) - return; - - if (mac_videodepth ==1) - pengoffset=(unsigned char *)(mac_videobase+80*mac_rowbytes) - +5*peng; - else - pengoffset=(unsigned char *)(mac_videobase+80*mac_rowbytes) - +20*peng; - - pptr=pengoffset; - - for(i=0;i<36;i++) - { - memcpy(pptr,bwpdptr,4); - bwpdptr+=4; - pptr+=mac_rowbytes; - } -#endif -} - -#ifdef DEBUG_SCREEN -/* - * B/W version of flaming Mac, unfinished (see above). - */ -static char bw_kaboom_map[]={ -#include "bw_mac.h" -}; -#endif - -#ifdef DEBUG_SCREEN -static void mac_boom_boom(void) -{ - static unsigned char *boomoffset=NULL; - unsigned char *pptr; - unsigned char *bwpdptr=bw_kaboom_map; - int i; - -#ifdef DEBUG_SERIAL - printk("BOOM !\n"); -#endif - - if (!MACH_IS_MAC) - return; - - if(!boomoffset) - if (mac_videodepth == 1) { - boomoffset=(unsigned char *)(mac_videobase+160*mac_rowbytes); - } else { - boomoffset=(unsigned char *)(mac_videobase+256*mac_rowbytes); - } - else - if (mac_videodepth == 1) - boomoffset+=5; - else - boomoffset+=32; - - pptr=boomoffset; - - for(i=0;i<36;i++) - { - memcpy(pptr,bwpdptr,4); - bwpdptr+=4; - pptr+=mac_rowbytes; - } -} -#endif - -void mac_boom(int booms) -{ -#ifdef DEBUG_SCREEN - int i; -#endif - - if (!MACH_IS_MAC) - return; - -#ifdef DEBUG_SCREEN - for(i=0;iident == MAC_MODEL_IIFX) { - /* no real VIA2, the OSS seems _very_different */ + /* no real VIA2, the OSS seems _very_ different */ via2_is_oss = 1; /* IIfx has OSS, at a different base address than RBV */ rbv_regp = (unsigned char *) OSS_BAS; @@ -459,7 +459,7 @@ int mac_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_re if (irq == IRQ_IDX(IRQ_MAC_SCSI)) { /* * Set vPCR for SCSI interrupts. (what about RBV here?) - * 980429 MS: RBV is ok, OSS seems to be differentt + * 980429 MS: RBV is ok, OSS seems to be different */ if (!via2_is_oss) if (macintosh_config->scsi_type == MAC_SCSI_OLD) { @@ -602,7 +602,10 @@ void mac_disable_irq (unsigned int irq) /* * In opposite to {en,dis}able_irq, requests between turn{off,on}_irq are not - * "stored". This is done with the VIA interrupt enable register + * "stored". This is done with the VIA interrupt enable register on VIAs. + * + * Note: Using these functions on non-VIA/OSS/PSC ints will panic, or at least + * have undesired side effects. */ void mac_turnon_irq( unsigned int irq ) @@ -615,14 +618,14 @@ void mac_turnon_irq( unsigned int irq ) if (!via) return; - if (srcidx == SRC_VIA2 && via2_is_rbv) + if (srcidx == SRC_VIA2 && via2_is_rbv) /* RBV as VIA2 */ via_write(via, rIER, via_read(via, rIER)|0x80|(1<<(irqidx))); - else if (srcidx == SRC_VIA2 && via2_is_oss) + else if (srcidx == SRC_VIA2 && via2_is_oss) /* OSS */ via_write(oss_regp, oss_map[irqidx]+8, 2); - else if (srcidx > SRC_VIA2) + else if (srcidx > SRC_VIA2) /* hope AVs have VIA2 */ via_write(via, (0x104 + 0x10*srcidx), via_read(via, (0x104 + 0x10*srcidx))|0x80|(1<<(irqidx))); - else + else /* VIA1+2 */ via_write(via, vIER, via_read(via, vIER)|0x80|(1<<(irqidx))); } @@ -637,9 +640,9 @@ void mac_turnoff_irq( unsigned int irq ) if (!via) return; - if (srcidx == SRC_VIA2 && via2_is_rbv) + if (srcidx == SRC_VIA2 && via2_is_rbv) /* RBV as VIA2 */ via_write(via, rIER, (via_read(via, rIER)&(1< SRC_VIA2) via_write(via, (0x104 + 0x10*srcidx), via_read(via, (0x104 + 0x10*srcidx))|(1<<(irqidx))); - else + else /* VIA1+2 */ via_write(via, vIER, (via_read(via, vIER)&(1<2) { diff --git a/arch/m68k/mac/mackeyb.c b/arch/m68k/mac/mackeyb.c index 64cd5e1f8e01..555f3f5f3b21 100644 --- a/arch/m68k/mac/mackeyb.c +++ b/arch/m68k/mac/mackeyb.c @@ -1,5 +1,12 @@ /* - * linux/arch/m68k/mac/mackeyb.c + * linux/arch/m68k/mac/mackeyb.c + * + * Keyboard driver for Macintosh computers. + * + * Adapted from drivers/macintosh/key_mac.c and arch/m68k/atari/akakeyb.c + * (see that file for its authors and contributors). + * + * Copyright (C) 1997 Michael Schmitz. * * 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 @@ -59,8 +66,15 @@ extern void put_queue(int); static void mac_leds_done(struct adb_request *); static void keyboard_input(unsigned char *, int, struct pt_regs *); static void mouse_input(unsigned char *, int, struct pt_regs *); -/* Hook for mouse driver */ -void (*adb_mouse_interrupt_hook) (char *, int); + +#ifdef CONFIG_ADBMOUSE +/* XXX: Hook for mouse driver */ +void (*adb_mouse_interrupt_hook)(unsigned char *, int); +int adb_emulate_buttons = 0; +int adb_button2_keycode = 0x7d; /* right control key */ +int adb_button3_keycode = 0x7c; /* right option key */ +#endif + /* The mouse driver - for debugging */ extern void adb_mouse_interrupt(char *, int); /* end keyb */ @@ -275,9 +289,11 @@ input_keycode(int keycode, int repeat) kbd = kbd_table + fg_console; up_flag = (keycode & 0x80); keycode &= 0x7f; + if (!repeat) del_timer(&repeat_timer); +#ifdef CONFIG_ADBMOUSE /* * XXX: Add mouse button 2+3 fake codes here if mouse open. * As we only report up/down events, keep track of faked buttons. @@ -289,7 +305,8 @@ input_keycode(int keycode, int repeat) * (wanted: command and alt/option, or KP= and KP( ...) * Debug version; might be rewritten to be faster on normal keys. */ - if (adb_mouse_interrupt_hook || console_loglevel >= 8) { + if (adb_emulate_buttons + && (adb_mouse_interrupt_hook || console_loglevel >= 8)) { unsigned char button, button2, button3, fake_event; static unsigned char button2state=0, button3state=0; /* up */ /* faked ADB packet */ @@ -297,21 +314,20 @@ input_keycode(int keycode, int repeat) button = 0; fake_event = 0; - switch (keycode) { /* which 'button' ? */ - case 0x7c: /* R-option */ - button2 = (!up_flag); /* new state */ - if (button2 != button2state) /* change ? */ - button = 2; - button2state = button2; /* save state */ - fake_event = 2; - break; - case 0x7d: /* R-control */ - button3 = (!up_flag); /* new state */ - if (button3 != button3state) /* change ? */ - button = 3; - button3state = button3; /* save state */ - fake_event = 3; - break; + if (keycode == adb_button2_keycode) { /* which 'button' ? */ + /* R-option */ + button2 = (!up_flag); /* new state */ + if (button2 != button2state) /* change ? */ + button = 2; + button2state = button2; /* save state */ + fake_event = 2; + } else if (keycode == adb_button3_keycode) { + /* R-control */ + button3 = (!up_flag); /* new state */ + if (button3 != button3state) /* change ? */ + button = 3; + button3state = button3; /* save state */ + fake_event = 3; } #ifdef DEBUG_ADBMOUSE if (fake_event && console_loglevel >= 8) @@ -340,6 +356,7 @@ input_keycode(int keycode, int repeat) if (fake_event) return; } +#endif /* CONFIG_ADBMOUSE */ /* * Convert R-shift/control/option to L version. @@ -365,16 +382,18 @@ input_keycode(int keycode, int repeat) * transition into a key-down transition. * MSch: need to turn each caps-lock event into a down-up * double event (keyboard code assumes caps-lock is a toggle) + * 981127: fix LED behavior (kudos atong!) */ -#if 0 - if (keycode == 0x39 && up_flag && vc_kbd_led(kbd, VC_CAPSLOCK)) - up_flag = 0; -#else - if (keycode == 0x39) { + switch (keycode) { + case 0x39: handle_scancode(keycode); /* down */ up_flag = 0x80; /* see below ... */ + mark_bh(KEYBOARD_BH); + break; + case 0x47: + mark_bh(KEYBOARD_BH); + break; } -#endif } handle_scancode(keycode + up_flag); diff --git a/arch/m68k/mac/via6522.c b/arch/m68k/mac/via6522.c index 08ca49071d27..05e6f44e4da3 100644 --- a/arch/m68k/mac/via6522.c +++ b/arch/m68k/mac/via6522.c @@ -304,10 +304,11 @@ void mac_reset(void) unsigned long flags; unsigned long *reset_hook; - save_flags(flags); - cli(); - /* need ROMBASE in booter */ + /* indeed, plus need to MAP THE ROM !! */ + + if (mac_bi_data.rombase == 0) + mac_bi_data.rombase = 0x40800000; /* works on some */ rom_reset = (void *) (mac_bi_data.rombase + 0xa); @@ -318,12 +319,22 @@ void mac_reset(void) printk("ROM reset hook: %p\n", *reset_hook); rom_reset = *reset_hook; #endif + if (macintosh_config->ident == MAC_MODEL_SE30) { + /* + * MSch: Machines known to crash on ROM reset ... + */ + printk("System halted.\n"); + while(1); + } else { + save_flags(flags); + cli(); - rom_reset(); + rom_reset(); - restore_flags(flags); + restore_flags(flags); + } - /* We never make it this far... */ + /* We never make it this far... it usually panics above. */ printk ("Restart failed. Please restart manually.\n"); /* XXX - delay do we need to spin here ? */ diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c index 62129782b19a..ef1b855bd72b 100644 --- a/arch/m68k/mm/fault.c +++ b/arch/m68k/mm/fault.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -32,8 +33,7 @@ extern const int frame_extra_sizes[]; /* in m68k/kernel/signal.c */ asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address, unsigned long error_code) { - struct task_struct *tsk = current; - struct mm_struct *mm = tsk->mm; + struct mm_struct *mm = current->mm; struct vm_area_struct * vma; unsigned long fixup; int write; @@ -41,9 +41,17 @@ asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address, #ifdef DEBUG printk ("regs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n", regs->sr, regs->pc, address, error_code, - tsk->mm->pgd); + current->mm->pgd); #endif + + /* + * If we're in an interrupt or have no user + * context, we must not take the fault.. + */ + if (in_interrupt() || mm == &init_mm) + goto no_context; + down(&mm->mmap_sem); vma = find_vma(mm, address); @@ -86,7 +94,14 @@ good_area: if (!(vma->vm_flags & (VM_READ | VM_EXEC))) goto bad_area; } - handle_mm_fault(current, vma, address, write); + + /* + * If for any reason at all we couldn't handle the fault, + * make sure we exit gracefully rather than endlessly redo + * the fault. + */ + if (!handle_mm_fault(current, vma, address, write)) + goto do_sigbus; /* There seems to be a missing invalidate somewhere in do_no_page. * Until I found it, this one cures the problem and makes @@ -106,10 +121,15 @@ bad_area: /* User mode accesses just cause a SIGSEGV */ if (user_mode(regs)) { - force_sig (SIGSEGV, tsk); + siginfo_t info; + info.si_signo = SIGSEGV; + info.si_code = SEGV_MAPERR; + info.si_addr = (void *)address; + force_sig_info(SIGSEGV, &info, current); return 1; } +no_context: /* Are we prepared to handle this kernel fault? */ if ((fixup = search_exception_table(regs->pc)) != 0) { struct pt_regs *tregs; @@ -136,5 +156,22 @@ bad_area: die_if_kernel("Oops", regs, error_code); do_exit(SIGKILL); +/* + * We ran out of memory, or some other thing happened to us that made + * us unable to handle the page fault gracefully. + */ +do_sigbus: + up(&mm->mmap_sem); + + /* + * Send a sigbus, regardless of whether we were in kernel + * or user mode. + */ + force_sig(SIGBUS, current); + + /* Kernel mode? Handle exceptions or die */ + if (!user_mode(regs)) + goto no_context; + return 1; } diff --git a/arch/m68k/mvme16x/16xints.c b/arch/m68k/mvme16x/16xints.c index fbb370a07f8f..9cc0d39d1f11 100644 --- a/arch/m68k/mvme16x/16xints.c +++ b/arch/m68k/mvme16x/16xints.c @@ -106,9 +106,12 @@ void mvme16x_free_irq(unsigned int irq, void *dev_id) void mvme16x_process_int (unsigned long vec, struct pt_regs *fp) { if (vec < 64 || vec > 255) - panic ("mvme16x_process_int: Illegal vector %ld", vec); - irq_tab[vec-64].count++; - irq_tab[vec-64].handler(vec, irq_tab[vec-64].dev_id, fp); + printk ("mvme16x_process_int: Illegal vector %ld", vec); + else + { + irq_tab[vec-64].count++; + irq_tab[vec-64].handler(vec, irq_tab[vec-64].dev_id, fp); + } } int mvme16x_get_irq_list (char *buf) diff --git a/drivers/acorn/block/ide-ics.c b/drivers/acorn/block/ide-ics.c index 188206d3ac5f..17bc5e6fdcf0 100644 --- a/drivers/acorn/block/ide-ics.c +++ b/drivers/acorn/block/ide-ics.c @@ -27,6 +27,7 @@ #define ICS_IDENT_OFFSET 0x8a0 +#define ICS_ARCIN_V5_INTRSTAT 0x000 #define ICS_ARCIN_V5_INTROFFSET 0x001 #define ICS_ARCIN_V5_IDEOFFSET 0xa00 #define ICS_ARCIN_V5_IDEALTOFFSET 0xae0 @@ -34,9 +35,11 @@ #define ICS_ARCIN_V6_IDEOFFSET_1 0x800 #define ICS_ARCIN_V6_INTROFFSET_1 0x880 +#define ICS_ARCIN_V6_INTRSTAT_1 0x8a4 #define ICS_ARCIN_V6_IDEALTOFFSET_1 0x8e0 #define ICS_ARCIN_V6_IDEOFFSET_2 0xc00 #define ICS_ARCIN_V6_INTROFFSET_2 0xc80 +#define ICS_ARCIN_V6_INTRSTAT_2 0xca4 #define ICS_ARCIN_V6_IDEALTOFFSET_2 0xce0 #define ICS_ARCIN_V6_IDESTEPPING 4 @@ -199,6 +202,8 @@ static inline void icside_register (struct expansion_card *ec, int index) case ics_if_arcin_v5: port = ecard_address (ec, ECARD_MEMC, 0); + ec->irqaddr = ioaddr(port + ICS_ARCIN_V5_INTRSTAT); + ec->irqmask = 1; ec->irq_data = (void *)port; ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v5; @@ -210,10 +215,13 @@ static inline void icside_register (struct expansion_card *ec, int index) port + ICS_ARCIN_V5_IDEALTOFFSET, ICS_ARCIN_V5_IDESTEPPING, ec->irq); + result[index][1] = -1; break; case ics_if_arcin_v6: port = ecard_address (ec, ECARD_IOC, ECARD_FAST); + ec->irqaddr = ioaddr(port + ICS_ARCIN_V6_INTRSTAT_1); + ec->irqmask = 1; ec->irq_data = (void *)port; ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v6; diff --git a/drivers/acorn/char/Config.in b/drivers/acorn/char/Config.in index cbd70732d44f..ede0a82661b2 100644 --- a/drivers/acorn/char/Config.in +++ b/drivers/acorn/char/Config.in @@ -2,3 +2,14 @@ if [ "$CONFIG_SERIAL" != "n" ]; then tristate ' Atomwide serial port support' CONFIG_ATOMWIDE_SERIAL tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL fi + +if [ "$CONFIG_MOUSE" = "y" ]; then + if [ "$CONFIG_ARCH_ACORN" = "y" ]; then + if [ "$CONFIG_ARCH_RPC" != "y" ]; then + define_bool CONFIG_KBDMOUSE y + else + define_bool CONFIG_RPCMOUSE y + fi + fi +fi + diff --git a/drivers/acorn/char/Makefile b/drivers/acorn/char/Makefile index ffc01825f917..ecbbfe90c007 100644 --- a/drivers/acorn/char/Makefile +++ b/drivers/acorn/char/Makefile @@ -13,6 +13,19 @@ L_TARGET := acorn-char.a M_OBJS := L_OBJS := +ifeq ($(MACHINE),rpc) + MOUSE_OBJS += mouse_rpc.o + L_OBJS += keyb_ps2.o +endif + +ifeq ($(CONFIG_MOUSE),y) + LX_OBJS += $(MOUSE_OBJS) +else + ifeq ($(CONFIG_MOUSE),m) + MX_OBJS += $(MOUSE_OBJS) + endif +endif + ifeq ($(CONFIG_ATOMWIDE_SERIAL),y) L_OBJS += serial-atomwide.o else diff --git a/drivers/acorn/char/keyb_ps2.c b/drivers/acorn/char/keyb_ps2.c new file mode 100644 index 000000000000..c3ef33363a6b --- /dev/null +++ b/drivers/acorn/char/keyb_ps2.c @@ -0,0 +1,355 @@ +/* + * linux/arch/arm/drivers/block/keyb_ps2.c + * + * Keyboard driver for RPC ARM Linux. + * + * Note!!! This driver talks directly to the keyboard. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +extern void kbd_reset_kdown(void); +int kbd_read_mask; + +#define IRQ_KEYBOARDRX 15 + +#define VERSION 100 + +#define KBD_REPORT_ERR +#define KBD_REPORT_UNKN + +#define KBD_ESCAPEE0 0xe0 /* in */ +#define KBD_ESCAPEE1 0xe1 /* in */ + +#define ESCE0(x) (0xe000|(x)) +#define ESCE1(x) (0xe100|(x)) + +#define KBD_BAT 0xaa /* in */ +#define KBD_SETLEDS 0xed /* out */ +#define KBD_ECHO 0xee /* in/out */ +#define KBD_BREAK 0xf0 /* in */ +#define KBD_TYPRATEDLY 0xf3 /* out */ +#define KBD_SCANENABLE 0xf4 /* out */ +#define KBD_DEFDISABLE 0xf5 /* out */ +#define KBD_DEFAULT 0xf6 /* out */ +#define KBD_ACK 0xfa /* in */ +#define KBD_DIAGFAIL 0xfd /* in */ +#define KBD_RESEND 0xfe /* in/out */ +#define KBD_RESET 0xff /* out */ + +#define CODE_BREAK 1 +#define CODE_ESCAPEE0 2 +#define CODE_ESCAPEE1 4 +#define CODE_ESCAPE12 8 + +#define K_NONE 0x7f +#define K_ESC 0x00 +#define K_F1 0x01 +#define K_F2 0x02 +#define K_F3 0x03 +#define K_F4 0x04 +#define K_F5 0x05 +#define K_F6 0x06 +#define K_F7 0x07 +#define K_F8 0x08 +#define K_F9 0x09 +#define K_F10 0x0a +#define K_F11 0x0b +#define K_F12 0x0c +#define K_PRNT 0x0d +#define K_SCRL 0x0e +#define K_BRK 0x0f +#define K_AGR 0x10 +#define K_1 0x11 +#define K_2 0x12 +#define K_3 0x13 +#define K_4 0x14 +#define K_5 0x15 +#define K_6 0x16 +#define K_7 0x17 +#define K_8 0x18 +#define K_9 0x19 +#define K_0 0x1a +#define K_MINS 0x1b +#define K_EQLS 0x1c +#define K_BKSP 0x1e +#define K_INS 0x1f +#define K_HOME 0x20 +#define K_PGUP 0x21 +#define K_NUML 0x22 +#define KP_SLH 0x23 +#define KP_STR 0x24 +#define KP_MNS 0x3a +#define K_TAB 0x26 +#define K_Q 0x27 +#define K_W 0x28 +#define K_E 0x29 +#define K_R 0x2a +#define K_T 0x2b +#define K_Y 0x2c +#define K_U 0x2d +#define K_I 0x2e +#define K_O 0x2f +#define K_P 0x30 +#define K_LSBK 0x31 +#define K_RSBK 0x32 +#define K_ENTR 0x47 +#define K_DEL 0x34 +#define K_END 0x35 +#define K_PGDN 0x36 +#define KP_7 0x37 +#define KP_8 0x38 +#define KP_9 0x39 +#define KP_PLS 0x4b +#define K_CAPS 0x5d +#define K_A 0x3c +#define K_S 0x3d +#define K_D 0x3e +#define K_F 0x3f +#define K_G 0x40 +#define K_H 0x41 +#define K_J 0x42 +#define K_K 0x43 +#define K_L 0x44 +#define K_SEMI 0x45 +#define K_SQOT 0x46 +#define K_HASH 0x1d +#define KP_4 0x48 +#define KP_5 0x49 +#define KP_6 0x4a +#define K_LSFT 0x4c +#define K_BSLH 0x33 +#define K_Z 0x4e +#define K_X 0x4f +#define K_C 0x50 +#define K_V 0x51 +#define K_B 0x52 +#define K_N 0x53 +#define K_M 0x54 +#define K_COMA 0x55 +#define K_DOT 0x56 +#define K_FSLH 0x57 +#define K_RSFT 0x58 +#define K_UP 0x59 +#define KP_1 0x5a +#define KP_2 0x5b +#define KP_3 0x5c +#define KP_ENT 0x67 +#define K_LCTL 0x3b +#define K_LALT 0x5e +#define K_SPCE 0x5f +#define K_RALT 0x60 +#define K_RCTL 0x61 +#define K_LEFT 0x62 +#define K_DOWN 0x63 +#define K_RGHT 0x64 +#define KP_0 0x65 +#define KP_DOT 0x66 + +static unsigned char keycode_translate[256] = +{ +/* 00 */ K_NONE, K_F9 , K_NONE, K_F5 , K_F3 , K_F1 , K_F2 , K_F12 , +/* 08 */ K_NONE, K_F10 , K_F8 , K_F6 , K_F4 , K_TAB , K_AGR , K_NONE, +/* 10 */ K_NONE, K_LALT, K_LSFT, K_NONE, K_LCTL, K_Q , K_1 , K_NONE, +/* 18 */ K_NONE, K_NONE, K_Z , K_S , K_A , K_W , K_2 , K_NONE, +/* 20 */ K_NONE, K_C , K_X , K_D , K_E , K_4 , K_3 , K_NONE, +/* 28 */ K_NONE, K_SPCE, K_V , K_F , K_T , K_R , K_5 , K_NONE, +/* 30 */ K_NONE, K_N , K_B , K_H , K_G , K_Y , K_6 , K_NONE, +/* 38 */ K_NONE, K_NONE, K_M , K_J , K_U , K_7 , K_8 , K_NONE, +/* 40 */ K_NONE, K_COMA, K_K , K_I , K_O , K_0 , K_9 , K_NONE, +/* 48 */ K_NONE, K_DOT , K_FSLH, K_L , K_SEMI, K_P , K_MINS, K_NONE, +/* 50 */ K_NONE, K_NONE, K_SQOT, K_NONE, K_LSBK, K_EQLS, K_NONE, K_NONE, +/* 58 */ K_CAPS, K_RSFT, K_ENTR, K_RSBK, K_NONE, K_HASH, K_NONE, K_NONE, +/* 60 */ K_NONE, K_BSLH, K_NONE, K_NONE, K_NONE, K_NONE, K_BKSP, K_NONE, +/* 68 */ K_NONE, KP_1 , K_NONE, KP_4 , KP_7 , K_NONE, K_NONE, K_NONE, +/* 70 */ KP_0 , KP_DOT, KP_2 , KP_5 , KP_6 , KP_8 , K_ESC , K_NUML, +/* 78 */ K_F11 , KP_PLS, KP_3 , KP_MNS, KP_STR, KP_9 , K_SCRL, K_NONE, + K_NONE, K_NONE, K_NONE, K_F7 , K_NONE, K_NONE, K_NONE, K_NONE, + K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, + K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, + K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, + K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, + K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, + K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, + K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, + K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, + K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, + K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, + K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, + K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, + K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE +}; + +#ifdef CONFIG_MAGIC_SYSRQ +unsigned char ps2kbd_sysrq_xlate[] = +{ + 27, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + '`', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '0', '-', '=', '£', 127, 0, + 0, 0, 0, '/', '*', '#', 9, 'q', + 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', + 'p', '[', ']', '\\', 22, 23, 25, '7', + '8', '9', '-', 0, 'a', 's', 'd', 'f', + 'g', 'h', 'j', 'k', 'l', ';', '\'', 13, + '4', '5', '6', '+', 0, 0, 'z', 'x', + 'c', 'v', 'b', 'n', 'm', ',', '.', '/', + 0, 0, '1', '2', '3', 0, 0, ' ', + 0, 0, 0, 0, 0, '0', '.', 10, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; +#endif + +int ps2kbd_pretranslate(unsigned char scancode) +{ + return 1; +} + +int ps2kbd_translate(unsigned char scancode, unsigned char *keycode_p, char *uf_p) +{ + *uf_p = scancode & 0200; + *keycode_p = scancode & 0x7f; + return 1; +} + +static void ps2kbd_key(unsigned int keycode, unsigned int up_flag) +{ + handle_scancode(keycode + (up_flag ? 0x80 : 0)); +} + +static inline void ps2kbd_sendbyte(unsigned char val) +{ + while(!(inb(IOMD_KCTRL) & (1 << 7))); + outb(val, IOMD_KARTTX); +} + +static unsigned char status; +static unsigned char ncodes; +static unsigned char bi; +static unsigned char buffer[4]; + +static inline void ps2kbd_reset(void) +{ + status = 0; + kbd_reset_kdown(); +} + +static void handle_rawcode(int keyval) +{ + int keysym; + + if (keyval > 0x83) { + switch (keyval) { + case KBD_ESCAPEE0: + ncodes = 2; + bi = 0; + break; + case KBD_ESCAPEE1: + ncodes = 3; + bi = 0; + break; + case KBD_BREAK: + status |= CODE_BREAK; + default: + return; + } + } + + if (ncodes) { + buffer[bi++] = keyval; + ncodes -= 1; + if (ncodes) + return; + keysym = K_NONE; + switch (buffer[0] << 8 | buffer[1]) { + case ESCE0(0x11): keysym = K_RALT; break; + case ESCE0(0x14): keysym = K_RCTL; break; + case ESCE0(0x4a): keysym = KP_SLH; break; + case ESCE0(0x5a): keysym = KP_ENT; break; + case ESCE0(0x69): keysym = K_END; break; + case ESCE0(0x6b): keysym = K_LEFT; break; + case ESCE0(0x6c): keysym = K_HOME; break; + case ESCE0(0x70): keysym = K_INS; break; + case ESCE0(0x71): keysym = K_DEL; break; + case ESCE0(0x72): keysym = K_DOWN; break; + case ESCE0(0x74): keysym = K_RGHT; break; + case ESCE0(0x75): keysym = K_UP; break; + case ESCE0(0x7a): keysym = K_PGDN; break; + case ESCE0(0x7c): keysym = K_PRNT; break; + case ESCE0(0x7d): keysym = K_PGUP; break; + case ESCE1(0x14): + if (buffer[2] == 0x77) + keysym = K_BRK; + break; + case ESCE0(0x12): /* ignore escaped shift key */ + status = 0; + return; + } + } else { + bi = 0; + keysym = keycode_translate[keyval]; + } + + if (keysym != K_NONE) + ps2kbd_key(keysym, status & CODE_BREAK); + status = 0; +} + +void ps2kbd_leds(unsigned int leds) +{ + ps2kbd_sendbyte(KBD_SETLEDS); + ps2kbd_sendbyte(leds); + ps2kbd_sendbyte(KBD_SCANENABLE); +} + +static void ps2kbd_rx(int irq, void *dev_id, struct pt_regs *regs) +{ + kbd_pt_regs = regs; + + while (inb(IOMD_KCTRL) & (1 << 5)) + handle_rawcode(inb(IOMD_KARTRX)); + mark_bh(KEYBOARD_BH); +} + +static void ps2kbd_tx(int irq, void *dev_id, struct pt_regs *regs) +{ +} + +__initfunc(int ps2kbd_init_hw(void)) +{ + unsigned long flags; + + save_flags_cli (flags); + if (request_irq (IRQ_KEYBOARDRX, ps2kbd_rx, 0, "keyboard", NULL) != 0) + panic("Could not allocate keyboard receive IRQ!"); + if (request_irq (IRQ_KEYBOARDTX, ps2kbd_tx, 0, "keyboard", NULL) != 0) + panic("Could not allocate keyboard transmit IRQ!"); + disable_irq (IRQ_KEYBOARDTX); + (void)IOMD_KARTRX; + restore_flags (flags); + + printk (KERN_INFO "PS/2 keyboard driver v%d.%02d\n", VERSION/100, VERSION%100); + return 0; +} + diff --git a/drivers/acorn/char/mouse_rpc.c b/drivers/acorn/char/mouse_rpc.c new file mode 100644 index 000000000000..a5c2b2bff5c3 --- /dev/null +++ b/drivers/acorn/char/mouse_rpc.c @@ -0,0 +1,86 @@ +/* + * linux/drivers/char/rpcmouse.c + * + * Copyright (C) 1996-1998 Russell King + * + * This handles the Acorn RiscPCs mouse. We basically have a couple + * of hardware registers that track the sensor count for the X-Y movement + * and another register holding the button state. On every VSYNC interrupt + * we read the complete state and then work out if something has changed. + */ +#include +#include +#include +#include + +#include +#include +#include + +#include "../../char/mouse.h" + +static short old_x, old_y, old_b; +static int mousedev; + +void +mouse_rpc_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + short x, y, dx, dy; + int buttons; + + x = (short)inl(IOMD_MOUSEX); + y = (short)inl(IOMD_MOUSEY); + buttons = (inl (0x800C4000) >> 4) & 7; + + dx = x - old_x; + old_x = x; + dy = y - old_y; + old_y = y; + + if (dx || dy || buttons != old_b) { + busmouse_add_movementbuttons(mousedev, dx, dy, buttons); + old_b = buttons; + } +} + +static struct busmouse rpcmouse = { + 6, "arcmouse", NULL, NULL, 7 +}; + +int +mouse_rpc_init(void) +{ + mousedev = register_busmouse(&rpcmouse); + + if (mousedev < 0) + printk("rpcmouse: could not register mouse driver\n"); + else { + old_x = (short)inl(IOMD_MOUSEX); + old_y = (short)inl(IOMD_MOUSEY); + old_b = (inl (0x800C4000) >> 4) & 7; + if (request_irq(IRQ_VSYNCPULSE, mouse_rpc_irq, SA_SHIRQ, "mouse", &mousedev)) { + printk("rpcmouse: unable to allocate VSYNC interrupt\n"); + unregister_busmouse(mousedev); + mousedev = -1; + } + } + + return mousedev >= 0 ? 0 : -ENODEV; +} + +#ifdef MODULE +int +init_module(void) +{ + return mouse_rpc_init(); +} + +int +cleanup_module(void) +{ + if (mousedev >= 0) { + unregister_busmouse(mousedev); + free_irq(IRQ_VSYNCPULSE, &mousedev); + } +} +#endif diff --git a/drivers/acorn/net/etherh.c b/drivers/acorn/net/etherh.c index 1add274980f4..4f88f6bb4696 100644 --- a/drivers/acorn/net/etherh.c +++ b/drivers/acorn/net/etherh.c @@ -186,7 +186,7 @@ etherh_block_output (struct device *dev, int count, const unsigned char *buf, in if (ei_status.dmaing) { printk ("%s: DMAing conflict in etherh_block_input: " - " DMAstat %d irqlock %d intr %d\n", dev->name, + " DMAstat %d irqlock %d intr %ld\n", dev->name, ei_status.dmaing, ei_status.irqlock, dev->interrupt); return; } @@ -246,7 +246,7 @@ etherh_block_input (struct device *dev, int count, struct sk_buff *skb, int ring if (ei_status.dmaing) { printk ("%s: DMAing conflict in etherh_block_input: " - " DMAstat %d irqlock %d intr %d\n", dev->name, + " DMAstat %d irqlock %d intr %ld\n", dev->name, ei_status.dmaing, ei_status.irqlock, dev->interrupt); return; } @@ -288,7 +288,7 @@ etherh_get_header (struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page) if (ei_status.dmaing) { printk ("%s: DMAing conflict in etherh_get_header: " - " DMAstat %d irqlock %d intr %d\n", dev->name, + " DMAstat %d irqlock %d intr %ld\n", dev->name, ei_status.dmaing, ei_status.irqlock, dev->interrupt); return; } @@ -469,9 +469,9 @@ static void etherh_initdev (ecard_t *ec, struct device *dev) ecard_claim (ec); dev->irq = ec->irq; - dev->mem_end = ec->cld.product; + dev->mem_end = ec->cid.product; - switch (ec->cld.product) { + switch (ec->cid.product) { case PROD_I3_ETHERLAN500: dev->base_addr = ecard_address (ec, ECARD_MEMC, 0) + ETHERH500_NS8390; dev->mem_start = dev->base_addr + ETHERH500_DATAPORT; diff --git a/drivers/acorn/scsi/acornscsi.c b/drivers/acorn/scsi/acornscsi.c index a203bc5c2920..56aafd46784c 100644 --- a/drivers/acorn/scsi/acornscsi.c +++ b/drivers/acorn/scsi/acornscsi.c @@ -148,10 +148,11 @@ #include "../../scsi/hosts.h" #include "../../scsi/constants.h" #include "acornscsi.h" +#include "msgqueue.h" #define VER_MAJOR 2 #define VER_MINOR 0 -#define VER_PATCH 5 +#define VER_PATCH 6 #ifndef ABORT_TAG #define ABORT_TAG 0xd @@ -177,6 +178,8 @@ #define DMAC_WRITE (MODECON_WRITE) #define INIT_SBICDMA (CTRL_DMABURST) +#define scsi_xferred have_data_in + /* * Size of on-board DMA buffer */ @@ -259,6 +262,29 @@ unsigned int dmac_address (unsigned int io_port) dmac_read (io_port, TXADRMD) << 8 | dmac_read (io_port, TXADRLO); } + +static +void acornscsi_dumpdma (AS_Host *host, char *where) +{ + unsigned int mode, addr, len; + + mode = dmac_read (host->dma.io_port, MODECON); + addr = dmac_address (host->dma.io_port); + len = dmac_read (host->dma.io_port, TXCNTHI) << 8 | + dmac_read (host->dma.io_port, TXCNTLO); + + printk ("scsi%d: %s: DMAC %02x @%06x+%04x msk %02x, ", + host->host->host_no, where, + mode, addr, (len + 1) & 0xffff, + dmac_read (host->dma.io_port, MASKREG)); + + printk ("DMA @%06x, ", host->dma.start_addr); + printk ("BH @%p +%04x, ", host->scsi.SCp.ptr, + host->scsi.SCp.this_residual); + printk ("DT @+%04x ST @+%04x", host->dma.transferred, + host->scsi.SCp.scsi_xferred); + printk ("\n"); +} #endif static @@ -345,15 +371,13 @@ void acornscsi_resetcard (AS_Host *host) host->card.page_reg = 0x40; outb (host->card.page_reg, host->card.io_page); -#ifdef USE_DMAC /* setup dmac - uPC71071 */ - dmac_write (host->dma.io_port, INIT, 0); - dmac_write (host->dma.io_port, INIT, INIT_8BIT); - dmac_write (host->dma.io_port, CHANNEL, CHANNEL_0); - dmac_write (host->dma.io_port, DEVCON0, INIT_DEVCON0); - dmac_write (host->dma.io_port, DEVCON1, INIT_DEVCON1); -#else - dmac_write (host->dma.io_port, INIT, 0); + dmac_write(host->dma.io_port, INIT, 0); +#ifdef USE_DMAC + dmac_write(host->dma.io_port, INIT, INIT_8BIT); + dmac_write(host->dma.io_port, CHANNEL, CHANNEL_0); + dmac_write(host->dma.io_port, DEVCON0, INIT_DEVCON0); + dmac_write(host->dma.io_port, DEVCON1, INIT_DEVCON1); #endif host->SCpnt = NULL; @@ -517,31 +541,6 @@ char acornscsi_target (AS_Host *host) return 'H'; } -#ifdef USE_DMAC -static -void acornscsi_dumpdma (AS_Host *host, char *where) -{ - unsigned int mode, addr, len; - - mode = dmac_read (host->dma.io_port, MODECON); - addr = dmac_address (host->dma.io_port); - len = dmac_read (host->dma.io_port, TXCNTHI) << 8 | - dmac_read (host->dma.io_port, TXCNTLO); - - printk ("scsi%d: %s: DMAC %02x @%06x+%04x msk %02x, ", - host->host->host_no, where, - mode, addr, (len + 1) & 0xffff, - dmac_read (host->dma.io_port, MASKREG)); - - printk ("DMA @%06x, ", host->dma.start_addr); - printk ("BH @%p +%04x, ", host->scsi.SCp.ptr, - host->scsi.SCp.this_residual); - printk ("DT @+%04x ST @+%04x", host->dma.transferred, - host->scsi.SCp.have_data_in); - printk ("\n"); -} -#endif - /* * Prototype: cmdtype_t acornscsi_cmdtype (int command) * Purpose : differentiate READ from WRITE from other commands @@ -1051,7 +1050,7 @@ void acornscsi_dma_cleanup (AS_Host *host) host->dma.xfer_setup = 0; #if (DEBUG & DEBUG_DMA) - DBG(host->SCpnt, acornscsi_dumpdma (host, "clup")); + DBG(host->SCpnt, acornscsi_dumpdma(host, "cupi")); #endif /* @@ -1068,6 +1067,9 @@ void acornscsi_dma_cleanup (AS_Host *host) * Update SCSI pointers */ acornscsi_data_updateptr (host, &host->scsi.SCp, transferred); +#if (DEBUG & DEBUG_DMA) + DBG(host->SCpnt, acornscsi_dumpdma(host, "cupo")); +#endif } } @@ -1193,15 +1195,15 @@ void acornscsi_dma_adjust (AS_Host *host) /* * Calculate correct DMA address - DMA is ahead of SCSI bus while * writing. - * host->scsi.SCp.have_data_in is the number of bytes + * host->scsi.SCp.scsi_xferred is the number of bytes * actually transferred to/from the SCSI bus. * host->dma.transferred is the number of bytes transferred * over DMA since host->dma.start_addr was last set. * - * real_dma_addr = host->dma.start_addr + host->scsi.SCp.have_data_in + * real_dma_addr = host->dma.start_addr + host->scsi.SCp.scsi_xferred * - host->dma.transferred */ - transferred = host->scsi.SCp.have_data_in - host->dma.transferred; + transferred = host->scsi.SCp.scsi_xferred - host->dma.transferred; if (transferred < 0) printk ("scsi%d.%c: Ack! DMA write correction %ld < 0!\n", host->host->host_no, acornscsi_target (host), transferred); @@ -1259,8 +1261,8 @@ static void acornscsi_sendmessage (AS_Host *host) { unsigned int message_length = msgqueue_msglength (&host->scsi.msgs); - int msglen; - char *msg; + int msgnr; + struct message *msg; #if (DEBUG & DEBUG_MESSAGES) printk ("scsi%d.%c: sending message ", @@ -1280,12 +1282,12 @@ void acornscsi_sendmessage (AS_Host *host) case 1: acornscsi_sbic_issuecmd (host, CMND_XFERINFO | CMND_SBT); - msg = msgqueue_getnextmsg (&host->scsi.msgs, &msglen); + msg = msgqueue_getmsg(&host->scsi.msgs, 0); while ((sbic_arm_read (host->scsi.io_port, ASR) & ASR_DBR) == 0); - sbic_arm_write (host->scsi.io_port, DATA, msg[0]); - host->scsi.last_message = msg[0]; + sbic_arm_write (host->scsi.io_port, DATA, msg->msg[0]); + host->scsi.last_message = msg->msg[0]; #if (DEBUG & DEBUG_MESSAGES) - print_msg (msg); + print_msg(msg->msg); #endif break; @@ -1303,21 +1305,22 @@ void acornscsi_sendmessage (AS_Host *host) sbic_arm_writenext (host->scsi.io_port, message_length); acornscsi_sbic_issuecmd (host, CMND_XFERINFO); - while ((msg = msgqueue_getnextmsg (&host->scsi.msgs, &msglen)) != NULL) { + msgnr = 0; + while ((msg = msgqueue_getmsg(&host->scsi.msgs, msgnr++)) != NULL) { unsigned int asr, i; #if (DEBUG & DEBUG_MESSAGES) print_msg (msg); #endif - for (i = 0; i < msglen;) { + for (i = 0; i < msg->length;) { asr = sbic_arm_read (host->scsi.io_port, ASR); if (asr & ASR_DBR) - sbic_arm_write (host->scsi.io_port, DATA, msg[i++]); + sbic_arm_write (host->scsi.io_port, DATA, msg->msg[i++]); if (asr & ASR_INT) break; } - host->scsi.last_message = msg[0]; - if (msg[0] == EXTENDED_MESSAGE) - host->scsi.last_message |= msg[2] << 8; + host->scsi.last_message = msg->msg[0]; + if (msg->msg[0] == EXTENDED_MESSAGE) + host->scsi.last_message |= msg->msg[2] << 8; if (asr & ASR_INT) break; } @@ -1401,10 +1404,10 @@ void acornscsi_message (AS_Host *host) } while (msgidx < msglen); #if (DEBUG & DEBUG_MESSAGES) - printk (KERN_DEBUG "scsi%d.%c: message in: ", + printk("scsi%d.%c: message in: ", host->host->host_no, acornscsi_target (host)); - print_msg (message); - printk ("\n"); + print_msg(message); + printk("\n"); #endif if (host->scsi.phase == PHASE_RECONNECTED) { @@ -1424,9 +1427,11 @@ void acornscsi_message (AS_Host *host) case ABORT: case ABORT_TAG: case COMMAND_COMPLETE: - if (host->scsi.phase != PHASE_STATUSIN) - printk (KERN_ERR "scsi%d.%c: command complete following non-status in phase?\n", + if (host->scsi.phase != PHASE_STATUSIN) { + printk(KERN_ERR "scsi%d.%c: command complete following non-status in phase?\n", host->host->host_no, acornscsi_target (host)); + acornscsi_dumplog(host, host->SCpnt->target); + } host->scsi.phase = PHASE_DONE; host->scsi.SCp.Message = message[0]; break; @@ -1594,7 +1599,7 @@ void acornscsi_message (AS_Host *host) */ if (0) { #if (DEBUG & DEBUG_LINK) - printk (KERN_DEBUG "scsi%d.%c: lun %d tag %d linked command complete\n", + printk("scsi%d.%c: lun %d tag %d linked command complete\n", host->host->host_no, acornscsi_target(host), host->SCpnt->tag); #endif /* @@ -1704,7 +1709,7 @@ int acornscsi_starttransfer (AS_Host *host) return 0; } - residual = host->SCpnt->request_bufflen - host->scsi.SCp.have_data_in; + residual = host->SCpnt->request_bufflen - host->scsi.SCp.scsi_xferred; sbic_arm_write (host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer); sbic_arm_writenext (host->scsi.io_port, residual >> 16); @@ -1833,7 +1838,7 @@ int acornscsi_reconnect_finish (AS_Host *host) printk ("\n"); #endif - host->dma.transferred = host->scsi.SCp.have_data_in; + host->dma.transferred = host->scsi.SCp.scsi_xferred; return host->SCpnt != NULL; } @@ -1935,7 +1940,7 @@ intr_ret_t acornscsi_sbicintr (AS_Host *host, int in_irq) /* BUS FREE -> SELECTION */ host->scsi.phase = PHASE_CONNECTED; msgqueue_flush (&host->scsi.msgs); - host->dma.transferred = host->scsi.SCp.have_data_in; + host->dma.transferred = host->scsi.SCp.scsi_xferred; /* 33C93 gives next interrupt indicating bus phase */ asr = sbic_arm_read (host->scsi.io_port, ASR); if (!(asr & ASR_INT)) @@ -2178,7 +2183,7 @@ intr_ret_t acornscsi_sbicintr (AS_Host *host, int in_irq) case 0x4b: /* -> PHASE_STATUSIN */ case 0x1b: /* -> PHASE_STATUSIN */ /* DATA IN -> STATUS */ - host->scsi.SCp.have_data_in = host->SCpnt->request_bufflen - + host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - acornscsi_sbic_xfcount (host); acornscsi_dma_stop (host); acornscsi_readstatusbyte (host); @@ -2188,7 +2193,7 @@ intr_ret_t acornscsi_sbicintr (AS_Host *host, int in_irq) case 0x1e: /* -> PHASE_MSGOUT */ case 0x4e: /* -> PHASE_MSGOUT */ /* DATA IN -> MESSAGE OUT */ - host->scsi.SCp.have_data_in = host->SCpnt->request_bufflen - + host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - acornscsi_sbic_xfcount (host); acornscsi_dma_stop (host); acornscsi_sendmessage (host); @@ -2197,7 +2202,7 @@ intr_ret_t acornscsi_sbicintr (AS_Host *host, int in_irq) case 0x1f: /* message in */ case 0x4f: /* message in */ /* DATA IN -> MESSAGE IN */ - host->scsi.SCp.have_data_in = host->SCpnt->request_bufflen - + host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - acornscsi_sbic_xfcount (host); acornscsi_dma_stop (host); acornscsi_message (host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */ @@ -2223,7 +2228,7 @@ intr_ret_t acornscsi_sbicintr (AS_Host *host, int in_irq) case 0x4b: /* -> PHASE_STATUSIN */ case 0x1b: /* -> PHASE_STATUSIN */ /* DATA OUT -> STATUS */ - host->scsi.SCp.have_data_in = host->SCpnt->request_bufflen - + host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - acornscsi_sbic_xfcount (host); acornscsi_dma_stop (host); acornscsi_dma_adjust (host); @@ -2234,7 +2239,7 @@ intr_ret_t acornscsi_sbicintr (AS_Host *host, int in_irq) case 0x1e: /* -> PHASE_MSGOUT */ case 0x4e: /* -> PHASE_MSGOUT */ /* DATA OUT -> MESSAGE OUT */ - host->scsi.SCp.have_data_in = host->SCpnt->request_bufflen - + host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - acornscsi_sbic_xfcount (host); acornscsi_dma_stop (host); acornscsi_dma_adjust (host); @@ -2244,7 +2249,7 @@ intr_ret_t acornscsi_sbicintr (AS_Host *host, int in_irq) case 0x1f: /* message in */ case 0x4f: /* message in */ /* DATA OUT -> MESSAGE IN */ - host->scsi.SCp.have_data_in = host->SCpnt->request_bufflen - + host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - acornscsi_sbic_xfcount (host); acornscsi_dma_stop (host); acornscsi_dma_adjust (host); @@ -2426,7 +2431,7 @@ int acornscsi_queuecmd (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) SCpnt->tag = 0; SCpnt->SCp.phase = (int)acornscsi_datadirection (SCpnt->cmnd[0]); SCpnt->SCp.sent_command = 0; - SCpnt->SCp.have_data_in = 0; + SCpnt->SCp.scsi_xferred = 0; SCpnt->SCp.Status = 0; SCpnt->SCp.Message = 0; @@ -2592,7 +2597,7 @@ int acornscsi_reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags) SCpnt->result = DID_RESET << 16; SCpnt->scsi_done (SCpnt); } -while (1); + return SCSI_RESET_BUS_RESET | SCSI_RESET_HOST_RESET | SCSI_RESET_SUCCESS; } @@ -2658,6 +2663,9 @@ int acornscsi_detect(Scsi_Host_Template * tpnt) host->dma.io_port = instance->io_port + 0xc00; host->dma.io_intr_clear = POD_SPACE(instance->io_port) + 0x800; + ecs[count]->irqaddr = (char *)ioaddr(host->card.io_intr); + ecs[count]->irqmask = 0x0a; + request_region (instance->io_port + 0x800, 2, "acornscsi(sbic)"); request_region (host->card.io_intr, 1, "acornscsi(intr)"); request_region (host->card.io_page, 1, "acornscsi(page)"); diff --git a/drivers/acorn/scsi/cumana_2.c b/drivers/acorn/scsi/cumana_2.c index 38b78f721bda..797eaae066d9 100644 --- a/drivers/acorn/scsi/cumana_2.c +++ b/drivers/acorn/scsi/cumana_2.c @@ -156,8 +156,6 @@ cumanascsi_2_intr(int irq, void *dev_id, struct pt_regs *regs) static void cumanascsi_2_invalidate(char *addr, long len, fasdmadir_t direction) { - unsigned int page; - if (direction == DMA_OUT) dma_cache_wback((unsigned long)addr, (unsigned long)len); else diff --git a/drivers/acorn/scsi/eesox.c b/drivers/acorn/scsi/eesox.c index f58fad4a9840..301b83d05af3 100644 --- a/drivers/acorn/scsi/eesox.c +++ b/drivers/acorn/scsi/eesox.c @@ -164,8 +164,6 @@ eesoxscsi_intr(int irq, void *dev_id, struct pt_regs *regs) static void eesoxscsi_invalidate(char *addr, long len, fasdmadir_t direction) { - unsigned int page; - if (direction == DMA_OUT) dma_cache_wback((unsigned long)addr, (unsigned long)len); else diff --git a/drivers/acorn/scsi/powertec.c b/drivers/acorn/scsi/powertec.c index db9ec0a8f949..caae8a8ba040 100644 --- a/drivers/acorn/scsi/powertec.c +++ b/drivers/acorn/scsi/powertec.c @@ -152,8 +152,6 @@ powertecscsi_intr(int irq, void *dev_id, struct pt_regs *regs) static void powertecscsi_invalidate(char *addr, long len, fasdmadir_t direction) { - unsigned int page; - if (direction == DMA_OUT) dma_cache_wback((unsigned long)addr, (unsigned long)len); else diff --git a/drivers/char/serial.c b/drivers/char/serial.c index 59c2f3f122e5..d207041c9344 100644 --- a/drivers/char/serial.c +++ b/drivers/char/serial.c @@ -154,7 +154,7 @@ #endif static char *serial_name = "Serial driver"; -static char *serial_version = "4.26"; +static char *serial_version = "4.27"; static DECLARE_TASK_QUEUE(tq_serial); @@ -180,7 +180,7 @@ static struct console sercons; static unsigned detect_uart_irq (struct serial_state * state); static void autoconfig(struct serial_state * info); -static void change_speed(struct async_struct *info); +static void change_speed(struct async_struct *info, struct termios *old); static void rs_wait_until_sent(struct tty_struct *tty, int timeout); /* @@ -1110,7 +1110,7 @@ static int startup(struct async_struct * info) /* * and set the speed of the serial port */ - change_speed(info); + change_speed(info, 0); info->flags |= ASYNC_INITIALIZED; restore_flags(flags); @@ -1233,7 +1233,8 @@ static void shutdown(struct async_struct * info) * This routine is called to set the UART divisor registers to match * the specified baud rate for a serial port. */ -static void change_speed(struct async_struct *info) +static void change_speed(struct async_struct *info, + struct termios *old_termios) { unsigned short port; int quot = 0, baud_base, baud; @@ -1284,7 +1285,25 @@ static void change_speed(struct async_struct *info) else if (baud) quot = baud_base / baud; } - /* If the quotient is ever zero, default to 9600 bps */ + /* If the quotient is zero refuse the change */ + if (!quot && old_termios) { + info->tty->termios->c_cflag &= ~CBAUD; + info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD); + baud = tty_get_baud_rate(info->tty); + if (!baud) + baud = 9600; + if (baud == 38400 && + ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) + quot = info->state->custom_divisor; + else { + if (baud == 134) + /* Special case since 134 is really 134.5 */ + quot = (2*baud_base / 269); + else if (baud) + quot = baud_base / baud; + } + } + /* As a last resort, if the quotient is zero, default to 9600 bps */ if (!quot) quot = baud_base / 9600; info->quot = quot; @@ -1653,7 +1672,7 @@ static int set_serial_info(struct async_struct * info, return -EPERM; state->flags = ((state->flags & ~ASYNC_USR_MASK) | (new_serial.flags & ASYNC_USR_MASK)); - info->flags = ((state->flags & ~ASYNC_USR_MASK) | + info->flags = ((info->flags & ~ASYNC_USR_MASK) | (info->flags & ASYNC_USR_MASK)); state->custom_divisor = new_serial.custom_divisor; goto check_and_exit; @@ -1733,7 +1752,7 @@ check_and_exit: info->tty->alt_speed = 230400; if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) info->tty->alt_speed = 460800; - change_speed(info); + change_speed(info, 0); } } else retval = startup(info); @@ -2003,7 +2022,6 @@ static int set_multiport_struct(struct async_struct * info, "driver!!\n"); } } - return 0; } #endif @@ -2150,7 +2168,7 @@ static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) == RELEVANT_IFLAG(old_termios->c_iflag))) return; - change_speed(info); + change_speed(info, old_termios); /* Handle transition to B0 status */ if ((old_termios->c_cflag & CBAUD) && @@ -2645,13 +2663,13 @@ static int rs_open(struct tty_struct *tty, struct file * filp) *tty->termios = info->state->normal_termios; else *tty->termios = info->state->callout_termios; - change_speed(info); + change_speed(info, 0); } #ifdef CONFIG_SERIAL_CONSOLE if (sercons.cflag && sercons.index == line) { tty->termios->c_cflag = sercons.cflag; sercons.cflag = 0; - change_speed(info); + change_speed(info, 0); } #endif info->session = current->session; diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 6a1d1c6495c3..9165d0ffbbcc 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c @@ -52,7 +52,6 @@ void tty_wait_until_sent(struct tty_struct * tty, long timeout) if (!tty->driver.chars_in_buffer) return; add_wait_queue(&tty->write_wait, &wait); - current->counter = 0; /* make us low-priority */ if (!timeout) timeout = MAX_SCHEDULE_TIMEOUT; do { diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c index b8e9936f82e8..34edf220005a 100644 --- a/drivers/net/3c505.c +++ b/drivers/net/3c505.c @@ -266,12 +266,12 @@ static inline unsigned int backlog_next(unsigned int n) static inline int get_status(unsigned int base_addr) { - int timeout = jiffies + 10; + int timeout = jiffies + 10*HZ/100; register int stat1; do { stat1 = inb_status(base_addr); - } while (stat1 != inb_status(base_addr) && jiffies < timeout); - if (jiffies >= timeout) + } while (stat1 != inb_status(base_addr) && time_before(jiffies, timeout)); + if (time_after_eq(jiffies, timeout)) TIMEOUT_MSG(__LINE__); return stat1; } @@ -296,23 +296,23 @@ inline static void adapter_reset(struct device *dev) if (inb_status(dev->base_addr) & ACRF) { do { inb_command(dev->base_addr); - timeout = jiffies + 2; - while ((jiffies <= timeout) && !(inb_status(dev->base_addr) & ACRF)); + timeout = jiffies + 2*HZ/100; + while (time_before_eq(jiffies, timeout) && !(inb_status(dev->base_addr) & ACRF)); } while (inb_status(dev->base_addr) & ACRF); set_hsf(dev, HSF_PCB_NAK); } outb_control(adapter->hcr_val | ATTN | DIR, dev); - timeout = jiffies + 1; - while (jiffies <= timeout); + timeout = jiffies + 1*HZ/100; + while (time_before_eq(jiffies, timeout)); outb_control(adapter->hcr_val & ~ATTN, dev); - timeout = jiffies + 1; - while (jiffies <= timeout); + timeout = jiffies + 1*HZ/100; + while (time_before_eq(jiffies, timeout)); outb_control(adapter->hcr_val | FLSH, dev); - timeout = jiffies + 1; - while (jiffies <= timeout); + timeout = jiffies + 1*HZ/100; + while (time_before_eq(jiffies, timeout)); outb_control(adapter->hcr_val & ~FLSH, dev); - timeout = jiffies + 1; - while (jiffies <= timeout); + timeout = jiffies + 1*HZ/100; + while (time_before_eq(jiffies, timeout)); outb_control(orig_hcr, dev); if (!start_receive(dev, &adapter->tx_pcb)) @@ -326,7 +326,7 @@ inline static void adapter_reset(struct device *dev) static inline void check_3c505_dma(struct device *dev) { elp_device *adapter = dev->priv; - if (adapter->dmaing && (jiffies > (adapter->current_dma.start_time + 10))) { + if (adapter->dmaing && time_after(jiffies, adapter->current_dma.start_time + 10)) { unsigned long flags, f; printk("%s: DMA %s timed out, %d bytes left\n", dev->name, adapter->current_dma.direction ? "download" : "upload", get_dma_residue(dev->dma)); save_flags(flags); @@ -350,7 +350,7 @@ static inline unsigned int send_pcb_slow(unsigned int base_addr, unsigned char b { unsigned int timeout; outb_command(byte, base_addr); - for (timeout = jiffies + 5; jiffies < timeout;) { + for (timeout = jiffies + 5*HZ/100; time_before(jiffies, timeout);) { if (inb_status(base_addr) & HCRE) return FALSE; } @@ -448,7 +448,7 @@ static int send_pcb(struct device *dev, pcb_struct * pcb) /* now wait for the acknowledgement */ sti(); - for (timeout = jiffies + 5; jiffies < timeout;) { + for (timeout = jiffies + 5*HZ/100; time_before(jiffies, timeout);) { switch (GET_ASF(dev->base_addr)) { case ASF_PCB_ACK: adapter->send_pcb_semaphore = 0; @@ -499,18 +499,18 @@ static int receive_pcb(struct device *dev, pcb_struct * pcb) set_hsf(dev, 0); /* get the command code */ - timeout = jiffies + 2; - while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && jiffies < timeout); - if (jiffies >= timeout) { + timeout = jiffies + 2*HZ/100; + while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout)); + if (time_after_eq(jiffies, timeout)) { TIMEOUT_MSG(__LINE__); return FALSE; } pcb->command = inb_command(dev->base_addr); /* read the data length */ - timeout = jiffies + 3; - while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && jiffies < timeout); - if (jiffies >= timeout) { + timeout = jiffies + 3*HZ/100; + while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout)); + if (time_after_eq(jiffies, timeout)) { TIMEOUT_MSG(__LINE__); printk("%s: status %02x\n", dev->name, stat); return FALSE; @@ -738,8 +738,8 @@ static void elp_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr) /* * receive a PCB from the adapter */ - timeout = jiffies + 3; - while ((inb_status(dev->base_addr) & ACRF) != 0 && jiffies < timeout) { + timeout = jiffies + 3*HZ/100; + while ((inb_status(dev->base_addr) & ACRF) != 0 && time_before(jiffies, timeout)) { if (receive_pcb(dev, &adapter->irx_pcb)) { switch (adapter->irx_pcb.command) { case 0: @@ -971,8 +971,8 @@ static int elp_open(struct device *dev) printk("%s: couldn't send memory configuration command\n", dev->name); else { int timeout = jiffies + TIMEOUT; - while (adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] == 0 && jiffies < timeout); - if (jiffies >= timeout) + while (adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] == 0 && time_before(jiffies, timeout)); + if (time_after_eq(jiffies, timeout)) TIMEOUT_MSG(__LINE__); } @@ -990,8 +990,8 @@ static int elp_open(struct device *dev) printk("%s: couldn't send 82586 configure command\n", dev->name); else { int timeout = jiffies + TIMEOUT; - while (adapter->got[CMD_CONFIGURE_82586] == 0 && jiffies < timeout); - if (jiffies >= timeout) + while (adapter->got[CMD_CONFIGURE_82586] == 0 && time_before(jiffies, timeout)); + if (time_after_eq(jiffies, timeout)) TIMEOUT_MSG(__LINE__); } @@ -1177,8 +1177,8 @@ static struct net_device_stats *elp_get_stats(struct device *dev) printk("%s: couldn't send get statistics command\n", dev->name); else { int timeout = jiffies + TIMEOUT; - while (adapter->got[CMD_NETWORK_STATISTICS] == 0 && jiffies < timeout); - if (jiffies >= timeout) { + while (adapter->got[CMD_NETWORK_STATISTICS] == 0 && time_before(jiffies, timeout)); + if (time_after_eq(jiffies, timeout)) { TIMEOUT_MSG(__LINE__); return &adapter->stats; } @@ -1270,8 +1270,8 @@ static void elp_set_mc_list(struct device *dev) printk("%s: couldn't send set_multicast command\n", dev->name); else { int timeout = jiffies + TIMEOUT; - while (adapter->got[CMD_LOAD_MULTICAST_LIST] == 0 && jiffies < timeout); - if (jiffies >= timeout) { + while (adapter->got[CMD_LOAD_MULTICAST_LIST] == 0 && time_before(jiffies, timeout)); + if (time_after_eq(jiffies, timeout)) { TIMEOUT_MSG(__LINE__); } } @@ -1294,8 +1294,8 @@ static void elp_set_mc_list(struct device *dev) printk("%s: couldn't send 82586 configure command\n", dev->name); else { int timeout = jiffies + TIMEOUT; - while (adapter->got[CMD_CONFIGURE_82586] == 0 && jiffies < timeout); - if (jiffies >= timeout) + while (adapter->got[CMD_CONFIGURE_82586] == 0 && time_before(jiffies, timeout)); + if (time_after_eq(jiffies, timeout)) TIMEOUT_MSG(__LINE__); } } @@ -1371,8 +1371,8 @@ __initfunc(static int elp_sense(struct device *dev)) if (orig_HSR & DIR) { /* If HCR.DIR is up, we pull it down. HSR.DIR should follow. */ outb(0, dev->base_addr + PORT_CONTROL); - timeout = jiffies + 30; - while (jiffies < timeout); + timeout = jiffies + 30*HZ/100; + while (time_before(jiffies, timeout)); restore_flags(flags); if (inb_status(addr) & DIR) { if (elp_debug > 0) @@ -1382,8 +1382,8 @@ __initfunc(static int elp_sense(struct device *dev)) } else { /* If HCR.DIR is down, we pull it up. HSR.DIR should follow. */ outb(DIR, dev->base_addr + PORT_CONTROL); - timeout = jiffies + 30; - while (jiffies < timeout); + timeout = jiffies + 30*HZ/100; + while (time_before(jiffies, timeout)); restore_flags(flags); if (!(inb_status(addr) & DIR)) { if (elp_debug > 0) @@ -1479,13 +1479,13 @@ __initfunc(int elplus_probe(struct device *dev)) /* First try to write just one byte, to see if the card is * responding at all normally. */ - timeout = jiffies + 5; + timeout = jiffies + 5*HZ/100; okay = 0; - while (jiffies < timeout && !(inb_status(dev->base_addr) & HCRE)); + while (time_before(jiffies, timeout) && !(inb_status(dev->base_addr) & HCRE)); if ((inb_status(dev->base_addr) & HCRE)) { outb_command(0, dev->base_addr); /* send a spurious byte */ - timeout = jiffies + 5; - while (jiffies < timeout && !(inb_status(dev->base_addr) & HCRE)); + timeout = jiffies + 5*HZ/100; + while (time_before(jiffies, timeout) && !(inb_status(dev->base_addr) & HCRE)); if (inb_status(dev->base_addr) & HCRE) okay = 1; } @@ -1499,8 +1499,8 @@ __initfunc(int elplus_probe(struct device *dev)) * Give it the benefit of the doubt for 10 seconds. */ printk("assuming 3c505 still starting\n"); - timeout = jiffies + 10 * HZ; - while (jiffies < timeout && (inb_status(dev->base_addr) & 7)); + timeout = jiffies + 10*HZ; + while (time_before(jiffies, timeout) && (inb_status(dev->base_addr) & 7)); if (inb_status(dev->base_addr) & 7) { printk("%s: 3c505 failed to start\n", dev->name); } else { diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index 58a44182e105..2b79709aaca7 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -63,6 +63,7 @@ static char *version = "3c509.c:1.12 6/4/97 becker@cesdis.gsfc.nasa.gov\n"; #include #include #include +#include #ifdef EL3_DEBUG int el3_debug = EL3_DEBUG; @@ -407,7 +408,7 @@ el3_open(struct device *dev) /* Set the spinlock before grabbing IRQ! */ ((struct el3_private *)dev->priv)->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; - if (request_irq(dev->irq, &el3_interrupt, 0, "3c509", dev)) { + if (request_irq(dev->irq, &el3_interrupt, 0, dev->name, dev)) { return -EAGAIN; } @@ -526,10 +527,21 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev) if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) printk("%s: Transmitter access conflict.\n", dev->name); else { - unsigned long flags; - - /* Spin on the lock, until we're clear of an IRQ */ - spin_lock_irqsave(&lp->lock, flags); + /* + * We lock the driver against other processors. Note + * we don't need to lock versus the IRQ as we suspended + * that. This means that we lose the ability to take + * an RX during a TX upload. That sucks a bit with SMP + * on an original 3c509 (2K buffer) + * + * Using disable_irq stops us crapping on other + * time sensitive devices. + */ + +#ifdef __SMP__ + disable_irq(dev->irq); + spin_lock(&lp->lock); +#endif /* Put out the doubleword header... */ outw(skb->len, ioaddr + TX_FIFO); @@ -547,8 +559,10 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev) } else /* Interrupt us when the FIFO has room for max-sized packet. */ outw(SetTxThreshold + 1536, ioaddr + EL3_CMD); - - spin_unlock_irqrestore(&lp->lock, flags); +#ifdef __SMP__ + spin_unlock(&lp->lock); + enable_irq(dev->irq); +#endif } dev_kfree_skb (skb); @@ -658,10 +672,14 @@ el3_get_stats(struct device *dev) struct el3_private *lp = (struct el3_private *)dev->priv; unsigned long flags; - save_flags(flags); - cli(); + /* + * This is fast enough not to bother with disable IRQ + * stuff. + */ + + spin_lock_irqsave(&lp->lock, flags); update_stats(dev); - restore_flags(flags); + spin_unlock_irqrestore(&lp->lock, flags); return &lp->stats; } @@ -683,13 +701,13 @@ static void update_stats(struct device *dev) EL3WINDOW(6); lp->stats.tx_carrier_errors += inb(ioaddr + 0); lp->stats.tx_heartbeat_errors += inb(ioaddr + 1); - /* Multiple collisions. */ inb(ioaddr + 2); - lp->stats.collisions += inb(ioaddr + 3); - lp->stats.tx_window_errors += inb(ioaddr + 4); - lp->stats.rx_fifo_errors += inb(ioaddr + 5); - lp->stats.tx_packets += inb(ioaddr + 6); - /* Rx packets */ inb(ioaddr + 7); - /* Tx deferrals */ inb(ioaddr + 8); + /* Multiple collisions. */ inb(ioaddr + 2); + lp->stats.collisions += inb(ioaddr + 3); + lp->stats.tx_window_errors += inb(ioaddr + 4); + lp->stats.rx_fifo_errors += inb(ioaddr + 5); + lp->stats.tx_packets += inb(ioaddr + 6); + /* Rx packets */ inb(ioaddr + 7); + /* Tx deferrals */ inb(ioaddr + 8); inw(ioaddr + 10); /* Total Rx and Tx octets. */ inw(ioaddr + 12); diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c index b74ca51e69c2..80743eaba4cd 100644 --- a/drivers/net/3c515.c +++ b/drivers/net/3c515.c @@ -39,16 +39,8 @@ static int max_interrupt_work = 20; #define RX_RING_SIZE 16 #define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ -#ifdef MODULE -#ifdef MODVERSIONS -#include -#endif #include #include -#else -#define MOD_INC_USE_COUNT -#define MOD_DEC_USE_COUNT -#endif #include #include @@ -67,12 +59,9 @@ static int max_interrupt_work = 20; #include #include #include -#if (LINUX_VERSION_CODE >= 0x10344) + #define NEW_MULTICAST #include -#else -#define udelay(microsec) do { int _i = 4*microsec; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0) -#endif /* Kernel version compatibility functions. */ #define RUN_AT(x) (jiffies + (x)) diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c index 968168d012aa..13bf1028a5a2 100644 --- a/drivers/net/3c523.c +++ b/drivers/net/3c523.c @@ -359,7 +359,7 @@ void alloc586(struct device *dev) DELAY(2); p->scp = (struct scp_struct *) (p->base + SCP_DEFAULT_ADDRESS); - p->scb = (struct scb_struct *) (dev->mem_start); + p->scb = (struct scb_struct *) phys_to_virt(dev->mem_start); p->iscp = (struct iscp_struct *) ((char *) p->scp - sizeof(struct iscp_struct)); memset((char *) p->iscp, 0, sizeof(struct iscp_struct)); @@ -523,7 +523,7 @@ __initfunc(int elmc_probe(struct device *dev)) Which we don't care much about here. We'll just tell Linux that we're using 16K. MCA won't permit adress space conflicts caused by not mapping the other 8K. */ - dev->mem_start = phys_to_virt(shm_table[(status & ELMC_STATUS_MEMORY_SELECT) >> 3]); + dev->mem_start = shm_table[(status & ELMC_STATUS_MEMORY_SELECT) >> 3]; /* We're using MCA, so it's a given that the information about memory size is correct. The Crynwr drivers do something like this. */ @@ -531,7 +531,7 @@ __initfunc(int elmc_probe(struct device *dev)) elmc_id_reset586(); /* seems like a good idea before checking it... */ size = 0x4000; /* check for 16K mem */ - if (!check586(dev, (char *) dev->mem_start, size)) { + if (!check586(dev, (char *) phys_to_virt(dev->mem_start), size)) { printk("%s: memprobe, Can't find memory at 0x%lx!\n", dev->name, dev->mem_start); release_region(dev->base_addr, ELMC_IO_EXTENT); @@ -539,7 +539,7 @@ __initfunc(int elmc_probe(struct device *dev)) } dev->mem_end = dev->mem_start + size; /* set mem_end showed by 'ifconfig' */ - ((struct priv *) (dev->priv))->base = dev->mem_start + size - 0x01000000; + ((struct priv *) (dev->priv))->base = phys_to_virt(dev->mem_start + size - 0x01000000); alloc586(dev); elmc_id_reset586(); /* make sure it doesn't generate spurious ints */ @@ -550,8 +550,7 @@ __initfunc(int elmc_probe(struct device *dev)) /* dump all the assorted information */ printk("%s: IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->name, dev->irq, dev->if_port ? "ex" : "in", - virt_to_phys(dev->mem_start), - virt_to_phys(dev->mem_end - 1)); + dev->mem_start, dev->mem_end - 1); /* The hardware address for the 3c523 is stored in the first six bytes of the IO address. */ @@ -628,7 +627,7 @@ static int init586(struct device *dev) s = jiffies; /* warning: only active with interrupts on !! */ while (!(cfg_cmd->cmd_status & STAT_COMPL)) { - if (jiffies - s > 30) + if (jiffies - s > 30*HZ/100) break; } @@ -654,7 +653,7 @@ static int init586(struct device *dev) s = jiffies; while (!(ias_cmd->cmd_status & STAT_COMPL)) { - if (jiffies - s > 30) + if (jiffies - s > 30*HZ/100) break; } @@ -679,7 +678,7 @@ static int init586(struct device *dev) s = jiffies; while (!(tdr_cmd->cmd_status & STAT_COMPL)) { - if (jiffies - s > 30) { + if (jiffies - s > 30*HZ/100) { printk("%s: %d Problems while running the TDR.\n", dev->name, __LINE__); result = 1; break; @@ -768,7 +767,7 @@ static int init586(struct device *dev) elmc_id_attn586(); s = jiffies; while (!(mc_cmd->cmd_status & STAT_COMPL)) { - if (jiffies - s > 30) + if (jiffies - s > 30*HZ/100) break; } if (!(mc_cmd->cmd_status & STAT_COMPL)) { diff --git a/drivers/net/Makefile b/drivers/net/Makefile index c89c3be8fb74..096fc998fbc2 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -5,7 +5,7 @@ SUB_DIRS := MOD_SUB_DIRS := $(SUB_DIRS) -ALL_SUB_DIRS := $(SUB_DIRS) hamradio +ALL_SUB_DIRS := $(SUB_DIRS) hamradio irda L_TARGET := net.a L_OBJS := auto_irq.o @@ -752,6 +752,16 @@ else endif endif +ifeq ($(CONFIG_COSA),y) +L_OBJS += cosa.o +CONFIG_SYNCPPP_BUILTIN = y +else + ifeq ($(CONFIG_COSA),m) + CONFIG_SYNCPPP_MODULE = y + M_OBJS += cosa.o + endif +endif + # If anything built-in uses syncppp, then build it into the kernel also. # If not, but a module uses it, build as a module. @@ -1029,6 +1039,14 @@ else endif endif +ifeq ($(CONFIG_IRDA),y) +SUB_DIRS += irda +else + ifeq ($(CONFIG_IRDA),m) + MOD_SUB_DIRS += irda + endif +endif + include $(TOPDIR)/Rules.make clean: diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c index c6950ad289a7..e5e2f572f49f 100644 --- a/drivers/net/ac3200.c +++ b/drivers/net/ac3200.c @@ -407,7 +407,6 @@ cleanup_module(void) release_region(dev->base_addr, AC_IO_EXTENT); if (ei_status.reg0) iounmap((void *)dev->mem_start); - dev->priv = NULL; unregister_netdev(dev); kfree(priv); } diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index 7eef6b801dee..d30f3f70f101 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -13,8 +13,6 @@ * (at your option) any later version. */ -#define DEBUG 1 -#define RX_DMA_SKBUFF 1 #define PKT_COPY_THRESHOLD 300 #include @@ -70,14 +68,71 @@ * by running `ifconfig eth mtu ' with being the Ethernet * interface number and being the MTU value. * + * Module parameters: + * + * When compiled as a loadable module, the driver allows for a number + * of module parameters to be specified. The driver supports the + * following module parameters: + * + * trace= - Firmware trace level. This requires special traced + * firmware to replace the firmware supplied with + * the driver - for debugging purposes only. + * + * link= - Link state. Normally you want to use the default link + * parameters set by the driver. This can be used to + * override these in case your switch doesn't negotiate + * the link properly. Valid values are: + * 0x0001 - Force half duplex link. + * 0x0002 - Do not negotiate line speed with the other end. + * 0x0010 - 10Mbit/sec link. + * 0x0020 - 100Mbit/sec link. + * 0x0040 - 1000Mbit/sec link. + * 0x0100 - Do not negotiate flow control. + * 0x0200 - Enable RX flow control Y + * 0x0400 - Enable TX flow control Y (Tigon II NICs only). + * Default value is 0x0270, ie. enable link+flow + * control negotiation. Negotiating the highest + * possible link speed with RX flow control enabled. + * + * When disabling link speed negotiation, only one link + * speed is allowed to be specified! + * + * tx_coal_tick= - number of coalescing clock ticks (us) allowed + * to wait for more packets to arive before + * interrupting the host, from the time the first + * packet arrives. + * + * rx_coal_tick= - number of coalescing clock ticks (us) allowed + * to wait for more packets to arive in the transmit ring, + * before interrupting the host, after transmitting the + * first packet in the ring. + * + * max_tx_desc= - maximum number of transmit descriptors + * (packets) transmitted before interrupting the host. + * + * max_rx_desc= - maximum number of receive descriptors + * (packets) received before interrupting the host. + * + * If you use more than one NIC, specify the parameters for the + * individual NICs with a comma, ie. trace=0,0x00001fff,0 you want to + * run tracing on NIC #2 but not on NIC #1 and #3. + * * TODO: * * - Add multicast support. - * - Make all the tuning parameters and link speed negotiation, user - * settable at driver/module init time. + * - The Tigon II firmware fails to run in some PCs. + * - NIC dump support. + * - More tuning parameters. */ -static const char *version = "acenic.c: v0.13 11/25/98 Jes Sorensen (Jes.Sorensen@cern.ch)\n"; +static int link[8] = {0, }; +static int trace[8] = {0, }; +static int tx_coal_tick[8] = {0, }; +static int rx_coal_tick[8] = {0, }; +static int max_tx_desc[8] = {0, }; +static int max_rx_desc[8] = {0, }; + +static const char *version = "acenic.c: v0.18 12/16/98 Jes Sorensen (Jes.Sorensen@cern.ch)\n"; static struct device *root_dev = NULL; @@ -149,6 +204,7 @@ __initfunc(int acenic_probe (struct device *dev)) if (!(ap->pci_command & PCI_COMMAND_MASTER)){ ap->pci_command |= PCI_COMMAND_MASTER; + pcibios_write_config_word(pci_bus, pci_dev_fun, PCI_COMMAND, ap->pci_command); @@ -226,7 +282,11 @@ __initfunc(int acenic_probe (struct device *dev)) break; } - ace_init(dev); +#ifdef MODULE + ace_init(dev, boards_found); +#else + ace_init(dev, -1); +#endif boards_found++; @@ -255,6 +315,17 @@ __initfunc(int acenic_probe (struct device *dev)) #ifdef MODULE +#if LINUX_VERSION_CODE > 0x20118 +MODULE_AUTHOR("Jes Sorensen "); +MODULE_DESCRIPTION("AceNIC/3C985 Gigabit Ethernet driver"); +MODULE_PARM(link, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(trace, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(tx_coal_tick, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(max_tx_desc, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(rx_coal_tick, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(max_rx_desc, "1-" __MODULE_STRING(8) "i"); +#endif + int init_module(void) { int cards; @@ -299,6 +370,8 @@ void cleanup_module(void) } iounmap(regs); + if(ap->trace_buf) + kfree(ap->trace_buf); kfree(ap->info); free_irq(root_dev->irq, root_dev); unregister_netdev(root_dev); @@ -326,7 +399,7 @@ static inline void ace_issue_cmd(struct ace_regs *regs, struct cmd *cmd) } -__initfunc(static int ace_init(struct device *dev)) +__initfunc(static int ace_init(struct device *dev, int board_idx)) { struct ace_private *ap; struct ace_regs *regs; @@ -430,7 +503,14 @@ __initfunc(static int ace_init(struct device *dev)) */ tmp = READ_CMD_MEM | WRITE_CMD_MEM; if (ap->version == 2){ +#if 0 + /* + * According to the documentation this enables writes + * to all PCI regs - NOT good. + */ tmp |= DMA_WRITE_ALL_ALIGN; +#endif + tmp |= MEM_READ_MULTIPLE; if (ap->pci_command & PCI_COMMAND_INVALIDATE){ switch(L1_CACHE_BYTES){ case 16: @@ -473,6 +553,13 @@ __initfunc(static int ace_init(struct device *dev)) return -EAGAIN; } + /* + * Register the device here to be able to catch allocated + * interrupt handlers in case the firmware doesn't come up. + */ + ap->next = root_dev; + root_dev = dev; + ap->info = info; memset(info, 0, sizeof(struct ace_info)); @@ -546,12 +633,16 @@ __initfunc(static int ace_init(struct device *dev)) info->tx_csm_ptr = virt_to_bus(&ap->tx_csm); + /* + * Potential item for tuning parameter + */ regs->DmaReadCfg = DMA_THRESH_8W; regs->DmaWriteCfg = DMA_THRESH_8W; regs->MaskInt = 0; regs->IfIdx = 1; + regs->AssistState = 1; #if 0 { u32 tmp; @@ -565,22 +656,87 @@ __initfunc(static int ace_init(struct device *dev)) regs->MacRxState = tmp; } #endif + regs->TuneStatTicks = 2 * TICKS_PER_SEC; - regs->TuneTxCoalTicks = TICKS_PER_SEC / 500; - regs->TuneMaxTxDesc = 7; - regs->TuneRxCoalTicks = TICKS_PER_SEC / 10000; - regs->TuneMaxRxDesc = 2; - regs->TuneTrace = 0 /* 0x30001fff */; - tmp = LNK_ENABLE | LNK_FULL_DUPLEX | LNK_1000MB | - LNK_RX_FLOW_CTL_Y | LNK_NEG_FCTL | LNK_NEGOTIATE; - if(ap->version == 1) - regs->TuneLink = tmp; - else{ - tmp |= LNK_TX_FLOW_CTL_Y; - regs->TuneLink = tmp; - regs->TuneFastLink = tmp; + + if ((board_idx < 8) && tx_coal_tick[board_idx]) + regs->TuneTxCoalTicks = tx_coal_tick[board_idx] * + TICKS_PER_SEC / 1000; + else + regs->TuneTxCoalTicks = TICKS_PER_SEC / 500; + if ((board_idx < 8) && max_tx_desc[board_idx]) + regs->TuneMaxTxDesc = max_tx_desc[board_idx]; + else + regs->TuneMaxTxDesc = 7; + + if ((board_idx < 8) && rx_coal_tick[board_idx]) + regs->TuneRxCoalTicks = rx_coal_tick[board_idx] * + TICKS_PER_SEC / 1000; + else + regs->TuneRxCoalTicks = TICKS_PER_SEC / 10000; + if ((board_idx < 8) && max_rx_desc[board_idx]) + regs->TuneMaxRxDesc = max_rx_desc[board_idx]; + else + regs->TuneMaxRxDesc = 2; + + if (board_idx < 8) + regs->TuneTrace = trace[board_idx]; + else + regs->TuneTrace = 0; + + tmp = LNK_ENABLE; + + if ((board_idx > 7) || !(link[board_idx])){ + if (board_idx > 8) + printk(KERN_WARNING "%s: more then 8 NICs detected, " + "ignoring link options!\n", dev->name); + /* + * No link options specified, we go for the defaults + */ + tmp |= LNK_FULL_DUPLEX | LNK_1000MB | LNK_100MB | LNK_10MB | + LNK_RX_FLOW_CTL_Y | LNK_NEG_FCTL | LNK_NEGOTIATE; + + if(ap->version == 2) + tmp |= LNK_TX_FLOW_CTL_Y; + } else { + int option = link[board_idx]; + if (option & 0x01){ + printk(KERN_INFO "%s: Setting half duplex link\n", + dev->name); + tmp |= LNK_FULL_DUPLEX; + } + if ((option & 0x02) == 0) + tmp |= LNK_NEGOTIATE; + if (option & 0x10) + tmp |= LNK_10MB; + if (option & 0x20) + tmp |= LNK_100MB; + if (option & 0x40) + tmp |= LNK_1000MB; + if ((option & 0x70) == 0){ + printk(KERN_WARNING "%s: No media speed specified, " + "forcing auto negotiation\n", dev->name); + tmp |= LNK_NEGOTIATE | LNK_1000MB | + LNK_100MB | LNK_10MB; + } + if ((option & 0x100) == 0) + tmp |= LNK_NEG_FCTL; + else + printk(KERN_INFO "%s: Disabling flow control " + "negotiation\n", dev->name); + if (option & 0x200) + tmp |= LNK_RX_FLOW_CTL_Y; + if ((option & 0x400) && (ap->version == 2)){ + printk(KERN_INFO "%s: Enabling TX flow control\n", + dev->name); + tmp |= LNK_TX_FLOW_CTL_Y; + } } + regs->TuneLink = tmp; + if (ap->version == 2) + regs->TuneFastLink = tmp; + if (ap->version == 1) regs->Pc = tigonFwStartAddr; else if (ap->version == 2) @@ -595,18 +751,17 @@ __initfunc(static int ace_init(struct device *dev)) regs->CpuCtrl = (regs->CpuCtrl & ~(CPU_HALT | CPU_TRACE)); /* - * Wait for the firmware to spin up - max 2 seconds. + * Wait for the firmware to spin up - max 3 seconds. */ myjif = jiffies + 3 * HZ; while ((myjif > jiffies) && !ap->fw_running); if (!ap->fw_running){ printk(KERN_ERR "%s: firmware NOT running!\n", dev->name); + ace_dump_trace(ap); + regs->CpuCtrl |= CPU_HALT; return -EBUSY; } - ap->next = root_dev; - root_dev = dev; - /* * We load the ring here as there seem to be no way to tell the * firmware to wipe the ring without re-initializing it. @@ -620,7 +775,6 @@ __initfunc(static int ace_init(struct device *dev)) /* * Monitor the card to detect hangs. */ - static void ace_timer(unsigned long data) { struct device *dev = (struct device *)data; @@ -642,6 +796,17 @@ static void ace_timer(unsigned long data) } +/* + * Copy the contents of the NIC's trace buffer to kernel memory. + */ +static void ace_dump_trace(struct ace_private *ap) +{ + if (!ap->trace_buf) + if (!(ap->trace_buf = kmalloc(ACE_TRACE_SIZE, GFP_KERNEL))); + return; +} + + /* * Load the standard rx ring. */ @@ -822,7 +987,6 @@ static u32 ace_handle_event(struct device *dev, u32 evtcsm, u32 evtprd) ap->fw_running = 1; break; case E_STATS_UPDATED: - mod_timer(&ap->timer, jiffies + (5/2*HZ)); break; case E_LNK_STATE: { @@ -1036,18 +1200,6 @@ static void ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) return; } -#if 0 - /* - * Since we are also using a spinlock, I wonder if this is - * actually worth it. - */ - if (test_and_set_bit(0, (void*)&dev->interrupt) != 0) { - printk(KERN_WARNING "%s: Re-entering the interrupt handler.\n", - dev->name); - return; - } -#endif - /* * Tell the card not to generate interrupts while we are in here. */ @@ -1079,6 +1231,7 @@ static void ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) } ap->tx_ret_csm = txcsm; + mod_timer(&ap->timer, jiffies + (5/2*HZ)); } rxretprd = ap->rx_ret_prd; @@ -1098,9 +1251,6 @@ static void ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) regs->Mb0Lo = 0; spin_unlock(&ap->lock); -#if 0 - dev->interrupt = 0; -#endif } @@ -1159,9 +1309,9 @@ static int ace_open(struct device *dev) * Setup the timer */ init_timer(&ap->timer); - ap->timer.expires = jiffies + 5/2 * HZ; + ap->timer.expires = jiffies + (5/2 * HZ); ap->timer.data = (unsigned long)dev; - ap->timer.function = &ace_timer; + ap->timer.function = ace_timer; add_timer(&ap->timer); return 0; } diff --git a/drivers/net/acenic.h b/drivers/net/acenic.h index e84be5f7bdb3..bcd5b21fa6a1 100644 --- a/drivers/net/acenic.h +++ b/drivers/net/acenic.h @@ -142,6 +142,8 @@ struct ace_regs { #define ACE_JUMBO_MTU 9000 #define ACE_STD_MTU 1500 +#define ACE_TRACE_SIZE 0x8000 + /* * Host control register bits. */ @@ -205,19 +207,12 @@ struct ace_regs { #define DMA_WRITE_MAX_128 0xa0 #define DMA_WRITE_MAX_256 0xc0 #define DMA_WRITE_MAX_1K 0xe0 +#define MEM_READ_MULTIPLE 0x00020000 #define DMA_WRITE_ALL_ALIGN 0x00800000 #define READ_CMD_MEM 0x06000000 #define WRITE_CMD_MEM 0x70000000 -/* - * Transmit status. - */ - -#define ENA_XMIT 0x01 -#define PERM_CON 0x02 - - /* * Mode status */ @@ -580,9 +575,11 @@ struct ace_private __attribute__ ((aligned (L1_CACHE_BYTES))); struct device *next __attribute__ ((aligned (L1_CACHE_BYTES))); + unsigned char *trace_buf; int fw_running, fw_up, jumbo, promisc; int version; - int vendor; + int flags; + u16 vendor; u16 pci_command; u8 pci_bus; u8 pci_dev_fun; @@ -593,7 +590,7 @@ struct ace_private /* * Prototypes */ -static int ace_init(struct device *dev); +static int ace_init(struct device *dev, int board_idx); static int ace_load_std_rx_ring(struct device *dev); static int ace_load_jumbo_rx_ring(struct device *dev); static int ace_flush_jumbo_rx_ring(struct device *dev); @@ -603,6 +600,7 @@ static int ace_open(struct device *dev); static int ace_start_xmit(struct sk_buff *skb, struct device *dev); static int ace_close(struct device *dev); static void ace_timer(unsigned long data); +static void ace_dump_trace(struct ace_private *ap); static void ace_set_multicast_list(struct device *dev); static int ace_change_mtu(struct device *dev, int new_mtu); static int ace_set_mac_addr(struct device *dev, void *p); diff --git a/drivers/net/acenic_firmware.h b/drivers/net/acenic_firmware.h index 2c7d4f4782ff..befe4232d1c6 100644 --- a/drivers/net/acenic_firmware.h +++ b/drivers/net/acenic_firmware.h @@ -1,28 +1,28 @@ /* Generated by genfw.c */ int tigonFwReleaseMajor = 0xc; int tigonFwReleaseMinor = 0x1; -int tigonFwReleaseFix = 0x4; +int tigonFwReleaseFix = 0x6; u32 tigonFwStartAddr = 0x4000; u32 tigonFwTextAddr = 0x4000; -int tigonFwTextLen = 0x10300; -u32 tigonFwDataAddr = 0x14d40; +int tigonFwTextLen = 0x10500; +u32 tigonFwDataAddr = 0x14f50; int tigonFwDataLen = 0x140; -u32 tigonFwRodataAddr = 0x14300; -int tigonFwRodataLen = 0xa20; -u32 tigonFwBssAddr = 0x14eb0; +u32 tigonFwRodataAddr = 0x14500; +int tigonFwRodataLen = 0xa30; +u32 tigonFwBssAddr = 0x150c0; int tigonFwBssLen = 0x2080; -u32 tigonFwSbssAddr = 0x14e80; +u32 tigonFwSbssAddr = 0x15090; int tigonFwSbssLen = 0x28; -u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] = { -0x10000003, 0x0, 0xd, 0xd, 0x3c1d0001, 0x8fbd4d74, +u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __init = { +0x10000003, 0x0, 0xd, 0xd, 0x3c1d0001, 0x8fbd4f84, 0x3a0f021, 0x3c100000, 0x26104000, 0xc00100c, 0x0, 0xd, 0x27bdffd8, 0x3c1cc000, 0x3c1b0013, 0x377bd800, 0xd021, 0x3c170013, -0x36f75430, 0x2e02021, 0x340583d0, 0xafbf0024, 0xc00242c, 0xafb00020, -0xc00238c, 0x0, 0x3c040001, 0x24844360, 0x24050001, 0x2e03021, -0x3821, 0x3c100001, 0x26106f30, 0xafb00010, 0xc0023a7, 0xafbb0014, +0x36f75430, 0x2e02021, 0x340583d0, 0xafbf0024, 0xc002488, 0xafb00020, +0xc0023e8, 0x0, 0x3c040001, 0x24844560, 0x24050001, 0x2e03021, +0x3821, 0x3c100001, 0x26107140, 0xafb00010, 0xc002403, 0xafbb0014, 0x3c02000f, 0x3442ffff, 0x2021024, 0x362102b, 0x10400009, 0x24050003, -0x3c040001, 0x2484436c, 0x2003021, 0x3603821, 0x3c020010, 0xafa20010, -0xc0023a7, 0xafa00014, 0x2021, 0x3405c000, 0x3c010001, 0x370821, +0x3c040001, 0x2484456c, 0x2003021, 0x3603821, 0x3c020010, 0xafa20010, +0xc002403, 0xafa00014, 0x2021, 0x3405c000, 0x3c010001, 0x370821, 0xa02083a0, 0x3c010001, 0x370821, 0xa02083a2, 0x3c010001, 0x370821, 0xa02083a3, 0x3c010001, 0x370821, 0xac2083a4, 0xa2e004c8, 0x418c0, 0x24840001, 0x771021, 0xac40726c, 0x771021, 0xac407270, 0x2e31021, @@ -46,122 +46,124 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] = { 0x8f8200b0, 0x8ee304bc, 0x431025, 0xaf8200b0, 0x8f8200b0, 0x30420004, 0x1440fffd, 0x0, 0x8ee20450, 0x8ee30454, 0xaee304ec, 0x8ee204ec, 0x2442e000, 0x2c422001, 0x1440000d, 0x26e40030, 0x8ee20450, 0x8ee30454, -0x3c040001, 0x24844378, 0x3c050001, 0xafa00010, 0xafa00014, 0x8ee704ec, -0x34a5f000, 0xc0023a7, 0x603021, 0x26e40030, 0xc00242c, 0x24050400, -0x27440080, 0xc00242c, 0x24050080, 0x26e4776c, 0xc00242c, 0x24050400, +0x3c040001, 0x24844578, 0x3c050001, 0xafa00010, 0xafa00014, 0x8ee704ec, +0x34a5f000, 0xc002403, 0x603021, 0x26e40030, 0xc002488, 0x24050400, +0x27440080, 0xc002488, 0x24050080, 0x26e4776c, 0xc002488, 0x24050400, 0x8f42025c, 0x26e40094, 0xaee20060, 0x8f420260, 0x27450200, 0x24060008, -0xaee20068, 0x24020006, 0xc00243e, 0xaee20064, 0x3c023b9a, 0x3442ca00, +0xaee20068, 0x24020006, 0xc00249a, 0xaee20064, 0x3c023b9a, 0x3442ca00, 0x2021, 0x24030002, 0xaee30074, 0xaee30070, 0xaee2006c, 0x240203e8, 0xaee20104, 0x24020001, 0xaee30100, 0xaee2010c, 0x3c030001, 0x641821, -0x90634d40, 0x2e41021, 0x24840001, 0xa043009c, 0x2c82000f, 0x1440fff8, +0x90634f50, 0x2e41021, 0x24840001, 0xa043009c, 0x2c82000f, 0x1440fff8, 0x0, 0x8f820040, 0x2e41821, 0x24840001, 0x21702, 0x24420030, 0xa062009c, 0x2e41021, 0xa040009c, 0x96e2046a, 0x30420003, 0x14400009, -0x0, 0x96e2047a, 0x30420003, 0x5040012b, 0x3c030800, 0x96e2046a, +0x0, 0x96e2047a, 0x30420003, 0x50400131, 0x3c030800, 0x96e2046a, 0x30420003, 0x1040002a, 0x3c020700, 0x96e2047a, 0x30420003, 0x10400026, 0x3c020700, 0x96e3047a, 0x96e2046a, 0x14620022, 0x3c020700, 0x8ee204b0, 0x24030001, 0xa2e34e10, 0x34420e00, 0xaee204b0, 0x8f420218, 0x30420100, -0x10400005, 0x0, 0x3c020001, 0x2442ded0, 0x800111d, 0x21100, -0x3c020001, 0x2442d0d0, 0x21100, 0x21182, 0x3c030800, 0x431025, -0x3c010001, 0xac220f38, 0x3c020001, 0x2442f3c8, 0x21100, 0x21182, -0x3c030800, 0x431025, 0x3c010001, 0xac220f78, 0x8ee20000, 0x34424000, -0x8001232, 0xaee20000, 0x34423000, 0xafa20018, 0x8ee205f8, 0x8f430228, -0x24420001, 0x304900ff, 0x512300dc, 0xafa00010, 0x8ee205f8, 0x210c0, +0x10400005, 0x0, 0x3c020001, 0x2442e128, 0x800111d, 0x21100, +0x3c020001, 0x2442d31c, 0x21100, 0x21182, 0x3c030800, 0x431025, +0x3c010001, 0xac221138, 0x3c020001, 0x2442f640, 0x21100, 0x21182, +0x3c030800, 0x431025, 0x3c010001, 0xac221178, 0x8ee20000, 0x34424000, +0x8001238, 0xaee20000, 0x34423000, 0xafa20018, 0x8ee205f8, 0x8f430228, +0x24420001, 0x304900ff, 0x512300e2, 0xafa00010, 0x8ee205f8, 0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f870120, 0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128, -0x15020007, 0x1021, 0x8ee201a0, 0x3021, 0x24420001, 0xaee201a0, -0x800119d, 0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, -0x8ee50434, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, -0xace50004, 0x8ee305f8, 0x24020008, 0xa4e2000e, 0x2402000d, 0xace20018, -0xace9001c, 0x318c0, 0x246305fc, 0x2e31021, 0xace20008, 0x8ee204b4, -0xace20010, 0xaf880120, 0x92e24e10, 0x14400037, 0x24060001, 0x8ee24e20, -0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 0x1462001f, -0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, -0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, -0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x8001187, -0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, -0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x800119d, -0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, -0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, -0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x54c0000c, -0xaee905f8, 0x3c040001, 0x24844384, 0xafa00010, 0xafa00014, 0x8ee605f8, -0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f000, 0x800121d, 0x0, -0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, -0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, 0x3021, 0x24420001, -0xaee201a0, 0x8001201, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, +0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, 0x8ee201a0, +0x3021, 0x24420001, 0xaee201a0, 0x80011a0, 0x8ee201a0, 0x8ee405f8, +0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b, +0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee305f8, 0x24020008, +0xa4e2000e, 0x2402000d, 0xace20018, 0xace9001c, 0x318c0, 0x246305fc, +0x2e31021, 0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, +0x14400037, 0x24060001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, +0x8c830000, 0x24020007, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, +0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, +0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24, 0x24420001, +0x10a20005, 0x0, 0x800118a, 0x0, 0x14a00005, 0x0, +0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, +0x50400013, 0xac800000, 0x80011a0, 0x0, 0x8ee24e20, 0x24030040, +0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, +0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020007, 0xac820000, +0x24020001, 0xac820004, 0x54c0000c, 0xaee905f8, 0x3c040001, 0x24844584, +0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403, +0x34a5f000, 0x8001223, 0x0, 0x8f830120, 0x27623800, 0x24660020, +0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, +0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x3021, 0x24420001, +0xaee201a0, 0x8001207, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x24060001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24, -0x24420001, 0x10a20005, 0x0, 0x80011eb, 0x0, 0x14a00005, +0x24420001, 0x10a20005, 0x0, 0x80011f1, 0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, -0x2c420011, 0x50400013, 0xac800000, 0x8001201, 0x0, 0x8ee24e20, +0x2c420011, 0x50400013, 0xac800000, 0x8001207, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x14c0001b, 0x0, 0x3c040001, -0x2484438c, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, -0xc0023a7, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x800121d, -0x8ee201ac, 0x3c040001, 0x24844398, 0xafa00014, 0x8ee605f8, 0x8f470228, -0x3c050009, 0xc0023a7, 0x34a5f005, 0x8ee201a8, 0x24420001, 0xaee201a8, -0x8ee201a8, 0x8ee2015c, 0x3c040001, 0x248443a4, 0x3405f001, 0x24420001, -0xaee2015c, 0x8ee2015c, 0x3021, 0x3821, 0xafa00010, 0xc0023a7, -0xafa00014, 0x8001232, 0x0, 0x3c020001, 0x2442f2f0, 0x21100, -0x21182, 0x431025, 0x3c010001, 0xac220f78, 0x96e2045a, 0x30420003, +0x2484458c, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, +0xc002403, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8001223, +0x8ee201ac, 0x3c040001, 0x24844598, 0xafa00014, 0x8ee605f8, 0x8f470228, +0x3c050009, 0xc002403, 0x34a5f005, 0x8ee201a8, 0x24420001, 0xaee201a8, +0x8ee201a8, 0x8ee2015c, 0x3c040001, 0x248445a4, 0x3405f001, 0x24420001, +0xaee2015c, 0x8ee2015c, 0x3021, 0x3821, 0xafa00010, 0xc002403, +0xafa00014, 0x8001238, 0x0, 0x3c020001, 0x2442f568, 0x21100, +0x21182, 0x431025, 0x3c010001, 0xac221178, 0x96e2045a, 0x30420003, 0x10400025, 0x3c050fff, 0x8ee204b8, 0x34a5ffff, 0x34420a00, 0xaee204b8, -0x8ee304b8, 0x3c040001, 0x248443b0, 0x24020001, 0xa2e204dc, 0xa2e204dd, -0x3c020002, 0x621825, 0x3c020001, 0x2442a1c0, 0x451024, 0x21082, -0xaee304b8, 0x3c030800, 0x431025, 0x3c010001, 0xac220f20, 0x3c020001, -0x2442abb4, 0x451024, 0x21082, 0x431025, 0x3c010001, 0xac220f80, -0x96e6045a, 0x3821, 0x24050011, 0xafa00010, 0xc0023a7, 0xafa00014, -0x8001262, 0x0, 0x3c020001, 0x2442a7e0, 0x21100, 0x21182, -0x3c030800, 0x431025, 0x3c010001, 0xac220f80, 0x96e2046a, 0x30420010, -0x14400009, 0x0, 0x96e2047a, 0x30420010, 0x1040010c, 0x0, +0x8ee304b8, 0x3c040001, 0x248445b0, 0x24020001, 0xa2e204dc, 0xa2e204dd, +0x3c020002, 0x621825, 0x3c020001, 0x2442a390, 0x451024, 0x21082, +0xaee304b8, 0x3c030800, 0x431025, 0x3c010001, 0xac221120, 0x3c020001, +0x2442adb4, 0x451024, 0x21082, 0x431025, 0x3c010001, 0xac221180, +0x96e6045a, 0x3821, 0x24050011, 0xafa00010, 0xc002403, 0xafa00014, +0x8001268, 0x0, 0x3c020001, 0x2442a9d4, 0x21100, 0x21182, +0x3c030800, 0x431025, 0x3c010001, 0xac221180, 0x96e2046a, 0x30420010, +0x14400009, 0x0, 0x96e2047a, 0x30420010, 0x10400112, 0x0, 0x96e2046a, 0x30420010, 0x10400005, 0x3c020700, 0x96e2047a, 0x30420010, -0x144000fc, 0x3c020700, 0x34423000, 0xafa20018, 0x8ee205f8, 0x8f430228, -0x24420001, 0x304900ff, 0x512300dc, 0xafa00010, 0x8ee205f8, 0x210c0, +0x14400102, 0x3c020700, 0x34423000, 0xafa20018, 0x8ee205f8, 0x8f430228, +0x24420001, 0x304900ff, 0x512300e2, 0xafa00010, 0x8ee205f8, 0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f870120, 0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128, -0x15020007, 0x1021, 0x8ee201a0, 0x3021, 0x24420001, 0xaee201a0, -0x80012e1, 0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, -0x8ee50434, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, -0xace50004, 0x8ee305f8, 0x24020008, 0xa4e2000e, 0x2402000d, 0xace20018, -0xace9001c, 0x318c0, 0x246305fc, 0x2e31021, 0xace20008, 0x8ee204b4, -0xace20010, 0xaf880120, 0x92e24e10, 0x14400037, 0x24060001, 0x8ee24e20, -0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 0x1462001f, -0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, -0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, -0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x80012cb, -0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, -0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x80012e1, -0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, -0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, -0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x54c0000c, -0xaee905f8, 0x3c040001, 0x24844384, 0xafa00010, 0xafa00014, 0x8ee605f8, -0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f000, 0x8001361, 0x0, -0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, -0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, 0x3021, 0x24420001, -0xaee201a0, 0x8001345, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, +0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, 0x8ee201a0, +0x3021, 0x24420001, 0xaee201a0, 0x80012ea, 0x8ee201a0, 0x8ee405f8, +0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b, +0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee305f8, 0x24020008, +0xa4e2000e, 0x2402000d, 0xace20018, 0xace9001c, 0x318c0, 0x246305fc, +0x2e31021, 0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, +0x14400037, 0x24060001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, +0x8c830000, 0x24020007, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, +0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, +0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24, 0x24420001, +0x10a20005, 0x0, 0x80012d4, 0x0, 0x14a00005, 0x0, +0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, +0x50400013, 0xac800000, 0x80012ea, 0x0, 0x8ee24e20, 0x24030040, +0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, +0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020007, 0xac820000, +0x24020001, 0xac820004, 0x54c0000c, 0xaee905f8, 0x3c040001, 0x24844584, +0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403, +0x34a5f000, 0x800136d, 0x0, 0x8f830120, 0x27623800, 0x24660020, +0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, +0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x3021, 0x24420001, +0xaee201a0, 0x8001351, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x24060001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24, -0x24420001, 0x10a20005, 0x0, 0x800132f, 0x0, 0x14a00005, +0x24420001, 0x10a20005, 0x0, 0x800133b, 0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, -0x2c420011, 0x50400013, 0xac800000, 0x8001345, 0x0, 0x8ee24e20, +0x2c420011, 0x50400013, 0xac800000, 0x8001351, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x14c0001b, 0x0, 0x3c040001, -0x2484438c, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, -0xc0023a7, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8001361, -0x8ee201ac, 0x3c040001, 0x24844398, 0xafa00014, 0x8ee605f8, 0x8f470228, -0x3c050009, 0xc0023a7, 0x34a5f005, 0x8ee201a8, 0x24420001, 0xaee201a8, -0x8ee201a8, 0x8ee2015c, 0x3c040001, 0x248443a4, 0x3405f002, 0x24420001, -0xaee2015c, 0x8ee2015c, 0x3021, 0x3821, 0xafa00010, 0xc0023a7, -0xafa00014, 0x96e6047a, 0x96e7046a, 0x3c040001, 0x248443bc, 0x24050012, -0xafa00010, 0xc0023a7, 0xafa00014, 0xc004440, 0x0, 0xc0022b8, +0x2484458c, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, +0xc002403, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x800136d, +0x8ee201ac, 0x3c040001, 0x24844598, 0xafa00014, 0x8ee605f8, 0x8f470228, +0x3c050009, 0xc002403, 0x34a5f005, 0x8ee201a8, 0x24420001, 0xaee201a8, +0x8ee201a8, 0x8ee2015c, 0x3c040001, 0x248445a4, 0x3405f002, 0x24420001, +0xaee2015c, 0x8ee2015c, 0x3021, 0x3821, 0xafa00010, 0xc002403, +0xafa00014, 0x96e6047a, 0x96e7046a, 0x3c040001, 0x248445bc, 0x24050012, +0xafa00010, 0xc002403, 0xafa00014, 0xc0044c0, 0x0, 0xc002314, 0x0, 0x3c060001, 0x34c63800, 0xaee005f8, 0xaf400228, 0xaf40022c, 0x96e30458, 0x8ee40000, 0x3c0512d8, 0x34a5c358, 0x27623800, 0xaee27248, 0x27623800, 0xaee27250, 0x27623800, 0xaee27254, 0x3661021, 0xaee27260, @@ -170,464 +172,391 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] = { 0xaee05234, 0xaee05230, 0xaee0522c, 0xaee07240, 0xaee07244, 0xaee0724c, 0xaee07258, 0xaee004c0, 0x2463ffff, 0x852025, 0xaee304e8, 0xaee40000, 0xaf800060, 0xaf820064, 0x3c020100, 0xafa20018, 0x8ee205f8, 0x8f430228, -0x24420001, 0x304900ff, 0x512300dc, 0xafa00010, 0x8ee205f8, 0x210c0, +0x24420001, 0x304900ff, 0x512300e2, 0xafa00010, 0x8ee205f8, 0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f870120, 0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128, -0x15020007, 0x1021, 0x8ee201a0, 0x3021, 0x24420001, 0xaee201a0, -0x8001413, 0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, -0x8ee50434, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, -0xace50004, 0x8ee305f8, 0x24020008, 0xa4e2000e, 0x2402000d, 0xace20018, -0xace9001c, 0x318c0, 0x246305fc, 0x2e31021, 0xace20008, 0x8ee204b4, -0xace20010, 0xaf880120, 0x92e24e10, 0x14400037, 0x24060001, 0x8ee24e20, -0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 0x1462001f, -0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, -0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, -0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x80013fd, -0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, -0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x8001413, -0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, -0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, -0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x54c0000c, -0xaee905f8, 0x3c040001, 0x24844384, 0xafa00010, 0xafa00014, 0x8ee605f8, -0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f000, 0x8001493, 0x0, -0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, -0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, 0x3021, 0x24420001, -0xaee201a0, 0x8001477, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, +0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, 0x8ee201a0, +0x3021, 0x24420001, 0xaee201a0, 0x8001422, 0x8ee201a0, 0x8ee405f8, +0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b, +0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee305f8, 0x24020008, +0xa4e2000e, 0x2402000d, 0xace20018, 0xace9001c, 0x318c0, 0x246305fc, +0x2e31021, 0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, +0x14400037, 0x24060001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, +0x8c830000, 0x24020007, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, +0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, +0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24, 0x24420001, +0x10a20005, 0x0, 0x800140c, 0x0, 0x14a00005, 0x0, +0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, +0x50400013, 0xac800000, 0x8001422, 0x0, 0x8ee24e20, 0x24030040, +0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, +0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020007, 0xac820000, +0x24020001, 0xac820004, 0x54c0000c, 0xaee905f8, 0x3c040001, 0x24844584, +0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403, +0x34a5f000, 0x80014a5, 0x0, 0x8f830120, 0x27623800, 0x24660020, +0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, +0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x3021, 0x24420001, +0xaee201a0, 0x8001489, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x24060001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24, -0x24420001, 0x10a20005, 0x0, 0x8001461, 0x0, 0x14a00005, +0x24420001, 0x10a20005, 0x0, 0x8001473, 0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, -0x2c420011, 0x50400013, 0xac800000, 0x8001477, 0x0, 0x8ee24e20, +0x2c420011, 0x50400013, 0xac800000, 0x8001489, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x14c0001b, 0x0, 0x3c040001, -0x2484438c, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, -0xc0023a7, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8001493, -0x8ee201ac, 0x3c040001, 0x24844398, 0xafa00014, 0x8ee605f8, 0x8f470228, -0x3c050009, 0xc0023a7, 0x34a5f005, 0x8ee201a8, 0x24420001, 0xaee201a8, -0x8ee201a8, 0x8ee20150, 0x24420001, 0xaee20150, 0xc0014c8, 0x8ee20150, +0x2484458c, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, +0xc002403, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x80014a5, +0x8ee201ac, 0x3c040001, 0x24844598, 0xafa00014, 0x8ee605f8, 0x8f470228, +0x3c050009, 0xc002403, 0x34a5f005, 0x8ee201a8, 0x24420001, 0xaee201a8, +0x8ee201a8, 0x8ee20150, 0x24420001, 0xaee20150, 0xc0014dc, 0x8ee20150, 0x8f8200a0, 0x30420004, 0x1440fffd, 0x0, 0x8f820040, 0x30420001, 0x14400008, 0x0, 0x8f430104, 0x24020001, 0x10620004, 0x0, 0x8f420264, 0x10400006, 0x0, 0x8ee20178, 0x24420001, 0xaee20178, -0x80014b3, 0x8ee20178, 0x8f820044, 0x34420004, 0xaf820044, 0x8ee20174, +0x80014c5, 0x8ee20178, 0x8f820044, 0x34420004, 0xaf820044, 0x8ee20174, 0x24420001, 0xaee20174, 0x8ee20174, 0x8f8200d8, 0x8f8300d4, 0x431023, 0xaee2725c, 0x8ee2725c, 0x1c400003, 0x3c030001, 0x431021, 0xaee2725c, -0xc003fb0, 0x0, 0xc004380, 0xaf800228, 0x8fbf0024, 0x8fb00020, +0xc004054, 0x0, 0xc004400, 0xaf800228, 0x8fbf0024, 0x8fb00020, 0x3e00008, 0x27bd0028, 0x3e00008, 0x0, 0x3e00008, 0x0, -0x2402002c, 0xaf820050, 0xaee07264, 0x8f420238, 0xaee27268, 0x8f820054, -0x24420067, 0xaf820058, 0xaee07b78, 0xaee07b7c, 0xaee07b74, 0x3c010001, -0x370821, 0xac2083ac, 0x3c010001, 0x370821, 0x3e00008, 0xa02083a9, -0x27bdffd8, 0xafbf0024, 0xafb00020, 0x8f820054, 0x3c030001, 0x8c634dfc, -0x24420067, 0x1060000d, 0xaf820058, 0x3c020001, 0x571021, 0x904283a8, -0x10400005, 0x3c030200, 0x3c010001, 0x370821, 0x80014ef, 0xa02083a8, -0x8ee20000, 0x431025, 0xaee20000, 0x8f420218, 0x30420100, 0x104000c3, -0x0, 0x8f8200b0, 0x30420004, 0x104000bf, 0x0, 0x3c030001, -0x771821, 0x8c6383c0, 0x8f820104, 0x146200b1, 0x0, 0x3c030001, -0x771821, 0x8c6383c4, 0x8f8200b4, 0x146200ab, 0x0, 0x8f8200b0, -0x3c030080, 0x431024, 0x1040000d, 0x0, 0x8f82011c, 0x34420002, -0xaf82011c, 0x8f8200b0, 0x2403fffb, 0x431024, 0xaf8200b0, 0x8f82011c, -0x2403fffd, 0x431024, 0x80015b5, 0xaf82011c, 0x3c030001, 0x771821, -0x8c6383c0, 0x8f820104, 0x1462007f, 0x0, 0x3c030001, 0x771821, -0x8c6383c4, 0x8f8200b4, 0x14620079, 0x0, 0x3c070001, 0xf73821, -0x8ce783c0, 0x8f8200b0, 0x3c040001, 0x24844430, 0xafa00014, 0xafa20010, -0x8f8600b0, 0x3c050005, 0xc0023a7, 0x34a50900, 0x8f82011c, 0x34420002, -0xaf82011c, 0x8f830104, 0x8f8200b0, 0x34420001, 0xaf8200b0, 0xaf830104, -0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, -0x8f820128, 0x14c20006, 0x0, 0x8ee201a0, 0x24420001, 0xaee201a0, -0x8001589, 0x8ee201a0, 0x8f440208, 0x8f45020c, 0x26e20030, 0xac620008, -0x24020400, 0xa462000e, 0x2402000f, 0xac620018, 0xac60001c, 0xac640000, +0x0, 0x0, 0x2402002c, 0xaf820050, 0xaee07264, 0x8f420238, +0xaee27268, 0x8f820054, 0x24420067, 0xaf820058, 0xaee07b78, 0xaee07b7c, +0xaee07b74, 0x3c010001, 0x370821, 0xac2083ac, 0x3c010001, 0x370821, +0x3e00008, 0xa02083a9, 0x27bdffd8, 0xafbf0024, 0xafb00020, 0x8f820054, +0x3c030001, 0x8c63500c, 0x24420067, 0x1060000d, 0xaf820058, 0x3c020001, +0x571021, 0x904283a8, 0x10400005, 0x3c030200, 0x3c010001, 0x370821, +0x8001503, 0xa02083a8, 0x8ee20000, 0x431025, 0xaee20000, 0x8f420218, +0x30420100, 0x104000c6, 0x0, 0x8f8200b0, 0x30420004, 0x104000c2, +0x0, 0x3c030001, 0x771821, 0x8c6383c0, 0x8f820104, 0x146200b4, +0x0, 0x3c030001, 0x771821, 0x8c6383c4, 0x8f8200b4, 0x146200ae, +0x0, 0x8f8200b0, 0x3c030080, 0x431024, 0x1040000d, 0x0, +0x8f82011c, 0x34420002, 0xaf82011c, 0x8f8200b0, 0x2403fffb, 0x431024, +0xaf8200b0, 0x8f82011c, 0x2403fffd, 0x431024, 0x80015cc, 0xaf82011c, +0x3c030001, 0x771821, 0x8c6383c0, 0x8f820104, 0x14620082, 0x0, +0x3c030001, 0x771821, 0x8c6383c4, 0x8f8200b4, 0x1462007c, 0x0, +0x3c070001, 0xf73821, 0x8ce783c0, 0x8f8200b0, 0x3c040001, 0x24844630, +0xafa00014, 0xafa20010, 0x8f8600b0, 0x3c050005, 0xc002403, 0x34a50900, +0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830104, 0x8f8200b0, 0x34420001, +0xaf8200b0, 0xaf830104, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, +0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124, +0x14c20006, 0x0, 0x8ee201a0, 0x24420001, 0xaee201a0, 0x80015a0, +0x8ee201a0, 0x8f440208, 0x8f45020c, 0x26e20030, 0xac620008, 0x24020400, +0xa462000e, 0x2402000f, 0xac620018, 0xac60001c, 0xac640000, 0xac650004, +0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x0, +0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007, +0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, +0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, +0x10430007, 0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, +0x800158a, 0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, +0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, +0x80015a0, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, +0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, +0x24425028, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, +0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201d4, 0x3c070001, +0xf73821, 0x8ce783c0, 0x24420001, 0xaee201d4, 0x8ee201d4, 0x3c040001, +0x2484463c, 0x80015bd, 0xafa00010, 0x8f820104, 0x3c010001, 0x370821, +0xac2283c0, 0x8f8200b4, 0x3c070001, 0xf73821, 0x8ce783c0, 0x3c040001, +0x24844644, 0x3c010001, 0x370821, 0xac2283c4, 0xafa00010, 0xafa00014, +0x8f8600b0, 0x3c050005, 0xc002403, 0x34a50900, 0x80015cc, 0x0, +0x8f820104, 0x3c010001, 0x370821, 0xac2283c0, 0x8f8200b4, 0x3c010001, +0x370821, 0xac2283c4, 0x8ee27264, 0x92e304e4, 0x24420067, 0x14600006, +0xaee27264, 0x8ee27264, 0x8f430234, 0x43102b, 0x1440007b, 0x0, +0x8ee304d4, 0x8ee204e8, 0x14620004, 0x0, 0x92e204e4, 0x50400074, +0xa2e004e4, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, +0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124, 0x14c20007, +0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8001637, +0x8ee201a0, 0x8ee204d4, 0xac62001c, 0x8ee404a0, 0x8ee504a4, 0x2462001c, +0xac620008, 0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, -0x0, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, -0x24020007, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, +0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, +0x24020012, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24, 0x24420001, 0x10a20005, -0x0, 0x8001573, 0x0, 0x14a00005, 0x0, 0x8f820128, +0x0, 0x8001621, 0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, -0xac800000, 0x8001589, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, +0xac800000, 0x8001637, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, -0x210c0, 0x24425028, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, -0xac820004, 0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201d4, -0x3c070001, 0xf73821, 0x8ce783c0, 0x24420001, 0xaee201d4, 0x8ee201d4, -0x3c040001, 0x2484443c, 0x80015a6, 0xafa00010, 0x8f820104, 0x3c010001, -0x370821, 0xac2283c0, 0x8f8200b4, 0x3c070001, 0xf73821, 0x8ce783c0, -0x3c040001, 0x24844444, 0x3c010001, 0x370821, 0xac2283c4, 0xafa00010, -0xafa00014, 0x8f8600b0, 0x3c050005, 0xc0023a7, 0x34a50900, 0x80015b5, -0x0, 0x8f820104, 0x3c010001, 0x370821, 0xac2283c0, 0x8f8200b4, -0x3c010001, 0x370821, 0xac2283c4, 0x8ee27264, 0x92e304e4, 0x24420067, -0x14600006, 0xaee27264, 0x8ee27264, 0x8f430234, 0x43102b, 0x14400078, -0x0, 0x8ee304d4, 0x8ee204e8, 0x14620004, 0x0, 0x92e204e4, -0x50400071, 0xa2e004e4, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, -0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, -0x8021, 0x24420001, 0xaee201a0, 0x800161d, 0x8ee201a0, 0x8ee204d4, -0xac62001c, 0x8ee404a0, 0x8ee504a4, 0x2462001c, 0xac620008, 0x24020008, +0x210c0, 0x24425028, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, +0xac820004, 0x5600000b, 0x24100001, 0x8ee204d4, 0x3c040001, 0x2484464c, +0xafa00014, 0xafa20010, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403, +0x34a5f006, 0x16000003, 0x24020001, 0x8001650, 0xa2e204e4, 0x8ee2016c, +0x24420001, 0xaee2016c, 0x8ee2016c, 0x8ee204d4, 0xa2e004e4, 0xaee004e0, +0xaee07264, 0xaee204e8, 0x8ee20e0c, 0x1040006d, 0x0, 0x8f830120, +0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, +0x10c20004, 0x0, 0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, +0x8021, 0x24420001, 0xaee201a0, 0x80016ad, 0x8ee201a0, 0x8ee2723c, +0xac62001c, 0x8ee40498, 0x8ee5049c, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, -0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x8001607, +0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x8001697, 0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, -0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x800161d, +0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x80016ad, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x5600000b, -0x24100001, 0x8ee204d4, 0x3c040001, 0x2484444c, 0xafa00014, 0xafa20010, -0x8ee605f8, 0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f006, 0x16000003, -0x24020001, 0x8001636, 0xa2e204e4, 0x8ee2016c, 0x24420001, 0xaee2016c, -0x8ee2016c, 0x8ee204d4, 0xa2e004e4, 0xaee004e0, 0xaee07264, 0xaee204e8, -0x8ee20e0c, 0x1040006a, 0x0, 0x8f830120, 0x27623800, 0x24660020, -0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 0x0, -0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8001690, 0x8ee201a0, -0x8ee2723c, 0xac62001c, 0x8ee40498, 0x8ee5049c, 0x2462001c, 0xac620008, -0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004, -0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x24100001, -0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020012, -0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, -0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, -0x10430007, 0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, -0x800167a, 0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, -0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, -0x8001690, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, -0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, -0x24425028, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, -0x5600000b, 0x24100001, 0x8ee2723c, 0x3c040001, 0x24844458, 0xafa00014, -0xafa20010, 0x8ee6723c, 0x8f470280, 0x3c050009, 0xc0023a7, 0x34a5f008, -0x56000001, 0xaee00e0c, 0x8ee20170, 0x24420001, 0xaee20170, 0x8ee20170, -0x8ee24e14, 0x10400019, 0x0, 0xaee04e14, 0x8f820040, 0x30420001, -0x14400008, 0x0, 0x8f430104, 0x24020001, 0x10620004, 0x0, -0x8f420264, 0x10400006, 0x0, 0x8ee20178, 0x24420001, 0xaee20178, -0x80016bd, 0x8ee20178, 0x8f820044, 0x34420004, 0xaf820044, 0x8ee20174, -0x24420001, 0xaee20174, 0x8ee20174, 0x8ee27268, 0x2442ff99, 0xaee27268, -0x8ee27268, 0x1c400299, 0x0, 0x8f420238, 0x10400296, 0x0, -0x8f420080, 0xaee2004c, 0x8f4200c0, 0xaee20048, 0x8f420084, 0xaee20038, -0x8f420084, 0xaee20234, 0x8f420088, 0xaee20238, 0x8f42008c, 0xaee2023c, -0x8f420090, 0xaee20240, 0x8f420094, 0xaee20244, 0x8f420098, 0xaee20248, -0x8f42009c, 0xaee2024c, 0x8f4200a0, 0xaee20250, 0x8f4200a4, 0xaee20254, -0x8f4200a8, 0xaee20258, 0x8f4200ac, 0xaee2025c, 0x8f4200b0, 0xaee20260, -0x8f4200b4, 0xaee20264, 0x8f4200b8, 0xaee20268, 0x8f4200bc, 0x24040001, -0xaee2026c, 0xaee0003c, 0x41080, 0x571021, 0x8ee3003c, 0x8c420234, -0x24840001, 0x621821, 0x2c82000f, 0xaee3003c, 0x1440fff8, 0x41080, -0x8f4200cc, 0xaee20050, 0x8f4200d0, 0xaee20054, 0x8f830120, 0x27623800, -0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, -0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8001750, -0x8ee201a0, 0x8f440208, 0x8f45020c, 0x26e20030, 0xac620008, 0x24020400, -0xa462000e, 0x2402000f, 0xac620018, 0xac60001c, 0xac640000, 0xac650004, -0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x24100001, -0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007, -0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, -0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, -0x10430007, 0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, -0x800173a, 0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, -0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, -0x8001750, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, -0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, -0x24425028, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, -0x12000206, 0x3c020400, 0xafa20018, 0x3c020001, 0x571021, 0x904283a0, -0x10400105, 0x0, 0x8ee205f8, 0x8f430228, 0x24420001, 0x304a00ff, -0x514300f7, 0xafa00010, 0x8ee205f8, 0x210c0, 0x571021, 0x8fa30018, -0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f830054, 0x8f820054, 0x24690032, -0x1221023, 0x2c420033, 0x10400067, 0x5821, 0x24180008, 0x240f000d, -0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120, 0x27623800, 0x24e80020, -0x102102b, 0x50400001, 0x27683000, 0x8f820128, 0x15020007, 0x1021, -0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x80017cb, 0x8ee201a0, -0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, -0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee205f8, -0xa4f8000e, 0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 0x2e21021, -0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 0x14400033, -0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, -0x144d001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, -0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, -0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, -0x80017b8, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, -0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, -0x80017cb, 0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 0x1021, -0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, -0x2e22021, 0xac8d0000, 0xac8e0004, 0x56000006, 0x240b0001, 0x8f820054, -0x1221023, 0x2c420033, 0x1440ffa0, 0x0, 0x316300ff, 0x24020001, -0x14620074, 0x3c050009, 0xaeea05f8, 0x8f830054, 0x8f820054, 0x24690032, -0x1221023, 0x2c420033, 0x1040005e, 0x5821, 0x240d0008, 0x240c0011, -0x24080012, 0x24070040, 0x240a0001, 0x8f830120, 0x27623800, 0x24660020, -0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 0x0, -0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8001834, 0x8ee201a0, -0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494, 0x2462001c, 0xac620008, -0xa46d000e, 0xac6c0018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, -0xaf860120, 0x92e24e10, 0x14400033, 0x24100001, 0x8ee24e20, 0x210c0, -0x24425028, 0x2e22021, 0x8c820000, 0x1448001f, 0x0, 0x8ee34e20, -0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001, 0xac820004, -0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10470007, 0x0, 0x8ee24e24, -0x24420001, 0x10620005, 0x0, 0x8001821, 0x0, 0x14600005, -0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, -0x2c420011, 0x50400010, 0xac800000, 0x8001834, 0x0, 0x8ee24e20, -0x24420001, 0x50470003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, -0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0xac880000, 0xac8a0004, -0x56000006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa9, -0x0, 0x316300ff, 0x24020001, 0x14620003, 0x3c050009, 0x800194b, -0x24100001, 0x3c040001, 0x24844464, 0xafa00010, 0xafa00014, 0x8f860120, -0x8f870124, 0x8001850, 0x34a5f011, 0x3c040001, 0x24844470, 0xafa00010, -0xafa00014, 0x8f860120, 0x8f870124, 0x34a5f010, 0xc0023a7, 0x8021, -0x800194b, 0x0, 0x3c040001, 0x2484447c, 0xafa00014, 0x8ee605f8, -0x8f470228, 0x3c050009, 0x8001944, 0x34a5f00f, 0x8ee205f8, 0x8f430228, -0x24420001, 0x304900ff, 0x512300dc, 0xafa00010, 0x8ee205f8, 0x210c0, -0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f870120, +0x24100001, 0x8ee2723c, 0x3c040001, 0x24844658, 0xafa00014, 0xafa20010, +0x8ee6723c, 0x8f470280, 0x3c050009, 0xc002403, 0x34a5f008, 0x56000001, +0xaee00e0c, 0x8ee20170, 0x24420001, 0xaee20170, 0x8ee20170, 0x8ee24e14, +0x10400019, 0x0, 0xaee04e14, 0x8f820040, 0x30420001, 0x14400008, +0x0, 0x8f430104, 0x24020001, 0x10620004, 0x0, 0x8f420264, +0x10400006, 0x0, 0x8ee20178, 0x24420001, 0xaee20178, 0x80016da, +0x8ee20178, 0x8f820044, 0x34420004, 0xaf820044, 0x8ee20174, 0x24420001, +0xaee20174, 0x8ee20174, 0x8ee27268, 0x2442ff99, 0xaee27268, 0x8ee27268, +0x1c4002a8, 0x0, 0x8f420238, 0x104002a5, 0x0, 0x8f420080, +0xaee2004c, 0x8f4200c0, 0xaee20048, 0x8f420084, 0xaee20038, 0x8f420084, +0xaee20234, 0x8f420088, 0xaee20238, 0x8f42008c, 0xaee2023c, 0x8f420090, +0xaee20240, 0x8f420094, 0xaee20244, 0x8f420098, 0xaee20248, 0x8f42009c, +0xaee2024c, 0x8f4200a0, 0xaee20250, 0x8f4200a4, 0xaee20254, 0x8f4200a8, +0xaee20258, 0x8f4200ac, 0xaee2025c, 0x8f4200b0, 0xaee20260, 0x8f4200b4, +0xaee20264, 0x8f4200b8, 0xaee20268, 0x8f4200bc, 0x24040001, 0xaee2026c, +0xaee0003c, 0x41080, 0x571021, 0x8ee3003c, 0x8c420234, 0x24840001, +0x621821, 0x2c82000f, 0xaee3003c, 0x1440fff8, 0x41080, 0x8f4200cc, +0xaee20050, 0x8f4200d0, 0xaee20054, 0x8f830120, 0x27623800, 0x24660020, +0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, +0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x8021, 0x24420001, +0xaee201a0, 0x8001770, 0x8ee201a0, 0x8f440208, 0x8f45020c, 0x26e20030, +0xac620008, 0x24020400, 0xa462000e, 0x2402000f, 0xac620018, 0xac60001c, +0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, +0x14400037, 0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, +0x8c830000, 0x24020007, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, +0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, +0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24, 0x24420001, +0x10a20005, 0x0, 0x800175a, 0x0, 0x14a00005, 0x0, +0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, +0x50400013, 0xac800000, 0x8001770, 0x0, 0x8ee24e20, 0x24030040, +0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, +0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020007, 0xac820000, +0x24020001, 0xac820004, 0x12000212, 0x3c020400, 0xafa20018, 0x3c020001, +0x571021, 0x904283a0, 0x1040010b, 0x0, 0x8ee205f8, 0x8f430228, +0x24420001, 0x304a00ff, 0x514300fd, 0xafa00010, 0x8ee205f8, 0x210c0, +0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f830054, +0x8f820054, 0x24690032, 0x1221023, 0x2c420033, 0x1040006a, 0x5821, +0x24180008, 0x240f000d, 0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120, 0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128, -0x15020007, 0x1021, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, -0x80018c9, 0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, -0x8ee50434, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, -0xace50004, 0x8ee305f8, 0x24020008, 0xa4e2000e, 0x2402000d, 0xace20018, -0xace9001c, 0x318c0, 0x246305fc, 0x2e31021, 0xace20008, 0x8ee204b4, -0xace20010, 0xaf880120, 0x92e24e10, 0x14400037, 0x24100001, 0x8ee24e20, -0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 0x1462001f, +0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, 0x8ee201a0, +0x8021, 0x24420001, 0xaee201a0, 0x80017ee, 0x8ee201a0, 0x8ee405f8, +0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b, +0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee205f8, 0xa4f8000e, +0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 0x2e21021, 0xace20008, +0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 0x14400033, 0x24100001, +0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x144d001f, +0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, +0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x104c0007, +0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x80017db, +0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, +0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x80017ee, +0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 0x1021, 0x8ee24e20, +0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, +0xac8d0000, 0xac8e0004, 0x56000006, 0x240b0001, 0x8f820054, 0x1221023, +0x2c420033, 0x1440ff9d, 0x0, 0x316300ff, 0x24020001, 0x14620077, +0x3c050009, 0xaeea05f8, 0x8f830054, 0x8f820054, 0x24690032, 0x1221023, +0x2c420033, 0x10400061, 0x5821, 0x240d0008, 0x240c0011, 0x24080012, +0x24070040, 0x240a0001, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, +0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124, +0x14c20007, 0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, +0x800185a, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494, +0x2462001c, 0xac620008, 0xa46d000e, 0xac6c0018, 0xac640000, 0xac650004, +0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400033, 0x24100001, +0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x1448001f, +0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, +0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10470007, +0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x8001847, +0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, +0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x800185a, +0x0, 0x8ee24e20, 0x24420001, 0x50470003, 0x1021, 0x8ee24e20, +0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, +0xac880000, 0xac8a0004, 0x56000006, 0x240b0001, 0x8f820054, 0x1221023, +0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, 0x14620003, +0x3c050009, 0x8001977, 0x24100001, 0x3c040001, 0x24844664, 0xafa00010, +0xafa00014, 0x8f860120, 0x8f870124, 0x8001876, 0x34a5f011, 0x3c040001, +0x24844670, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x34a5f010, +0xc002403, 0x8021, 0x8001977, 0x0, 0x3c040001, 0x2484467c, +0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0x8001970, 0x34a5f00f, +0x8ee205f8, 0x8f430228, 0x24420001, 0x304900ff, 0x512300e2, 0xafa00010, +0x8ee205f8, 0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, +0xac440600, 0x8f870120, 0x27623800, 0x24e80020, 0x102102b, 0x50400001, +0x27683000, 0x8f820128, 0x11020004, 0x0, 0x8f820124, 0x15020007, +0x1021, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x80018f2, +0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, +0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, +0x8ee305f8, 0x24020008, 0xa4e2000e, 0x2402000d, 0xace20018, 0xace9001c, +0x318c0, 0x246305fc, 0x2e31021, 0xace20008, 0x8ee204b4, 0xace20010, +0xaf880120, 0x92e24e10, 0x14400037, 0x24100001, 0x8ee24e20, 0x210c0, +0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 0x1462001f, 0x0, +0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, +0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 0x0, +0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x80018dc, 0x0, +0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, +0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x80018f2, 0x0, +0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20, +0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, +0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x5600000c, 0xaee905f8, +0x3c040001, 0x24844688, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, +0x3c050009, 0xc002403, 0x34a5f000, 0x8001977, 0x0, 0x8f830120, +0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, +0x10c20004, 0x0, 0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, +0x8021, 0x24420001, 0xaee201a0, 0x8001959, 0x8ee201a0, 0x8ee205f8, +0xac62001c, 0x8ee40490, 0x8ee50494, 0x2462001c, 0xac620008, 0x24020008, +0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, +0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x24100001, 0x8ee24e20, +0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, -0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x80018b3, +0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x8001943, 0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, -0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x80018c9, +0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x8001959, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, -0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x5600000c, -0xaee905f8, 0x3c040001, 0x24844488, 0xafa00010, 0xafa00014, 0x8ee605f8, -0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f000, 0x800194b, 0x0, -0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, -0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, 0x8021, 0x24420001, -0xaee201a0, 0x800192d, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, -0x8ee50494, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, -0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, -0x92e24e10, 0x14400037, 0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, -0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0, 0x8ee34e20, -0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, -0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24, -0x24420001, 0x10a20005, 0x0, 0x8001917, 0x0, 0x14a00005, -0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, -0x2c420011, 0x50400013, 0xac800000, 0x800192d, 0x0, 0x8ee24e20, -0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, -0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020012, -0xac820000, 0x24020001, 0xac820004, 0x5600001d, 0x24100001, 0x3c040001, -0x24844490, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, -0xc0023a7, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x800194b, -0x8ee201ac, 0x3c040001, 0x2484449c, 0xafa00014, 0x8ee605f8, 0x8f470228, -0x3c050009, 0x34a5f005, 0xc0023a7, 0x0, 0x8ee201a8, 0x8021, -0x24420001, 0xaee201a8, 0x8ee201a8, 0x1200000c, 0x24020001, 0x3c010001, -0x370821, 0xa02083a0, 0x8f420238, 0x8ee30154, 0x24630001, 0xaee30154, -0x8ee30154, 0x800195b, 0xaee27268, 0x24020001, 0x3c010001, 0x370821, -0xa02283a0, 0x3c020001, 0x8c424dfc, 0x10400181, 0x0, 0x8ee27b74, -0x24430001, 0x284200c9, 0x1440019e, 0xaee37b74, 0x8ee204c4, 0x30420002, -0x14400113, 0xaee07b74, 0x8ee204c4, 0x3c030600, 0x34631000, 0x34420002, -0xaee204c4, 0xafa30018, 0x8ee205f8, 0x8f430228, 0x24420001, 0x304a00ff, -0x514300f7, 0xafa00010, 0x8ee205f8, 0x210c0, 0x571021, 0x8fa30018, -0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f830054, 0x8f820054, 0x24690032, -0x1221023, 0x2c420033, 0x10400067, 0x5821, 0x24180008, 0x240f000d, -0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120, 0x27623800, 0x24e80020, -0x102102b, 0x50400001, 0x27683000, 0x8f820128, 0x15020007, 0x1021, -0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x80019e1, 0x8ee201a0, -0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, -0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee205f8, -0xa4f8000e, 0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 0x2e21021, -0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 0x14400033, -0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, -0x144d001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, -0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, -0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, -0x80019ce, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, -0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, -0x80019e1, 0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 0x1021, -0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, -0x2e22021, 0xac8d0000, 0xac8e0004, 0x56000006, 0x240b0001, 0x8f820054, -0x1221023, 0x2c420033, 0x1440ffa0, 0x0, 0x316300ff, 0x24020001, -0x54620075, 0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054, 0x24690032, -0x1221023, 0x2c420033, 0x1040005e, 0x5821, 0x240d0008, 0x240c0011, -0x24080012, 0x24070040, 0x240a0001, 0x8f830120, 0x27623800, 0x24660020, -0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 0x0, -0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8001a4a, 0x8ee201a0, -0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494, 0x2462001c, 0xac620008, -0xa46d000e, 0xac6c0018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, -0xaf860120, 0x92e24e10, 0x14400033, 0x24100001, 0x8ee24e20, 0x210c0, -0x24425028, 0x2e22021, 0x8c820000, 0x1448001f, 0x0, 0x8ee34e20, -0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001, 0xac820004, -0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10470007, 0x0, 0x8ee24e24, -0x24420001, 0x10620005, 0x0, 0x8001a37, 0x0, 0x14600005, -0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, -0x2c420011, 0x50400010, 0xac800000, 0x8001a4a, 0x0, 0x8ee24e20, -0x24420001, 0x50470003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, -0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0xac880000, 0xac8a0004, -0x56000006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa9, -0x0, 0x316300ff, 0x24020001, 0x10620022, 0x0, 0x3c040001, -0x24844464, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, -0xc0023a7, 0x34a5f011, 0x8001a76, 0x0, 0x3c040001, 0x24844470, -0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc0023a7, 0x34a5f010, -0x8001a76, 0x0, 0x3c040001, 0x2484447c, 0xafa00014, 0x8ee605f8, -0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f00f, 0x8ee201a8, 0x24420001, -0xaee201a8, 0x8ee201a8, 0x8ee20158, 0x24420001, 0xaee20158, 0x8ee20158, -0x8ee204c4, 0x30420001, 0x10400055, 0x0, 0x8f420218, 0x30420080, -0x10400029, 0x0, 0x8f820044, 0x34420040, 0xaf820044, 0x8ee27b6c, -0x402821, 0x8ee200c0, 0x8ee300c4, 0x24060000, 0x2407ffff, 0x2021, -0x461024, 0x1444000d, 0x671824, 0x1465000b, 0x0, 0x8ee27b70, -0x402821, 0x8ee200e0, 0x8ee300e4, 0x2021, 0x461024, 0x14440003, -0x671824, 0x1065000b, 0x0, 0x8ee200c0, 0x8ee300c4, 0x8ee400e0, -0x8ee500e4, 0xaee37b6c, 0xaee57b70, 0x8f820044, 0x38420020, 0x8001b01, -0xaf820044, 0x8f820044, 0x2403ffdf, 0x431024, 0x8001b01, 0xaf820044, -0x8f820044, 0x2403ffdf, 0x431024, 0xaf820044, 0x8ee27b6c, 0x402821, -0x8ee200c0, 0x8ee300c4, 0x24060000, 0x2407ffff, 0x2021, 0x461024, -0x1444000d, 0x671824, 0x1465000b, 0x0, 0x8ee27b70, 0x402821, -0x8ee200e0, 0x8ee300e4, 0x2021, 0x461024, 0x14440003, 0x671824, -0x1065000b, 0x0, 0x8ee200c0, 0x8ee300c4, 0x8ee400e0, 0x8ee500e4, -0xaee37b6c, 0xaee57b70, 0x8f820044, 0x38420040, 0x8001b01, 0xaf820044, -0x8f820044, 0x34420040, 0x8001b01, 0xaf820044, 0x8f820044, 0x34420040, -0xaf820044, 0x8ee27b7c, 0x24430001, 0x28420015, 0x14400028, 0xaee37b7c, -0x8f820044, 0x38420020, 0xaf820044, 0x8001b01, 0xaee07b7c, 0x8ee204c4, -0x30420001, 0x10400011, 0x0, 0x8f420218, 0x30420080, 0x10400009, -0x0, 0x8f820044, 0x34420020, 0xaf820044, 0x8f820044, 0x2403ffbf, -0x431024, 0x8001aff, 0xaf820044, 0x8f820044, 0x34420060, 0x8001aff, -0xaf820044, 0x8f820044, 0x34420040, 0xaf820044, 0x8ee27b78, 0x24430001, -0x28421389, 0x14400005, 0xaee37b78, 0x8f820044, 0x38420020, 0xaf820044, -0xaee07b78, 0xc0044fc, 0x0, 0x8fbf0024, 0x8fb00020, 0x3e00008, -0x27bd0028, 0x0, 0x0, 0x0, 0x27bdffb8, 0xafbf0044, +0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x5600001d, +0x24100001, 0x3c040001, 0x24844690, 0xafa00010, 0xafa00014, 0x8ee605f8, +0x8f470228, 0x3c050009, 0xc002403, 0x34a5f001, 0x8ee201ac, 0x24420001, +0xaee201ac, 0x8001977, 0x8ee201ac, 0x3c040001, 0x2484469c, 0xafa00014, +0x8ee605f8, 0x8f470228, 0x3c050009, 0x34a5f005, 0xc002403, 0x0, +0x8ee201a8, 0x8021, 0x24420001, 0xaee201a8, 0x8ee201a8, 0x1200000c, +0x24020001, 0x3c010001, 0x370821, 0xa02083a0, 0x8f420238, 0x8ee30154, +0x24630001, 0xaee30154, 0x8ee30154, 0x8001987, 0xaee27268, 0x24020001, +0x3c010001, 0x370821, 0xa02283a0, 0x3c020001, 0x8c42500c, 0x10400187, +0x0, 0x8ee27b74, 0x24430001, 0x284200c9, 0x144001a4, 0xaee37b74, +0x8ee204c4, 0x30420002, 0x14400119, 0xaee07b74, 0x8ee204c4, 0x3c030600, +0x34631000, 0x34420002, 0xaee204c4, 0xafa30018, 0x8ee205f8, 0x8f430228, +0x24420001, 0x304a00ff, 0x514300fd, 0xafa00010, 0x8ee205f8, 0x210c0, +0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f830054, +0x8f820054, 0x24690032, 0x1221023, 0x2c420033, 0x1040006a, 0x5821, +0x24180008, 0x240f000d, 0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120, +0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128, +0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, 0x8ee201a0, +0x8021, 0x24420001, 0xaee201a0, 0x8001a10, 0x8ee201a0, 0x8ee405f8, +0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b, +0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee205f8, 0xa4f8000e, +0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 0x2e21021, 0xace20008, +0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 0x14400033, 0x24100001, +0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x144d001f, +0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, +0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x104c0007, +0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x80019fd, +0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, +0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x8001a10, +0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 0x1021, 0x8ee24e20, +0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, +0xac8d0000, 0xac8e0004, 0x56000006, 0x240b0001, 0x8f820054, 0x1221023, +0x2c420033, 0x1440ff9d, 0x0, 0x316300ff, 0x24020001, 0x54620078, +0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054, 0x24690032, 0x1221023, +0x2c420033, 0x10400061, 0x5821, 0x240d0008, 0x240c0011, 0x24080012, +0x24070040, 0x240a0001, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, +0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124, +0x14c20007, 0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, +0x8001a7c, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494, +0x2462001c, 0xac620008, 0xa46d000e, 0xac6c0018, 0xac640000, 0xac650004, +0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400033, 0x24100001, +0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x1448001f, +0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, +0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10470007, +0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x8001a69, +0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, +0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x8001a7c, +0x0, 0x8ee24e20, 0x24420001, 0x50470003, 0x1021, 0x8ee24e20, +0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, +0xac880000, 0xac8a0004, 0x56000006, 0x240b0001, 0x8f820054, 0x1221023, +0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, 0x10620022, +0x0, 0x3c040001, 0x24844664, 0xafa00010, 0xafa00014, 0x8f860120, +0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011, 0x8001aa8, 0x0, +0x3c040001, 0x24844670, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, +0xc002403, 0x34a5f010, 0x8001aa8, 0x0, 0x3c040001, 0x2484467c, +0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f00f, +0x8ee201a8, 0x24420001, 0xaee201a8, 0x8ee201a8, 0x8ee20158, 0x24420001, +0xaee20158, 0x8ee20158, 0x8ee204c4, 0x30420001, 0x10400055, 0x0, +0x8f420218, 0x30420080, 0x10400029, 0x0, 0x8f820044, 0x34420040, +0xaf820044, 0x8ee27b6c, 0x402821, 0x8ee200c0, 0x8ee300c4, 0x24060000, +0x2407ffff, 0x2021, 0x461024, 0x1444000d, 0x671824, 0x1465000b, +0x0, 0x8ee27b70, 0x402821, 0x8ee200e0, 0x8ee300e4, 0x2021, +0x461024, 0x14440003, 0x671824, 0x1065000b, 0x0, 0x8ee200c0, +0x8ee300c4, 0x8ee400e0, 0x8ee500e4, 0xaee37b6c, 0xaee57b70, 0x8f820044, +0x38420020, 0x8001b33, 0xaf820044, 0x8f820044, 0x2403ffdf, 0x431024, +0x8001b33, 0xaf820044, 0x8f820044, 0x2403ffdf, 0x431024, 0xaf820044, +0x8ee27b6c, 0x402821, 0x8ee200c0, 0x8ee300c4, 0x24060000, 0x2407ffff, +0x2021, 0x461024, 0x1444000d, 0x671824, 0x1465000b, 0x0, +0x8ee27b70, 0x402821, 0x8ee200e0, 0x8ee300e4, 0x2021, 0x461024, +0x14440003, 0x671824, 0x1065000b, 0x0, 0x8ee200c0, 0x8ee300c4, +0x8ee400e0, 0x8ee500e4, 0xaee37b6c, 0xaee57b70, 0x8f820044, 0x38420040, +0x8001b33, 0xaf820044, 0x8f820044, 0x34420040, 0x8001b33, 0xaf820044, +0x8f820044, 0x34420040, 0xaf820044, 0x8ee27b7c, 0x24430001, 0x28420015, +0x14400028, 0xaee37b7c, 0x8f820044, 0x38420020, 0xaf820044, 0x8001b33, +0xaee07b7c, 0x8ee204c4, 0x30420001, 0x10400011, 0x0, 0x8f420218, +0x30420080, 0x10400009, 0x0, 0x8f820044, 0x34420020, 0xaf820044, +0x8f820044, 0x2403ffbf, 0x431024, 0x8001b31, 0xaf820044, 0x8f820044, +0x34420060, 0x8001b31, 0xaf820044, 0x8f820044, 0x34420040, 0xaf820044, +0x8ee27b78, 0x24430001, 0x28421389, 0x14400005, 0xaee37b78, 0x8f820044, +0x38420020, 0xaf820044, 0xaee07b78, 0xc00457c, 0x0, 0x8fbf0024, +0x8fb00020, 0x3e00008, 0x27bd0028, 0x0, 0x27bdffb8, 0xafbf0044, 0xafb60040, 0xafb5003c, 0xafb40038, 0xafb30034, 0xafb20030, 0xafb1002c, 0xafb00028, 0x8f960064, 0x32c20004, 0x1040000c, 0x24020004, 0xaf820064, 0x8f420114, 0xaee204d0, 0x8f820060, 0x34420008, 0xaf820060, 0x8ee20168, -0x24420001, 0xaee20168, 0x8002293, 0x8ee20168, 0x32c20001, 0x10400004, -0x24020001, 0xaf820064, 0x8002293, 0x0, 0x32c20002, 0x1040076b, -0x0, 0x8f43022c, 0x8f42010c, 0x5062000c, 0xafa00010, 0x8f42022c, -0x21080, 0x5a1021, 0x8c420300, 0xafa20020, 0x8f42022c, 0x24070001, -0x24420001, 0x3042003f, 0x8001b41, 0xaf42022c, 0x3c040001, 0x24844510, -0xafa00014, 0x8f46022c, 0x8f47010c, 0x3c050003, 0xc0023a7, 0x34a5f01f, -0x3821, 0x14e00003, 0x0, 0x800228c, 0xaf960064, 0x93a20020, -0x2443ffff, 0x2c620011, 0x1040063c, 0x31080, 0x3c010001, 0x220821, -0x8c2245c8, 0x400008, 0x0, 0x8fa20020, 0x30420fff, 0xaee20dfc, -0x8f820060, 0x34420200, 0xaf820060, 0x8ee20118, 0x24420001, 0xaee20118, -0x8002287, 0x8ee20118, 0x8fa20020, 0x24030001, 0x3c010001, 0x370821, -0xa02383a1, 0x30420fff, 0xaee25228, 0x8f820060, 0x34420100, 0xaf820060, -0x8ee20144, 0x24420001, 0xaee20144, 0x8002287, 0x8ee20144, 0x8fa20020, -0x21200, 0x22502, 0x24020001, 0x10820005, 0x24020002, 0x10820009, -0x2402fffe, 0x8001b8a, 0xafa00010, 0x8ee204c4, 0xaee40070, 0xaee40074, -0x34420001, 0x8001b7e, 0xaee204c4, 0x8ee304c4, 0xaee40070, 0xaee40074, -0x621824, 0xaee304c4, 0x8f840054, 0x41442, 0x41c82, 0x431021, -0x41cc2, 0x431023, 0x41d02, 0x431021, 0x41d42, 0x431023, -0x8001b91, 0xaee20078, 0x3c040001, 0x2484451c, 0xafa00014, 0x8fa60020, -0x3c050003, 0xc0023a7, 0x34a50004, 0x8ee20110, 0x24420001, 0xaee20110, -0x8002287, 0x8ee20110, 0x27440212, 0xc00229d, 0x24050006, 0x3049001f, -0x920c0, 0x2e41021, 0x9442726c, 0x30424000, 0x1040000a, 0x971021, -0x97430212, 0xa443726e, 0x8f430214, 0x971021, 0xac437270, 0x2e41821, -0x34028000, 0x8001c38, 0xa462726c, 0x9443726e, 0x97420212, 0x14620006, -0x2e41021, 0x971021, 0x8c437270, 0x8f420214, 0x1062009d, 0x2e41021, -0x9442726c, 0x30428000, 0x10400028, 0x2406ffff, 0x2021, 0x410c0, -0x2e21021, 0x9442736c, 0x30424000, 0x54400005, 0x803021, 0x24840001, -0x2c820080, 0x1440fff8, 0x410c0, 0x4c10010, 0x620c0, 0x610c0, -0x571821, 0x8c63736c, 0x571021, 0xafa30010, 0x8c427370, 0x3c040001, -0x24844528, 0xafa20014, 0x8f470214, 0x3c050003, 0xc0023a7, 0x34a50013, -0x8001c4f, 0x3c020800, 0x97430212, 0x971021, 0xa443736e, 0x8f430214, -0x971021, 0xac437370, 0x910c0, 0x2e21021, 0x2e41821, 0x8001c36, -0xa446726c, 0x2e41021, 0x9445726c, 0x8001bed, 0x510c0, 0x9443736e, -0x97420212, 0x14620006, 0x510c0, 0x971021, 0x8c437370, 0x8f420214, -0x10620065, 0x510c0, 0x2e21021, 0x9445736c, 0x510c0, 0x2e21021, -0x9442736c, 0x30428000, 0x1040fff0, 0x971021, 0x520c0, 0x971021, -0x9443736e, 0x97420212, 0x14620006, 0x2406ffff, 0x971021, 0x8c437370, -0x8f420214, 0x10620053, 0x3c020800, 0x2021, 0x410c0, 0x2e21021, +0x24420001, 0xaee20168, 0x80022ee, 0x8ee20168, 0x32c20001, 0x10400004, +0x24020001, 0xaf820064, 0x80022ee, 0x0, 0x32c20002, 0x1440000c, +0x3c050003, 0x3c040001, 0x24844714, 0x34a50001, 0x2c03021, 0x3821, +0xafa00010, 0xc002403, 0xafa00014, 0x2402fff8, 0x80022ee, 0xaf820064, +0x8f43022c, 0x8f42010c, 0x5062000c, 0xafa00010, 0x8f42022c, 0x21080, +0x5a1021, 0x8c420300, 0xafa20020, 0x8f42022c, 0x24070001, 0x24420001, +0x3042003f, 0x8001b7c, 0xaf42022c, 0x3c040001, 0x24844720, 0xafa00014, +0x8f46022c, 0x8f47010c, 0x3c050003, 0xc002403, 0x34a5f01f, 0x3821, +0x14e00003, 0x0, 0x80022e7, 0xaf960064, 0x93a20020, 0x2443ffff, +0x2c620011, 0x10400656, 0x31080, 0x3c010001, 0x220821, 0x8c2247d8, +0x400008, 0x0, 0x8fa20020, 0x30420fff, 0xaee20dfc, 0x8f820060, +0x34420200, 0xaf820060, 0x8ee20118, 0x24420001, 0xaee20118, 0x80022e2, +0x8ee20118, 0x8fa20020, 0x24030001, 0x3c010001, 0x370821, 0xa02383a1, +0x30420fff, 0xaee25228, 0x8f820060, 0x34420100, 0xaf820060, 0x8ee20144, +0x24420001, 0xaee20144, 0x80022e2, 0x8ee20144, 0x8fa20020, 0x21200, +0x22502, 0x24020001, 0x10820005, 0x24020002, 0x10820009, 0x2402fffe, +0x8001bc5, 0xafa00010, 0x8ee204c4, 0xaee40070, 0xaee40074, 0x34420001, +0x8001bb9, 0xaee204c4, 0x8ee304c4, 0xaee40070, 0xaee40074, 0x621824, +0xaee304c4, 0x8f840054, 0x41442, 0x41c82, 0x431021, 0x41cc2, +0x431023, 0x41d02, 0x431021, 0x41d42, 0x431023, 0x8001bcc, +0xaee20078, 0x3c040001, 0x2484472c, 0xafa00014, 0x8fa60020, 0x3c050003, +0xc002403, 0x34a50004, 0x8ee20110, 0x24420001, 0xaee20110, 0x80022e2, +0x8ee20110, 0x27440212, 0xc0022f8, 0x24050006, 0x3049001f, 0x920c0, +0x2e41021, 0x9442726c, 0x30424000, 0x1040000a, 0x971021, 0x97430212, +0xa443726e, 0x8f430214, 0x971021, 0xac437270, 0x2e41821, 0x34028000, +0x8001c75, 0xa462726c, 0x9443726e, 0x97420212, 0x14620006, 0x2e41021, +0x971021, 0x8c437270, 0x8f420214, 0x1062009f, 0x2e41021, 0x9442726c, +0x30428000, 0x1040002a, 0x2406ffff, 0x2021, 0x410c0, 0x2e21021, 0x9442736c, 0x30424000, 0x54400005, 0x803021, 0x24840001, 0x2c820080, -0x1440fff8, 0x410c0, 0x4c10023, 0x620c0, 0x910c0, 0x571821, -0x8c63726c, 0x571021, 0xafa30010, 0x8c427270, 0x3c040001, 0x24844534, -0xafa20014, 0x8f470214, 0x3c050003, 0xc0023a7, 0x34a5f017, 0x8001c4f, -0x3c020800, 0x8f430210, 0xb71021, 0xac43776c, 0x8f430214, 0xb71021, -0xac437770, 0x3c020001, 0x571021, 0x8c4283a4, 0x24420001, 0x3c010001, -0x370821, 0xac2283a4, 0x3c030001, 0x771821, 0x8c6383a4, 0x2e51021, -0x8001c41, 0xa443776c, 0x97430212, 0x971021, 0xa443736e, 0x8f430214, -0x971021, 0xac437370, 0x510c0, 0x2e21021, 0x2e41821, 0xa446736c, -0x34028000, 0xa462736c, 0x2021, 0x428c0, 0x2e51021, 0x9442776c, -0x1040ffdc, 0x24840001, 0x2c820080, 0x5440fffa, 0x428c0, 0x92e204c8, -0x10400006, 0x24020001, 0x8ee304cc, 0x1221004, 0x621825, 0x8001c4e, -0xaee304cc, 0x8f830228, 0x24020001, 0x1221004, 0x621825, 0xaf830228, -0x3c020800, 0x34421000, 0xafa20018, 0x8ee205f8, 0x8f430228, 0x24420001, -0x304a00ff, 0x514300f7, 0xafa00010, 0x8ee205f8, 0x210c0, 0x571021, -0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f830054, 0x8f820054, -0x24690032, 0x1221023, 0x2c420033, 0x10400067, 0x5821, 0x24100008, -0x240f000d, 0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120, 0x27623800, -0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128, 0x15020007, -0x1021, 0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0, 0x8001cc4, -0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, -0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, -0x8ee205f8, 0xa4f0000e, 0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, -0x2e21021, 0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, -0x14400033, 0x24070001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, -0x8c820000, 0x144d001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, -0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, -0x24420001, 0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, -0x0, 0x8001cb1, 0x0, 0x14600005, 0x0, 0x8f820128, -0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, -0xac800000, 0x8001cc4, 0x0, 0x8ee24e20, 0x24420001, 0x504c0003, -0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, -0x24425028, 0x2e22021, 0xac8d0000, 0xac8e0004, 0x54e00006, 0x240b0001, -0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa0, 0x0, 0x316300ff, -0x24020001, 0x54620075, 0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054, -0x24690032, 0x1221023, 0x2c420033, 0x1040005e, 0x5821, 0x240e0008, -0x240d0011, 0x240a0012, 0x24080040, 0x240c0001, 0x8f830120, 0x27623800, -0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, -0x0, 0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0, 0x8001d2d, -0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494, 0x2462001c, -0xac620008, 0xa46e000e, 0xac6d0018, 0xac640000, 0xac650004, 0x8ee204b4, -0xac620010, 0xaf860120, 0x92e24e10, 0x14400033, 0x24070001, 0x8ee24e20, -0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x144a001f, 0x0, -0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001, -0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10480007, 0x0, -0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x8001d1a, 0x0, -0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, -0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x8001d2d, 0x0, -0x8ee24e20, 0x24420001, 0x50480003, 0x1021, 0x8ee24e20, 0x24420001, -0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0xac8a0000, -0xac8c0004, 0x54e00006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, -0x1440ffa9, 0x0, 0x316300ff, 0x24020001, 0x10620022, 0x0, -0x3c040001, 0x24844540, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, -0x3c050009, 0xc0023a7, 0x34a5f011, 0x8001d59, 0x0, 0x3c040001, -0x2484454c, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc0023a7, -0x34a5f010, 0x8001d59, 0x0, 0x3c040001, 0x24844558, 0xafa00014, -0x8ee605f8, 0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f00f, 0x8ee201a8, -0x24420001, 0xaee201a8, 0x8ee201a8, 0x8ee20124, 0x24420001, 0xaee20124, -0x8001f47, 0x8ee20124, 0x27440212, 0xc00229d, 0x24050006, 0x3049001f, -0x928c0, 0x2e51021, 0x9442726c, 0x30428000, 0x1040002d, 0xb71021, -0x9443726e, 0x97420212, 0x1462001a, 0xb71021, 0x8c437270, 0x8f420214, -0x54620018, 0xafa20010, 0x92e204c8, 0x10400007, 0x24020001, 0x8ee304cc, -0x1221004, 0x21027, 0x621824, 0x8001d7e, 0xaee304cc, 0x8f830228, -0x1221004, 0x21027, 0x621824, 0xaf830228, 0x918c0, 0x2e31021, -0x9442726c, 0x2e31821, 0x34424000, 0x8001e04, 0xa462726c, 0x8f420214, -0xafa20010, 0x910c0, 0x571021, 0x8c42726c, 0x3c040001, 0x24844564, -0x3c050003, 0xafa20014, 0x8f470210, 0x34a5f01c, 0xc0023a7, 0x1203021, -0x8001e39, 0x3c020800, 0x9443726e, 0x97420212, 0x14620019, 0x918c0, -0xb71021, 0x8c437270, 0x8f420214, 0x14620014, 0x918c0, 0x2e51021, -0x9447726c, 0x720c0, 0x971021, 0x9443736e, 0xb71021, 0xa443726e, -0x971021, 0x8c437370, 0xb71021, 0xac437270, 0x2e41021, 0x9443736c, -0x2e51021, 0xa443726c, 0x2e41821, 0x24024000, 0x8001e04, 0xa462736c, -0x2e31021, 0x9447726c, 0x3021, 0x720c0, 0x2e41021, 0x9442736c, -0x4021, 0x30428000, 0x14400025, 0xe02821, 0x605021, 0x240b4000, -0x971021, 0x9443736e, 0x97420212, 0x54620015, 0xe02821, 0x971021, -0x8c437370, 0x8f420214, 0x54620010, 0xe02821, 0x11000006, 0x2e41021, -0x9443736c, 0x510c0, 0x2e21021, 0x8001dd0, 0xa443736c, 0x9443736c, -0x2ea1021, 0xa443726c, 0x710c0, 0x2e21021, 0xa44b736c, 0x8001dde, -0x24060001, 0x510c0, 0x2e21021, 0x9447736c, 0x720c0, 0x2e41021, -0x9442736c, 0x30428000, 0x1040ffdf, 0x25080001, 0x30c200ff, 0x14400025, -0x2021, 0x720c0, 0x971021, 0x9443736e, 0x97420212, 0x1462000f, -0x910c0, 0x971021, 0x8c437370, 0x8f420214, 0x1462000a, 0x910c0, -0x2e41821, 0x24024000, 0x15000015, 0xa462736c, 0x910c0, 0x2e21821, -0x34028000, 0x8001e04, 0xa462726c, 0x571021, 0x8c42726c, 0x3c040001, -0x24844570, 0x3c050003, 0xafa20010, 0x710c0, 0x571021, 0x8c42736c, -0x34a5001e, 0x1203021, 0xc0023a7, 0xafa20014, 0x8001e39, 0x3c020800, -0x2021, 0x428c0, 0xb71021, 0x9443776e, 0x97420212, 0x5462002b, -0x24840001, 0xb71021, 0x8c437770, 0x8f420214, 0x54620026, 0x24840001, -0x3c020001, 0x571021, 0x8c4283a4, 0x2442ffff, 0x3c010001, 0x370821, -0xac2283a4, 0x3c020001, 0x571021, 0x8c4283a4, 0x809021, 0x242102b, -0x1040000e, 0x24b1776c, 0x24b07774, 0x2f02021, 0x2f12821, 0xc002434, -0x24060008, 0x26310008, 0x3c020001, 0x571021, 0x8c4283a4, 0x26520001, -0x242102b, 0x1440fff5, 0x26100008, 0x3c040001, 0x972021, 0x8c8483a4, -0x24050008, 0x420c0, 0x2484776c, 0xc00242c, 0x2e42021, 0x8001e39, -0x3c020800, 0x2c820080, 0x1440ffcf, 0x428c0, 0x3c020800, 0x34422000, -0xafa20018, 0x8ee205f8, 0x8f430228, 0x24420001, 0x304a00ff, 0x514300f7, -0xafa00010, 0x8ee205f8, 0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c, -0xac4305fc, 0xac440600, 0x8f830054, 0x8f820054, 0x24690032, 0x1221023, -0x2c420033, 0x10400067, 0x5821, 0x24100008, 0x240f000d, 0x240d0007, -0x240c0040, 0x240e0001, 0x8f870120, 0x27623800, 0x24e80020, 0x102102b, -0x50400001, 0x27683000, 0x8f820128, 0x15020007, 0x1021, 0x8ee201a0, -0x3821, 0x24420001, 0xaee201a0, 0x8001eae, 0x8ee201a0, 0x8ee405f8, +0x1440fff8, 0x410c0, 0x4c10010, 0x618c0, 0x610c0, 0x571821, +0x8c63736c, 0x571021, 0xafa30010, 0x8c427370, 0x3c040001, 0x24844738, +0xafa20014, 0x8f470214, 0x3c050003, 0xc002403, 0x34a50013, 0x8001c8c, +0x3c020800, 0x97440212, 0x771021, 0xa444736e, 0x8f440214, 0x771021, +0x2e31821, 0xac447370, 0x34028000, 0xa462736c, 0x910c0, 0x2e21021, +0x8001c75, 0xa446726c, 0x2e41021, 0x9445726c, 0x8001c2a, 0x510c0, +0x9443736e, 0x97420212, 0x14620006, 0x510c0, 0x971021, 0x8c437370, +0x8f420214, 0x10620065, 0x510c0, 0x2e21021, 0x9445736c, 0x510c0, +0x2e21021, 0x9442736c, 0x30428000, 0x1040fff0, 0x971021, 0x520c0, +0x971021, 0x9443736e, 0x97420212, 0x14620006, 0x2406ffff, 0x971021, +0x8c437370, 0x8f420214, 0x10620053, 0x3c020800, 0x2021, 0x410c0, +0x2e21021, 0x9442736c, 0x30424000, 0x54400005, 0x803021, 0x24840001, +0x2c820080, 0x1440fff8, 0x410c0, 0x4c10023, 0x618c0, 0x910c0, +0x571821, 0x8c63726c, 0x571021, 0xafa30010, 0x8c427270, 0x3c040001, +0x24844744, 0xafa20014, 0x8f470214, 0x3c050003, 0xc002403, 0x34a5f017, +0x8001c8c, 0x3c020800, 0x8f430210, 0xb71021, 0xac43776c, 0x8f430214, +0xb71021, 0xac437770, 0x3c020001, 0x571021, 0x8c4283a4, 0x24420001, +0x3c010001, 0x370821, 0xac2283a4, 0x3c030001, 0x771821, 0x8c6383a4, +0x2e51021, 0x8001c7e, 0xa443776c, 0x97440212, 0x771021, 0xa444736e, +0x8f440214, 0x771021, 0x2e31821, 0xac447370, 0x34028000, 0xa462736c, +0x510c0, 0x2e21021, 0xa446736c, 0x2021, 0x428c0, 0x2e51021, +0x9442776c, 0x1040ffdc, 0x24840001, 0x2c820080, 0x5440fffa, 0x428c0, +0x92e204c8, 0x10400006, 0x24020001, 0x8ee304cc, 0x1221004, 0x621825, +0x8001c8b, 0xaee304cc, 0x8f830228, 0x24020001, 0x1221004, 0x621825, +0xaf830228, 0x3c020800, 0x34421000, 0xafa20018, 0x8ee205f8, 0x8f430228, +0x24420001, 0x304a00ff, 0x514300fd, 0xafa00010, 0x8ee205f8, 0x210c0, +0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f830054, +0x8f820054, 0x24690032, 0x1221023, 0x2c420033, 0x1040006a, 0x5821, +0x24100008, 0x240f000d, 0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120, +0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128, +0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, 0x8ee201a0, +0x3821, 0x24420001, 0xaee201a0, 0x8001d04, 0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee205f8, 0xa4f0000e, 0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 0x2e21021, 0xace20008, @@ -635,707 +564,800 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] = { 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x144d001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x104c0007, -0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x8001e9b, +0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x8001cf1, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, -0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x8001eae, +0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x8001d04, 0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0xac8d0000, 0xac8e0004, 0x54e00006, 0x240b0001, 0x8f820054, 0x1221023, -0x2c420033, 0x1440ffa0, 0x0, 0x316300ff, 0x24020001, 0x54620075, +0x2c420033, 0x1440ff9d, 0x0, 0x316300ff, 0x24020001, 0x54620078, 0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054, 0x24690032, 0x1221023, -0x2c420033, 0x1040005e, 0x5821, 0x240e0008, 0x240d0011, 0x240a0012, +0x2c420033, 0x10400061, 0x5821, 0x240e0008, 0x240d0011, 0x240a0012, 0x24080040, 0x240c0001, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, -0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, -0x3821, 0x24420001, 0xaee201a0, 0x8001f17, 0x8ee201a0, 0x8ee205f8, -0xac62001c, 0x8ee40490, 0x8ee50494, 0x2462001c, 0xac620008, 0xa46e000e, -0xac6d0018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, -0x92e24e10, 0x14400033, 0x24070001, 0x8ee24e20, 0x210c0, 0x24425028, -0x2e22021, 0x8c820000, 0x144a001f, 0x0, 0x8ee34e20, 0x8ee24e24, -0x1062001b, 0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, -0x8ee34e20, 0x24420001, 0x10480007, 0x0, 0x8ee24e24, 0x24420001, -0x10620005, 0x0, 0x8001f04, 0x0, 0x14600005, 0x0, -0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, -0x50400010, 0xac800000, 0x8001f17, 0x0, 0x8ee24e20, 0x24420001, -0x50480003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, -0x210c0, 0x24425028, 0x2e22021, 0xac8a0000, 0xac8c0004, 0x54e00006, -0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa9, 0x0, -0x316300ff, 0x24020001, 0x10620022, 0x0, 0x3c040001, 0x24844540, -0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc0023a7, -0x34a5f011, 0x8001f43, 0x0, 0x3c040001, 0x2484454c, 0xafa00014, -0x8f860120, 0x8f870124, 0x3c050009, 0xc0023a7, 0x34a5f010, 0x8001f43, -0x0, 0x3c040001, 0x24844558, 0xafa00014, 0x8ee605f8, 0x8f470228, -0x3c050009, 0xc0023a7, 0x34a5f00f, 0x8ee201a8, 0x24420001, 0xaee201a8, -0x8ee201a8, 0x8ee20128, 0x24420001, 0xaee20128, 0x8ee20128, 0x8ee20160, -0x24420001, 0xaee20160, 0x8002287, 0x8ee20160, 0x8fa20020, 0x21200, -0x21d02, 0x24020001, 0x10620005, 0x24020002, 0x1062000d, 0x0, -0x8001f67, 0xafa00010, 0x92e204c8, 0x14400006, 0x24020001, 0x8f820228, -0xaee204cc, 0x2402ffff, 0xaf820228, 0x24020001, 0x8001f6e, 0xa2e204c8, -0x92e204c8, 0x5040000c, 0xa2e004c8, 0x8ee204cc, 0xaf820228, 0x8001f6e, -0xa2e004c8, 0x3c040001, 0x24844578, 0xafa00014, 0x8fa60020, 0x3c050003, -0xc0023a7, 0x34a5f009, 0x8ee2013c, 0x24420001, 0xaee2013c, 0x8002287, -0x8ee2013c, 0x8fa20020, 0x21200, 0x22502, 0x24020001, 0x10820005, -0x24020002, 0x1082000f, 0x0, 0x8001f93, 0xafa00010, 0x8f820220, -0x3c0308ff, 0x3463ffff, 0x431024, 0x34420008, 0xaf820220, 0x24020001, -0x3c010001, 0x370821, 0xa02283a2, 0x8001f9a, 0xaee40108, 0x8f820220, -0x3c0308ff, 0x3463fff7, 0x431024, 0xaf820220, 0x3c010001, 0x370821, -0xa02083a2, 0x8001f9a, 0xaee40108, 0x3c040001, 0x24844584, 0xafa00014, -0x8fa60020, 0x3c050003, 0xc0023a7, 0x34a5f00a, 0x8ee2012c, 0x24420001, -0xaee2012c, 0x8002287, 0x8ee2012c, 0x8fa20020, 0x21200, 0x21d02, -0x24020001, 0x10620005, 0x24020002, 0x1062000e, 0x0, 0x8001fc1, -0xafa00010, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420008, -0xaf820220, 0x24020001, 0x3c010001, 0x370821, 0x8001fc8, 0xa02283a3, -0x3c020001, 0x571021, 0x904283a2, 0x3c010001, 0x370821, 0x1440000e, -0xa02083a3, 0x8f820220, 0x3c0308ff, 0x3463fff7, 0x431024, 0x8001fc8, -0xaf820220, 0x3c040001, 0x24844590, 0xafa00014, 0x8fa60020, 0x3c050003, -0xc0023a7, 0x34a5f00b, 0x8ee20114, 0x24420001, 0xaee20114, 0x8002287, -0x8ee20114, 0x27840208, 0x27450200, 0xc00243e, 0x24060008, 0x26e40094, -0x27450200, 0xc00243e, 0x24060008, 0x8ee20134, 0x24420001, 0xaee20134, -0x8002287, 0x8ee20134, 0x8f460248, 0x24040001, 0xc004e2c, 0x24050004, -0x8ee20130, 0x24420001, 0xaee20130, 0x8002287, 0x8ee20130, 0x8ef301c4, -0x8ef401c8, 0x8ef501cc, 0x8ee20140, 0x26e40030, 0x24420001, 0xaee20140, -0x8ef00140, 0x8ef10074, 0x8ef20070, 0xc00242c, 0x24050400, 0xaef301c4, -0xaef401c8, 0xaef501cc, 0xaef00140, 0xaef10074, 0xaef20070, 0x8f42025c, -0x26e40094, 0xaee20060, 0x8f420260, 0x27450200, 0x24060008, 0xaee20068, -0x24020006, 0xc00243e, 0xaee20064, 0x3c023b9a, 0x3442ca00, 0xaee2006c, -0x240203e8, 0x24040002, 0x24030001, 0xaee20104, 0xaee40100, 0xaee3010c, -0x8f820220, 0x30420008, 0x10400004, 0x0, 0xaee30108, 0x8002011, -0x2021, 0xaee40108, 0x2021, 0x3c030001, 0x641821, 0x90634d50, -0x2e41021, 0x24840001, 0xa043009c, 0x2c82000f, 0x1440fff8, 0x0, -0x8f820040, 0x2e41821, 0x24840001, 0x21702, 0x24420030, 0xa062009c, -0x2e41021, 0x8002287, 0xa040009c, 0x240a0400, 0x24090040, 0x24080001, -0x8f830100, 0x27623000, 0x24660020, 0xc2102b, 0x50400001, 0x27662800, -0x8f820108, 0x14c20007, 0x26e20030, 0x8ee201a4, 0x3821, 0x24420001, -0xaee201a4, 0x8002050, 0x8ee201a4, 0x8ee404a8, 0x8ee504ac, 0xac620008, -0xa46a000e, 0xac600018, 0xac60001c, 0xac640000, 0xac650004, 0x8ee204bc, -0xac620010, 0xaf860100, 0x92e204dc, 0x1440000e, 0x24070001, 0x8ee24e18, -0x24420001, 0x50490003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, -0x8ee24e18, 0x210c0, 0x24424e28, 0x2e21021, 0xac400000, 0xac480004, -0x10e0ffd5, 0x0, 0x8ee20148, 0x24420001, 0xaee20148, 0x8002287, -0x8ee20148, 0x3c020900, 0xaee05228, 0xaee0522c, 0xaee05230, 0xaee05234, -0xaee001c8, 0x3c010001, 0x370821, 0xa02083a1, 0xafa20018, 0x8ee205f8, -0x8f430228, 0x24420001, 0x304a00ff, 0x514300f7, 0xafa00010, 0x8ee205f8, +0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124, +0x14c20007, 0x0, 0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0, +0x8001d70, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494, +0x2462001c, 0xac620008, 0xa46e000e, 0xac6d0018, 0xac640000, 0xac650004, +0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400033, 0x24070001, +0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x144a001f, +0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, +0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10480007, +0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x8001d5d, +0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, +0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x8001d70, +0x0, 0x8ee24e20, 0x24420001, 0x50480003, 0x1021, 0x8ee24e20, +0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, +0xac8a0000, 0xac8c0004, 0x54e00006, 0x240b0001, 0x8f820054, 0x1221023, +0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, 0x10620022, +0x0, 0x3c040001, 0x24844750, 0xafa00010, 0xafa00014, 0x8f860120, +0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011, 0x8001d9c, 0x0, +0x3c040001, 0x2484475c, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, +0xc002403, 0x34a5f010, 0x8001d9c, 0x0, 0x3c040001, 0x24844768, +0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f00f, +0x8ee201a8, 0x24420001, 0xaee201a8, 0x8ee201a8, 0x8ee20124, 0x24420001, +0xaee20124, 0x8001f93, 0x8ee20124, 0x27440212, 0xc0022f8, 0x24050006, +0x3049001f, 0x928c0, 0x2e51021, 0x9442726c, 0x30428000, 0x1040002f, +0x2e51021, 0x9442726c, 0x30424000, 0x1440001c, 0xb71021, 0x9443726e, +0x97420212, 0x14620018, 0xb71021, 0x8c437270, 0x8f420214, 0x54620016, +0xafa20010, 0x92e204c8, 0x10400007, 0x24020001, 0x8ee304cc, 0x1221004, +0x21027, 0x621824, 0x8001dc5, 0xaee304cc, 0x8f830228, 0x1221004, +0x21027, 0x621824, 0xaf830228, 0x910c0, 0x2e21821, 0x3402c000, +0x8001e4a, 0xa462726c, 0x8f420214, 0xafa20010, 0x910c0, 0x571021, +0x8c42726c, 0x3c040001, 0x24844774, 0x3c050003, 0xafa20014, 0x8f470210, +0x34a5f01c, 0xc002403, 0x1203021, 0x8001e7f, 0x3c020800, 0xb71021, +0x9443726e, 0x97420212, 0x14620019, 0x918c0, 0xb71021, 0x8c437270, +0x8f420214, 0x14620014, 0x918c0, 0x2e51021, 0x9447726c, 0x720c0, +0x971021, 0x9443736e, 0xb71021, 0xa443726e, 0x971021, 0x8c437370, +0xb71021, 0xac437270, 0x2e41021, 0x9443736c, 0x2e51021, 0xa443726c, +0x2e41821, 0x3402c000, 0x8001e4a, 0xa462736c, 0x2e31021, 0x9447726c, +0x3021, 0x720c0, 0x2e41021, 0x9442736c, 0x4021, 0x30428000, +0x14400025, 0xe02821, 0x605021, 0x340bc000, 0x971021, 0x9443736e, +0x97420212, 0x54620015, 0xe02821, 0x971021, 0x8c437370, 0x8f420214, +0x54620010, 0xe02821, 0x11000006, 0x2e41021, 0x9443736c, 0x510c0, +0x2e21021, 0x8001e16, 0xa443736c, 0x9443736c, 0x2ea1021, 0xa443726c, +0x710c0, 0x2e21021, 0xa44b736c, 0x8001e24, 0x24060001, 0x510c0, +0x2e21021, 0x9447736c, 0x720c0, 0x2e41021, 0x9442736c, 0x30428000, +0x1040ffdf, 0x25080001, 0x30c200ff, 0x14400025, 0x2021, 0x720c0, +0x971021, 0x9443736e, 0x97420212, 0x1462000f, 0x910c0, 0x971021, +0x8c437370, 0x8f420214, 0x1462000a, 0x910c0, 0x2e41821, 0x3402c000, +0x15000015, 0xa462736c, 0x910c0, 0x2e21821, 0x34028000, 0x8001e4a, +0xa462726c, 0x571021, 0x8c42726c, 0x3c040001, 0x24844780, 0x3c050003, +0xafa20010, 0x710c0, 0x571021, 0x8c42736c, 0x34a5001e, 0x1203021, +0xc002403, 0xafa20014, 0x8001e7f, 0x3c020800, 0x2021, 0x428c0, +0xb71021, 0x9443776e, 0x97420212, 0x5462002b, 0x24840001, 0xb71021, +0x8c437770, 0x8f420214, 0x54620026, 0x24840001, 0x3c020001, 0x571021, +0x8c4283a4, 0x2442ffff, 0x3c010001, 0x370821, 0xac2283a4, 0x3c020001, +0x571021, 0x8c4283a4, 0x809021, 0x242102b, 0x1040000e, 0x24b1776c, +0x24b07774, 0x2f02021, 0x2f12821, 0xc002490, 0x24060008, 0x26310008, +0x3c020001, 0x571021, 0x8c4283a4, 0x26520001, 0x242102b, 0x1440fff5, +0x26100008, 0x3c040001, 0x972021, 0x8c8483a4, 0x24050008, 0x420c0, +0x2484776c, 0xc002488, 0x2e42021, 0x8001e7f, 0x3c020800, 0x2c820080, +0x1440ffcf, 0x428c0, 0x3c020800, 0x34422000, 0xafa20018, 0x8ee205f8, +0x8f430228, 0x24420001, 0x304a00ff, 0x514300fd, 0xafa00010, 0x8ee205f8, 0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, -0x8f830054, 0x8f820054, 0x24690032, 0x1221023, 0x2c420033, 0x10400067, +0x8f830054, 0x8f820054, 0x24690032, 0x1221023, 0x2c420033, 0x1040006a, 0x5821, 0x24100008, 0x240f000d, 0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120, 0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, -0x8f820128, 0x15020007, 0x1021, 0x8ee201a0, 0x3821, 0x24420001, -0xaee201a0, 0x80020d4, 0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, -0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b, 0x822021, 0x862021, -0xace40000, 0xace50004, 0x8ee205f8, 0xa4f0000e, 0xacef0018, 0xacea001c, -0x210c0, 0x244205fc, 0x2e21021, 0xace20008, 0x8ee204b4, 0xace20010, -0xaf880120, 0x92e24e10, 0x14400033, 0x24070001, 0x8ee24e20, 0x210c0, -0x24425028, 0x2e22021, 0x8c820000, 0x144d001f, 0x0, 0x8ee34e20, -0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001, 0xac820004, -0x8ee24e24, 0x8ee34e20, 0x24420001, 0x104c0007, 0x0, 0x8ee24e24, -0x24420001, 0x10620005, 0x0, 0x80020c1, 0x0, 0x14600005, -0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, -0x2c420011, 0x50400010, 0xac800000, 0x80020d4, 0x0, 0x8ee24e20, -0x24420001, 0x504c0003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, -0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0xac8d0000, 0xac8e0004, -0x54e00006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa0, -0x0, 0x316300ff, 0x24020001, 0x54620075, 0xafa00010, 0xaeea05f8, -0x8f830054, 0x8f820054, 0x24690032, 0x1221023, 0x2c420033, 0x1040005e, -0x5821, 0x240e0008, 0x240d0011, 0x240a0012, 0x24080040, 0x240c0001, -0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, -0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, 0x3821, 0x24420001, -0xaee201a0, 0x800213d, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, +0x8f820128, 0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, +0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0, 0x8001ef7, 0x8ee201a0, +0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, +0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee205f8, +0xa4f0000e, 0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 0x2e21021, +0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 0x14400033, +0x24070001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, +0x144d001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, +0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, +0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, +0x8001ee4, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, +0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, +0x8001ef7, 0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 0x1021, +0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, +0x2e22021, 0xac8d0000, 0xac8e0004, 0x54e00006, 0x240b0001, 0x8f820054, +0x1221023, 0x2c420033, 0x1440ff9d, 0x0, 0x316300ff, 0x24020001, +0x54620078, 0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054, 0x24690032, +0x1221023, 0x2c420033, 0x10400061, 0x5821, 0x240e0008, 0x240d0011, +0x240a0012, 0x24080040, 0x240c0001, 0x8f830120, 0x27623800, 0x24660020, +0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, +0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x3821, 0x24420001, +0xaee201a0, 0x8001f63, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494, 0x2462001c, 0xac620008, 0xa46e000e, 0xac6d0018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400033, 0x24070001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x144a001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10480007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, -0x800212a, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, +0x8001f50, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, -0x800213d, 0x0, 0x8ee24e20, 0x24420001, 0x50480003, 0x1021, +0x8001f63, 0x0, 0x8ee24e20, 0x24420001, 0x50480003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0xac8a0000, 0xac8c0004, 0x54e00006, 0x240b0001, 0x8f820054, -0x1221023, 0x2c420033, 0x1440ffa9, 0x0, 0x316300ff, 0x24020001, -0x10620022, 0x0, 0x3c040001, 0x24844540, 0xafa00010, 0xafa00014, -0x8f860120, 0x8f870124, 0x3c050009, 0xc0023a7, 0x34a5f011, 0x8002169, -0x0, 0x3c040001, 0x2484454c, 0xafa00014, 0x8f860120, 0x8f870124, -0x3c050009, 0xc0023a7, 0x34a5f010, 0x8002169, 0x0, 0x3c040001, -0x24844558, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc0023a7, -0x34a5f00f, 0x8ee201a8, 0x24420001, 0xaee201a8, 0x8ee201a8, 0x8ee20120, -0x24420001, 0xaee20120, 0x8ee20120, 0x8ee20164, 0x24420001, 0xaee20164, -0x8002287, 0x8ee20164, 0x8f42025c, 0x26e40094, 0xaee20060, 0x8f420260, -0x27450200, 0x24060008, 0xc00243e, 0xaee20068, 0x8f820220, 0x30420008, -0x14400002, 0x24020001, 0x24020002, 0xaee20108, 0x8ee2011c, 0x24420001, -0xaee2011c, 0x8002287, 0x8ee2011c, 0x3c040001, 0x2484459c, 0xafa00010, -0xafa00014, 0x8fa60020, 0x3c050003, 0xc0023a7, 0x34a5f00f, 0x93a20020, -0x3c030700, 0x34631000, 0x431025, 0xafa20018, 0x8ee205f8, 0x8f430228, -0x24420001, 0x304900ff, 0x512300dc, 0xafa00010, 0x8ee205f8, 0x210c0, -0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f870120, -0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128, -0x15020007, 0x1021, 0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0, -0x80021ff, 0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, -0x8ee50434, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, -0xace50004, 0x8ee305f8, 0x24020008, 0xa4e2000e, 0x2402000d, 0xace20018, -0xace9001c, 0x318c0, 0x246305fc, 0x2e31021, 0xace20008, 0x8ee204b4, -0xace20010, 0xaf880120, 0x92e24e10, 0x14400037, 0x24070001, 0x8ee24e20, -0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 0x1462001f, -0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, -0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, -0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x80021e9, -0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, -0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x80021ff, -0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, -0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, -0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x54e0000c, -0xaee905f8, 0x3c040001, 0x248445a4, 0xafa00010, 0xafa00014, 0x8ee605f8, -0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f000, 0x800227f, 0x0, -0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, -0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, 0x3821, 0x24420001, -0xaee201a0, 0x8002263, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, -0x8ee50494, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, -0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, +0x1221023, 0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, +0x10620022, 0x0, 0x3c040001, 0x24844750, 0xafa00010, 0xafa00014, +0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011, 0x8001f8f, +0x0, 0x3c040001, 0x2484475c, 0xafa00014, 0x8f860120, 0x8f870124, +0x3c050009, 0xc002403, 0x34a5f010, 0x8001f8f, 0x0, 0x3c040001, +0x24844768, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403, +0x34a5f00f, 0x8ee201a8, 0x24420001, 0xaee201a8, 0x8ee201a8, 0x8ee20128, +0x24420001, 0xaee20128, 0x8ee20128, 0x8ee20160, 0x24420001, 0xaee20160, +0x80022e2, 0x8ee20160, 0x8fa20020, 0x21200, 0x21d02, 0x24020001, +0x10620005, 0x24020002, 0x1062000d, 0x0, 0x8001fb3, 0xafa00010, +0x92e204c8, 0x14400006, 0x24020001, 0x8f820228, 0xaee204cc, 0x2402ffff, +0xaf820228, 0x24020001, 0x8001fba, 0xa2e204c8, 0x92e204c8, 0x5040000c, +0xa2e004c8, 0x8ee204cc, 0xaf820228, 0x8001fba, 0xa2e004c8, 0x3c040001, +0x24844788, 0xafa00014, 0x8fa60020, 0x3c050003, 0xc002403, 0x34a5f009, +0x8ee2013c, 0x24420001, 0xaee2013c, 0x80022e2, 0x8ee2013c, 0x8fa20020, +0x21200, 0x22502, 0x24020001, 0x10820005, 0x24020002, 0x1082000f, +0x0, 0x8001fdf, 0xafa00010, 0x8f820220, 0x3c0308ff, 0x3463ffff, +0x431024, 0x34420008, 0xaf820220, 0x24020001, 0x3c010001, 0x370821, +0xa02283a2, 0x8001fe6, 0xaee40108, 0x8f820220, 0x3c0308ff, 0x3463fff7, +0x431024, 0xaf820220, 0x3c010001, 0x370821, 0xa02083a2, 0x8001fe6, +0xaee40108, 0x3c040001, 0x24844794, 0xafa00014, 0x8fa60020, 0x3c050003, +0xc002403, 0x34a5f00a, 0x8ee2012c, 0x24420001, 0xaee2012c, 0x80022e2, +0x8ee2012c, 0x8fa20020, 0x21200, 0x21d02, 0x24020001, 0x10620005, +0x24020002, 0x1062000e, 0x0, 0x800200d, 0xafa00010, 0x8f820220, +0x3c0308ff, 0x3463ffff, 0x431024, 0x34420008, 0xaf820220, 0x24020001, +0x3c010001, 0x370821, 0x8002014, 0xa02283a3, 0x3c020001, 0x571021, +0x904283a2, 0x3c010001, 0x370821, 0x1440000e, 0xa02083a3, 0x8f820220, +0x3c0308ff, 0x3463fff7, 0x431024, 0x8002014, 0xaf820220, 0x3c040001, +0x248447a0, 0xafa00014, 0x8fa60020, 0x3c050003, 0xc002403, 0x34a5f00b, +0x8ee20114, 0x24420001, 0xaee20114, 0x80022e2, 0x8ee20114, 0x27840208, +0x27450200, 0xc00249a, 0x24060008, 0x26e40094, 0x27450200, 0xc00249a, +0x24060008, 0x8ee20134, 0x24420001, 0xaee20134, 0x80022e2, 0x8ee20134, +0x8f460248, 0x24040001, 0xc004eac, 0x24050004, 0x8ee20130, 0x24420001, +0xaee20130, 0x80022e2, 0x8ee20130, 0x8ef301c4, 0x8ef401c8, 0x8ef501cc, +0x8ee20140, 0x26e40030, 0x24420001, 0xaee20140, 0x8ef00140, 0x8ef10074, +0x8ef20070, 0xc002488, 0x24050400, 0xaef301c4, 0xaef401c8, 0xaef501cc, +0xaef00140, 0xaef10074, 0xaef20070, 0x8f42025c, 0x26e40094, 0xaee20060, +0x8f420260, 0x27450200, 0x24060008, 0xaee20068, 0x24020006, 0xc00249a, +0xaee20064, 0x3c023b9a, 0x3442ca00, 0xaee2006c, 0x240203e8, 0x24040002, +0x24030001, 0xaee20104, 0xaee40100, 0xaee3010c, 0x8f820220, 0x30420008, +0x10400004, 0x0, 0xaee30108, 0x800205d, 0x2021, 0xaee40108, +0x2021, 0x3c030001, 0x641821, 0x90634f60, 0x2e41021, 0x24840001, +0xa043009c, 0x2c82000f, 0x1440fff8, 0x0, 0x8f820040, 0x2e41821, +0x24840001, 0x21702, 0x24420030, 0xa062009c, 0x2e41021, 0x80022e2, +0xa040009c, 0x240a0400, 0x24090040, 0x24080001, 0x8f830100, 0x27623000, +0x24660020, 0xc2102b, 0x50400001, 0x27662800, 0x8f820108, 0x10c20004, +0x0, 0x8f820104, 0x14c20007, 0x26e20030, 0x8ee201a4, 0x3821, +0x24420001, 0xaee201a4, 0x800209f, 0x8ee201a4, 0x8ee404a8, 0x8ee504ac, +0xac620008, 0xa46a000e, 0xac600018, 0xac60001c, 0xac640000, 0xac650004, +0x8ee204bc, 0xac620010, 0xaf860100, 0x92e204dc, 0x1440000e, 0x24070001, +0x8ee24e18, 0x24420001, 0x50490003, 0x1021, 0x8ee24e18, 0x24420001, +0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e21021, 0xac400000, +0xac480004, 0x10e0ffd2, 0x0, 0x8ee20148, 0x24420001, 0xaee20148, +0x80022e2, 0x8ee20148, 0x3c020900, 0xaee05228, 0xaee0522c, 0xaee05230, +0xaee05234, 0xaee001c8, 0x3c010001, 0x370821, 0xa02083a1, 0xafa20018, +0x8ee205f8, 0x8f430228, 0x24420001, 0x304a00ff, 0x514300fd, 0xafa00010, +0x8ee205f8, 0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, +0xac440600, 0x8f830054, 0x8f820054, 0x24690032, 0x1221023, 0x2c420033, +0x1040006a, 0x5821, 0x24100008, 0x240f000d, 0x240d0007, 0x240c0040, +0x240e0001, 0x8f870120, 0x27623800, 0x24e80020, 0x102102b, 0x50400001, +0x27683000, 0x8f820128, 0x11020004, 0x0, 0x8f820124, 0x15020007, +0x1021, 0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0, 0x8002126, +0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, +0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, +0x8ee205f8, 0xa4f0000e, 0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, +0x2e21021, 0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, +0x14400033, 0x24070001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, +0x8c820000, 0x144d001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, +0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, +0x24420001, 0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, +0x0, 0x8002113, 0x0, 0x14600005, 0x0, 0x8f820128, +0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, +0xac800000, 0x8002126, 0x0, 0x8ee24e20, 0x24420001, 0x504c0003, +0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, +0x24425028, 0x2e22021, 0xac8d0000, 0xac8e0004, 0x54e00006, 0x240b0001, +0x8f820054, 0x1221023, 0x2c420033, 0x1440ff9d, 0x0, 0x316300ff, +0x24020001, 0x54620078, 0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054, +0x24690032, 0x1221023, 0x2c420033, 0x10400061, 0x5821, 0x240e0008, +0x240d0011, 0x240a0012, 0x24080040, 0x240c0001, 0x8f830120, 0x27623800, +0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, +0x0, 0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x3821, +0x24420001, 0xaee201a0, 0x8002192, 0x8ee201a0, 0x8ee205f8, 0xac62001c, +0x8ee40490, 0x8ee50494, 0x2462001c, 0xac620008, 0xa46e000e, 0xac6d0018, +0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, +0x14400033, 0x24070001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, +0x8c820000, 0x144a001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, +0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, +0x24420001, 0x10480007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, +0x0, 0x800217f, 0x0, 0x14600005, 0x0, 0x8f820128, +0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, +0xac800000, 0x8002192, 0x0, 0x8ee24e20, 0x24420001, 0x50480003, +0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, +0x24425028, 0x2e22021, 0xac8a0000, 0xac8c0004, 0x54e00006, 0x240b0001, +0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, +0x24020001, 0x10620022, 0x0, 0x3c040001, 0x24844750, 0xafa00010, +0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011, +0x80021be, 0x0, 0x3c040001, 0x2484475c, 0xafa00014, 0x8f860120, +0x8f870124, 0x3c050009, 0xc002403, 0x34a5f010, 0x80021be, 0x0, +0x3c040001, 0x24844768, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, +0xc002403, 0x34a5f00f, 0x8ee201a8, 0x24420001, 0xaee201a8, 0x8ee201a8, +0x8ee20120, 0x24420001, 0xaee20120, 0x8ee20120, 0x8ee20164, 0x24420001, +0xaee20164, 0x80022e2, 0x8ee20164, 0x8f42025c, 0x26e40094, 0xaee20060, +0x8f420260, 0x27450200, 0x24060008, 0xc00249a, 0xaee20068, 0x8f820220, +0x30420008, 0x14400002, 0x24020001, 0x24020002, 0xaee20108, 0x8ee2011c, +0x24420001, 0xaee2011c, 0x80022e2, 0x8ee2011c, 0x3c040001, 0x248447ac, +0xafa00010, 0xafa00014, 0x8fa60020, 0x3c050003, 0xc002403, 0x34a5f00f, +0x93a20020, 0x3c030700, 0x34631000, 0x431025, 0xafa20018, 0x8ee205f8, +0x8f430228, 0x24420001, 0x304900ff, 0x512300e2, 0xafa00010, 0x8ee205f8, +0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, +0x8f870120, 0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, +0x8f820128, 0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, +0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0, 0x8002257, 0x8ee201a0, +0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, +0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee305f8, +0x24020008, 0xa4e2000e, 0x2402000d, 0xace20018, 0xace9001c, 0x318c0, +0x246305fc, 0x2e31021, 0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 0x14400037, 0x24070001, 0x8ee24e20, 0x210c0, 0x24425028, -0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0, 0x8ee34e20, +0x2e22021, 0x8c830000, 0x24020007, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24, -0x24420001, 0x10a20005, 0x0, 0x800224d, 0x0, 0x14a00005, +0x24420001, 0x10a20005, 0x0, 0x8002241, 0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, -0x2c420011, 0x50400013, 0xac800000, 0x8002263, 0x0, 0x8ee24e20, +0x2c420011, 0x50400013, 0xac800000, 0x8002257, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, -0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020012, -0xac820000, 0x24020001, 0xac820004, 0x14e0001b, 0x0, 0x3c040001, -0x248445ac, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, -0xc0023a7, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x800227f, -0x8ee201ac, 0x3c040001, 0x248445b8, 0xafa00014, 0x8ee605f8, 0x8f470228, -0x3c050009, 0xc0023a7, 0x34a5f005, 0x8ee201a8, 0x24420001, 0xaee201a8, -0x8ee201a8, 0x8ee2014c, 0x24420001, 0xaee2014c, 0x8ee2014c, 0x8ee2015c, -0x24420001, 0xaee2015c, 0x8ee2015c, 0x8f43022c, 0x8f42010c, 0x14620009, -0x24020002, 0xaf820064, 0x8f820064, 0x14400005, 0x0, 0x8f43022c, -0x8f42010c, 0x1462f897, 0x0, 0x8fbf0044, 0x8fb60040, 0x8fb5003c, -0x8fb40038, 0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028, 0x3e00008, -0x27bd0048, 0x27bdfff8, 0x2408ffff, 0x10a00014, 0x4821, 0x3c0aedb8, -0x354a8320, 0x90870000, 0x24840001, 0x3021, 0x1071026, 0x30420001, -0x10400002, 0x81842, 0x6a1826, 0x604021, 0x24c60001, 0x2cc20008, -0x1440fff7, 0x73842, 0x25290001, 0x125102b, 0x1440fff0, 0x0, -0x1001021, 0x3e00008, 0x27bd0008, 0x0, 0x27bdffe8, 0x27642800, -0xafbf0010, 0xc00242c, 0x24051000, 0x24020021, 0xaf800100, 0xaf800104, -0xaf800108, 0xaf800110, 0xaf800114, 0xaf800118, 0xaf800120, 0xaf800124, -0xaf800128, 0xaf800130, 0xaf800134, 0xaf800138, 0xaee04e18, 0xaee04e1c, -0xaee04e20, 0xaee04e24, 0xaf82011c, 0x8f420218, 0x30420040, 0x10400004, -0x0, 0x8f82011c, 0x34420004, 0xaf82011c, 0x8fbf0010, 0x3e00008, -0x27bd0018, 0x27bdffe0, 0xafbf0018, 0x8f820104, 0xafa20010, 0x8f820100, -0x3c050002, 0xafa20014, 0x8f8600b0, 0x8f87011c, 0x3c040001, 0x2484466c, -0xc0023a7, 0x34a5f000, 0x8f8300b0, 0x3c027f00, 0x621824, 0x3c020400, -0x1062002b, 0x43102b, 0x14400008, 0x3c022000, 0x3c020100, 0x10620026, -0x3c020200, 0x10620013, 0x0, 0x8002316, 0x0, 0x1062000a, -0x43102b, 0x1040001e, 0x3c024000, 0x1462001c, 0x0, 0x8ee2018c, -0x24420001, 0xaee2018c, 0x8002316, 0x8ee2018c, 0x8ee20188, 0x24420001, -0xaee20188, 0x8002316, 0x8ee20188, 0x8f82011c, 0x34420002, 0xaf82011c, -0x8f830104, 0x8f8200b0, 0x34420001, 0xaf8200b0, 0xaf830104, 0x8f82011c, -0x2403fffd, 0x431024, 0xaf82011c, 0x8ee2019c, 0x24420001, 0xaee2019c, -0x8002319, 0x8ee2019c, 0x8f8200b0, 0x34420001, 0xaf8200b0, 0x8fbf0018, -0x3e00008, 0x27bd0020, 0x27bdffe0, 0xafbf001c, 0xafb00018, 0x8f820120, -0xafa20010, 0x8f820124, 0x3c050001, 0xafa20014, 0x8f8600a0, 0x8f87011c, -0x3c040001, 0x24844678, 0xc0023a7, 0x34a5f000, 0x8f8300a0, 0x3c027f00, -0x621824, 0x3c020400, 0x10620055, 0x8021, 0x43102b, 0x14400008, -0x3c042000, 0x3c020100, 0x1062004f, 0x3c020200, 0x1062003c, 0x0, -0x8002384, 0x0, 0x10640005, 0x83102b, 0x10400047, 0x3c024000, -0x14620045, 0x0, 0x8f8200a0, 0x441024, 0x10400006, 0x0, -0x8ee20190, 0x24420001, 0xaee20190, 0x800234d, 0x8ee20190, 0x8ee20194, -0x24420001, 0xaee20194, 0x8ee20194, 0x8f82011c, 0x34420002, 0xaf82011c, -0x8f82011c, 0x30420200, 0x1040001b, 0x0, 0x8f8300a0, 0x8f840124, -0x8f8200ac, 0x14400007, 0x24020001, 0x3c020001, 0x3442f000, 0x621024, -0x50400001, 0x24100001, 0x24020001, 0x1200000d, 0xaf8200a0, 0x8f820124, -0x2442ffe0, 0xaf820124, 0x8f820124, 0x8f820124, 0x27633000, 0x43102b, -0x10400005, 0x276237e0, 0xaf820124, 0x800236e, 0x0, 0xaf840124, -0x8f82011c, 0x2403fffd, 0x431024, 0x8002387, 0xaf82011c, 0x8f82011c, -0x34420002, 0xaf82011c, 0x8f830124, 0x8f8200a0, 0x34420001, 0xaf8200a0, -0xaf830124, 0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ee20198, -0x24420001, 0xaee20198, 0x8002387, 0x8ee20198, 0x8f8200a0, 0x34420001, -0xaf8200a0, 0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020, 0x0, -0x3c020001, 0x8c424d78, 0x27bdffe8, 0xafbf0014, 0x14400012, 0xafb00010, -0x3c100001, 0x26104eb0, 0x2002021, 0xc00242c, 0x24052000, 0x26021fe0, -0x3c010001, 0xac224e84, 0x3c010001, 0xac224e80, 0xaf420250, 0x24022000, -0xaf500254, 0xaf420258, 0x24020001, 0x3c010001, 0xac224d78, 0x8fbf0014, -0x8fb00010, 0x3e00008, 0x27bd0018, 0x3c030001, 0x8c634e84, 0x8c820000, -0x8fa80010, 0x8fa90014, 0xac620000, 0x3c020001, 0x8c424e84, 0x8c830004, -0xac430004, 0xac450008, 0x8f840054, 0x2443ffe0, 0xac460010, 0xac470014, -0xac480018, 0xac49001c, 0x3c010001, 0xac234e84, 0xac44000c, 0x3c020001, -0x24424eb0, 0x62182b, 0x10600005, 0x0, 0x3c020001, 0x8c424e80, -0x3c010001, 0xac224e84, 0x3c030001, 0x8c634e84, 0x3c020001, 0x8c424d60, -0xac620000, 0x3c030001, 0x8c634e84, 0x3c020001, 0x8c424d60, 0xac620004, -0x3e00008, 0xaf430250, 0x3c030001, 0x8c634e84, 0x3c020001, 0x8c424d60, -0x27bdffd0, 0xafb40020, 0x8fb40040, 0xafb00010, 0x808021, 0xafb50024, -0x8fb50044, 0x8fa40048, 0xafb10014, 0xa08821, 0xafbf0028, 0xafb3001c, -0xafb20018, 0xac620000, 0x3c050001, 0x8ca54e84, 0x3c020001, 0x8c424d60, -0xc09021, 0xe09821, 0x10800006, 0xaca20004, 0x24a50008, 0xc002434, -0x24060018, 0x80023f2, 0x0, 0x24a40008, 0xc00242c, 0x24050018, -0x3c020001, 0x8c424e84, 0x3c050001, 0x24a54eb0, 0x2442ffe0, 0x3c010001, -0xac224e84, 0x45102b, 0x10400005, 0x0, 0x3c020001, 0x8c424e80, -0x3c010001, 0xac224e84, 0x3c030001, 0x8c634e84, 0x8e020000, 0xac620000, -0x3c030001, 0x8c634e84, 0x8e020004, 0xac620004, 0xac710008, 0x8f840054, -0x2462ffe0, 0x3c010001, 0xac224e84, 0x45102b, 0xac720010, 0xac730014, -0xac740018, 0xac75001c, 0x10400005, 0xac64000c, 0x3c020001, 0x8c424e80, -0x3c010001, 0xac224e84, 0x3c030001, 0x8c634e84, 0x3c020001, 0x8c424d60, -0xac620000, 0x3c030001, 0x8c634e84, 0x3c020001, 0x8c424d60, 0xac620004, -0xaf430250, 0x8fbf0028, 0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018, -0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0030, 0x10a00005, 0x0, -0xac800000, 0x24a5fffc, 0x14a0fffd, 0x24840004, 0x3e00008, 0x0, -0x10c00007, 0x0, 0x8c820000, 0x24840004, 0x24c6fffc, 0xaca20000, -0x14c0fffb, 0x24a50004, 0x3e00008, 0x0, 0x10c00007, 0x0, -0x8ca20000, 0x24a50004, 0x24c6fffc, 0xac820000, 0x14c0fffb, 0x24840004, -0x3e00008, 0x0, 0x3e00008, 0x0, 0x27bdffd8, 0xafbf0020, -0x8ee304d4, 0x8ee204d0, 0x1062041e, 0x0, 0x8ee204d4, 0x8ee304ec, -0x21100, 0x626021, 0x95870008, 0x8d8a0000, 0x8d8b0004, 0x958d000a, -0x8ee2724c, 0x8ee3725c, 0x30e4ffff, 0x441021, 0x62182b, 0x10600015, -0x31a20004, 0x8f8200d8, 0x8ee37248, 0x431023, 0xaee2725c, 0x8ee2725c, -0x1c400003, 0x3c030001, 0x431021, 0xaee2725c, 0x8ee2724c, 0x8ee3725c, -0x441021, 0x62182b, 0x10600006, 0x31a20004, 0x8ee201b4, 0x24420001, -0xaee201b4, 0x800286d, 0x8ee201b4, 0x10400234, 0x31a20200, 0x10400144, -0x4821, 0x96e2045a, 0x30420010, 0x10400140, 0x0, 0x8f840100, +0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020007, +0xac820000, 0x24020001, 0xac820004, 0x54e0000c, 0xaee905f8, 0x3c040001, +0x248447b4, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, +0xc002403, 0x34a5f000, 0x80022da, 0x0, 0x8f830120, 0x27623800, +0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, +0x0, 0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x3821, +0x24420001, 0xaee201a0, 0x80022be, 0x8ee201a0, 0x8ee205f8, 0xac62001c, +0x8ee40490, 0x8ee50494, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, +0x24020011, 0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, +0xaf860120, 0x92e24e10, 0x14400037, 0x24070001, 0x8ee24e20, 0x210c0, +0x24425028, 0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0, +0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, +0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 0x0, +0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x80022a8, 0x0, +0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, +0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x80022be, 0x0, +0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20, +0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, +0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x14e0001b, 0x0, +0x3c040001, 0x248447bc, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, +0x3c050009, 0xc002403, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, +0x80022da, 0x8ee201ac, 0x3c040001, 0x248447c8, 0xafa00014, 0x8ee605f8, +0x8f470228, 0x3c050009, 0xc002403, 0x34a5f005, 0x8ee201a8, 0x24420001, +0xaee201a8, 0x8ee201a8, 0x8ee2014c, 0x24420001, 0xaee2014c, 0x8ee2014c, +0x8ee2015c, 0x24420001, 0xaee2015c, 0x8ee2015c, 0x8f43022c, 0x8f42010c, +0x14620009, 0x24020002, 0xaf820064, 0x8f820064, 0x14400005, 0x0, +0x8f43022c, 0x8f42010c, 0x1462f877, 0x0, 0x8fbf0044, 0x8fb60040, +0x8fb5003c, 0x8fb40038, 0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028, +0x3e00008, 0x27bd0048, 0x27bdfff8, 0x2408ffff, 0x10a00014, 0x4821, +0x3c0aedb8, 0x354a8320, 0x90870000, 0x24840001, 0x3021, 0x1071026, +0x30420001, 0x10400002, 0x81842, 0x6a1826, 0x604021, 0x24c60001, +0x2cc20008, 0x1440fff7, 0x73842, 0x25290001, 0x125102b, 0x1440fff0, +0x0, 0x1001021, 0x3e00008, 0x27bd0008, 0x0, 0x0, +0x27bdffe8, 0x27642800, 0xafbf0010, 0xc002488, 0x24051000, 0x24020021, +0xaf800100, 0xaf800104, 0xaf800108, 0xaf800110, 0xaf800114, 0xaf800118, +0xaf800120, 0xaf800124, 0xaf800128, 0xaf800130, 0xaf800134, 0xaf800138, +0xaee04e18, 0xaee04e1c, 0xaee04e20, 0xaee04e24, 0xaf82011c, 0x8f420218, +0x30420040, 0x10400004, 0x0, 0x8f82011c, 0x34420004, 0xaf82011c, +0x8fbf0010, 0x3e00008, 0x27bd0018, 0x27bdffe0, 0xafbf0018, 0x8f820104, +0xafa20010, 0x8f820100, 0x3c050002, 0xafa20014, 0x8f8600b0, 0x8f87011c, +0x3c040001, 0x2484487c, 0xc002403, 0x34a5f000, 0x8f8300b0, 0x3c027f00, +0x621824, 0x3c020400, 0x1062002b, 0x43102b, 0x14400008, 0x3c022000, +0x3c020100, 0x10620026, 0x3c020200, 0x10620013, 0x0, 0x8002372, +0x0, 0x1062000a, 0x43102b, 0x1040001e, 0x3c024000, 0x1462001c, +0x0, 0x8ee2018c, 0x24420001, 0xaee2018c, 0x8002372, 0x8ee2018c, +0x8ee20188, 0x24420001, 0xaee20188, 0x8002372, 0x8ee20188, 0x8f82011c, +0x34420002, 0xaf82011c, 0x8f830104, 0x8f8200b0, 0x34420001, 0xaf8200b0, +0xaf830104, 0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ee2019c, +0x24420001, 0xaee2019c, 0x8002375, 0x8ee2019c, 0x8f8200b0, 0x34420001, +0xaf8200b0, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffe0, 0xafbf001c, +0xafb00018, 0x8f820120, 0xafa20010, 0x8f820124, 0x3c050001, 0xafa20014, +0x8f8600a0, 0x8f87011c, 0x3c040001, 0x24844888, 0xc002403, 0x34a5f000, +0x8f8300a0, 0x3c027f00, 0x621824, 0x3c020400, 0x10620055, 0x8021, +0x43102b, 0x14400008, 0x3c042000, 0x3c020100, 0x1062004f, 0x3c020200, +0x1062003c, 0x0, 0x80023e0, 0x0, 0x10640005, 0x83102b, +0x10400047, 0x3c024000, 0x14620045, 0x0, 0x8f8200a0, 0x441024, +0x10400006, 0x0, 0x8ee20190, 0x24420001, 0xaee20190, 0x80023a9, +0x8ee20190, 0x8ee20194, 0x24420001, 0xaee20194, 0x8ee20194, 0x8f82011c, +0x34420002, 0xaf82011c, 0x8f82011c, 0x30420200, 0x1040001b, 0x0, +0x8f8300a0, 0x8f840124, 0x8f8200ac, 0x14400007, 0x24020001, 0x3c020001, +0x3442f000, 0x621024, 0x50400001, 0x24100001, 0x24020001, 0x1200000d, +0xaf8200a0, 0x8f820124, 0x2442ffe0, 0xaf820124, 0x8f820124, 0x8f820124, +0x27633000, 0x43102b, 0x10400005, 0x276237e0, 0xaf820124, 0x80023ca, +0x0, 0xaf840124, 0x8f82011c, 0x2403fffd, 0x431024, 0x80023e3, +0xaf82011c, 0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830124, 0x8f8200a0, +0x34420001, 0xaf8200a0, 0xaf830124, 0x8f82011c, 0x2403fffd, 0x431024, +0xaf82011c, 0x8ee20198, 0x24420001, 0xaee20198, 0x80023e3, 0x8ee20198, +0x8f8200a0, 0x34420001, 0xaf8200a0, 0x8fbf001c, 0x8fb00018, 0x3e00008, +0x27bd0020, 0x0, 0x3c020001, 0x8c424f88, 0x27bdffe8, 0xafbf0014, +0x14400012, 0xafb00010, 0x3c100001, 0x261050c0, 0x2002021, 0xc002488, +0x24052000, 0x26021fe0, 0x3c010001, 0xac225094, 0x3c010001, 0xac225090, +0xaf420250, 0x24022000, 0xaf500254, 0xaf420258, 0x24020001, 0x3c010001, +0xac224f88, 0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018, 0x3c030001, +0x8c635094, 0x8c820000, 0x8fa80010, 0x8fa90014, 0xac620000, 0x3c020001, +0x8c425094, 0x8c830004, 0xac430004, 0xac450008, 0x8f840054, 0x2443ffe0, +0xac460010, 0xac470014, 0xac480018, 0xac49001c, 0x3c010001, 0xac235094, +0xac44000c, 0x3c020001, 0x244250c0, 0x62182b, 0x10600005, 0x0, +0x3c020001, 0x8c425090, 0x3c010001, 0xac225094, 0x3c030001, 0x8c635094, +0x3c020001, 0x8c424f70, 0xac620000, 0x3c030001, 0x8c635094, 0x3c020001, +0x8c424f70, 0xac620004, 0x3e00008, 0xaf430250, 0x3c030001, 0x8c635094, +0x3c020001, 0x8c424f70, 0x27bdffd0, 0xafb40020, 0x8fb40040, 0xafb00010, +0x808021, 0xafb50024, 0x8fb50044, 0x8fa40048, 0xafb10014, 0xa08821, +0xafbf0028, 0xafb3001c, 0xafb20018, 0xac620000, 0x3c050001, 0x8ca55094, +0x3c020001, 0x8c424f70, 0xc09021, 0xe09821, 0x10800006, 0xaca20004, +0x24a50008, 0xc002490, 0x24060018, 0x800244e, 0x0, 0x24a40008, +0xc002488, 0x24050018, 0x3c020001, 0x8c425094, 0x3c050001, 0x24a550c0, +0x2442ffe0, 0x3c010001, 0xac225094, 0x45102b, 0x10400005, 0x0, +0x3c020001, 0x8c425090, 0x3c010001, 0xac225094, 0x3c030001, 0x8c635094, +0x8e020000, 0xac620000, 0x3c030001, 0x8c635094, 0x8e020004, 0xac620004, +0xac710008, 0x8f840054, 0x2462ffe0, 0x3c010001, 0xac225094, 0x45102b, +0xac720010, 0xac730014, 0xac740018, 0xac75001c, 0x10400005, 0xac64000c, +0x3c020001, 0x8c425090, 0x3c010001, 0xac225094, 0x3c030001, 0x8c635094, +0x3c020001, 0x8c424f70, 0xac620000, 0x3c030001, 0x8c635094, 0x3c020001, +0x8c424f70, 0xac620004, 0xaf430250, 0x8fbf0028, 0x8fb50024, 0x8fb40020, +0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0030, +0x10a00005, 0x0, 0xac800000, 0x24a5fffc, 0x14a0fffd, 0x24840004, +0x3e00008, 0x0, 0x10c00007, 0x0, 0x8c820000, 0x24840004, +0x24c6fffc, 0xaca20000, 0x14c0fffb, 0x24a50004, 0x3e00008, 0x0, +0x10c00007, 0x0, 0x8ca20000, 0x24a50004, 0x24c6fffc, 0xac820000, +0x14c0fffb, 0x24840004, 0x3e00008, 0x0, 0x3e00008, 0x0, +0x27bdffd8, 0xafbf0020, 0x8ee304d4, 0x8ee204d0, 0x10620436, 0x0, +0x8ee204d4, 0x8ee304ec, 0x21100, 0x626021, 0x95870008, 0x8d8a0000, +0x8d8b0004, 0x958d000a, 0x8ee2724c, 0x8ee3725c, 0x30e4ffff, 0x441021, +0x62182b, 0x10600015, 0x31a20004, 0x8f8200d8, 0x8ee37248, 0x431023, +0xaee2725c, 0x8ee2725c, 0x1c400003, 0x3c030001, 0x431021, 0xaee2725c, +0x8ee2724c, 0x8ee3725c, 0x441021, 0x62182b, 0x10600006, 0x31a20004, +0x8ee201b4, 0x24420001, 0xaee201b4, 0x80028e1, 0x8ee201b4, 0x10400240, +0x31a20200, 0x1040014d, 0x4821, 0x96e2045a, 0x30420010, 0x10400149, +0x0, 0x8f840100, 0x27623000, 0x24850020, 0xa2102b, 0x50400001, +0x27652800, 0x8f820108, 0x10a20004, 0x0, 0x8f820104, 0x14a20006, +0x2402000c, 0x8ee201a4, 0x24420001, 0xaee201a4, 0x800252c, 0x8ee201a4, +0xac8a0000, 0xac8b0004, 0x8ee37254, 0x24060005, 0xa482000e, 0xac860018, +0xac830008, 0x8ee204d4, 0xac82001c, 0x8ee204b8, 0xac820010, 0xaf850100, +0x92e204dc, 0x14400036, 0x24090001, 0x8ee24e18, 0x210c0, 0x24424e28, +0x2e22021, 0x8c820000, 0x1446001f, 0x0, 0x8ee34e18, 0x8ee24e1c, +0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c, +0x8ee54e18, 0x24420001, 0x10430007, 0x0, 0x8ee24e1c, 0x24420001, +0x10a20005, 0x0, 0x8002516, 0x0, 0x14a00005, 0x0, +0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, +0x50400013, 0xac800000, 0x800252c, 0x0, 0x8ee24e18, 0x24030040, +0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, +0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x24020005, 0xac820000, +0x24020001, 0xac820004, 0x1520000a, 0x3c040001, 0xafab0010, 0x8ee27254, +0x3c040001, 0x24844af0, 0x3c050004, 0xafa20014, 0x8ee604d4, 0x80028be, +0x34a5f114, 0x8ee27254, 0x34843800, 0x3641821, 0x24420010, 0x43102b, +0x14400073, 0x0, 0x8ee27254, 0x24480010, 0x3641021, 0x102102b, +0x14400002, 0x3c02ffff, 0x1024021, 0x8f850100, 0x27623000, 0x24a60020, +0xc2102b, 0x50400001, 0x27662800, 0x8f820108, 0x10c20004, 0x0, +0x8f820104, 0x14c20007, 0x2563000c, 0x8ee201a4, 0x4821, 0x24420001, +0xaee201a4, 0x80025a0, 0x8ee201a4, 0x2c64000c, 0x1441021, 0xaca20000, +0xaca30004, 0x24e2fff4, 0xa4a2000e, 0x24020006, 0xaca80008, 0xaca20018, +0x8ee204d4, 0xaca2001c, 0x8ee204b8, 0x3c030002, 0x431025, 0xaca20010, +0xaf860100, 0x92e204dc, 0x14400037, 0x24090001, 0x8ee24e18, 0x210c0, +0x24424e28, 0x2e22021, 0x8c830000, 0x24020005, 0x1462001f, 0x0, +0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, +0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007, 0x0, +0x8ee24e1c, 0x24420001, 0x10a20005, 0x0, 0x800258a, 0x0, +0x14a00005, 0x0, 0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, +0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x80025a0, 0x0, +0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, +0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, +0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x2508fffc, +0xafab0010, 0x8ee27254, 0x3c040001, 0x24844af0, 0x3c050004, 0xafa20014, +0x8ee604d4, 0x80028be, 0x34a5f125, 0x34028100, 0xa5020000, 0x9582000e, +0x800261d, 0xa5020002, 0x8f850100, 0x27623000, 0x24a60020, 0xc2102b, +0x50400001, 0x27662800, 0x8f820108, 0x10c20004, 0x0, 0x8f820104, +0x14c20007, 0x2563000c, 0x8ee201a4, 0x4821, 0x24420001, 0xaee201a4, +0x800260d, 0x8ee201a4, 0x2c64000c, 0x1441021, 0xaca20000, 0xaca30004, +0x8ee37254, 0x24e2fff4, 0xa4a2000e, 0x24020006, 0xaca20018, 0x24630010, +0xaca30008, 0x8ee204d4, 0xaca2001c, 0x8ee204b8, 0x3c030002, 0x431025, +0xaca20010, 0xaf860100, 0x92e204dc, 0x14400037, 0x24090001, 0x8ee24e18, +0x210c0, 0x24424e28, 0x2e22021, 0x8c830000, 0x24020005, 0x1462001f, +0x0, 0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004, +0x24420001, 0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007, +0x0, 0x8ee24e1c, 0x24420001, 0x10a20005, 0x0, 0x80025f7, +0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020, 0xaf820108, +0x8f820108, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x800260d, +0x0, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021, +0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, +0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, +0x34028100, 0xafab0010, 0x8ee27254, 0x3c040001, 0x24844af0, 0x3c050004, +0xafa20014, 0x8ee604d4, 0x80028be, 0x34a5f015, 0x8ee37254, 0xa462000c, +0x8ee37254, 0x9582000e, 0xa462000e, 0x8002681, 0x24e70004, 0x8f840100, 0x27623000, 0x24850020, 0xa2102b, 0x50400001, 0x27652800, 0x8f820108, -0x14a20006, 0x2402000c, 0x8ee201a4, 0x24420001, 0xaee201a4, 0x80024cd, -0x8ee201a4, 0xac8a0000, 0xac8b0004, 0x8ee37254, 0x24060005, 0xa482000e, -0xac860018, 0xac830008, 0x8ee204d4, 0xac82001c, 0x8ee204b8, 0xac820010, -0xaf850100, 0x92e204dc, 0x14400036, 0x24090001, 0x8ee24e18, 0x210c0, -0x24424e28, 0x2e22021, 0x8c820000, 0x1446001f, 0x0, 0x8ee34e18, +0x10a20004, 0x0, 0x8f820104, 0x14a20007, 0x24020006, 0x8ee201a4, +0x4821, 0x24420001, 0xaee201a4, 0x8002677, 0x8ee201a4, 0xac8a0000, +0xac8b0004, 0x8ee37254, 0xa487000e, 0xac820018, 0xac830008, 0x8ee204d4, +0xac82001c, 0x8ee204b8, 0x3c030002, 0x431025, 0xac820010, 0xaf850100, +0x92e204dc, 0x14400037, 0x24090001, 0x8ee24e18, 0x210c0, 0x24424e28, +0x2e22021, 0x8c830000, 0x24020005, 0x1462001f, 0x0, 0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007, 0x0, 0x8ee24e1c, -0x24420001, 0x10a20005, 0x0, 0x80024b7, 0x0, 0x14a00005, +0x24420001, 0x10a20005, 0x0, 0x8002661, 0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, -0x2c420011, 0x50400013, 0xac800000, 0x80024cd, 0x0, 0x8ee24e18, +0x2c420011, 0x50400013, 0xac800000, 0x8002677, 0x0, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x24020005, -0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x3c040001, 0xafab0010, -0x8ee27254, 0x3c040001, 0x248448e0, 0x3c050004, 0xafa20014, 0x8ee604d4, -0x800284a, 0x34a5f114, 0x8ee27254, 0x34843800, 0x3641821, 0x24420010, -0x43102b, 0x14400070, 0x0, 0x8ee27254, 0x24480010, 0x3641021, -0x102102b, 0x14400002, 0x3c02ffff, 0x1024021, 0x8f850100, 0x27623000, -0x24a60020, 0xc2102b, 0x50400001, 0x27662800, 0x8f820108, 0x14c20007, -0x2563000c, 0x8ee201a4, 0x4821, 0x24420001, 0xaee201a4, 0x800253e, -0x8ee201a4, 0x2c64000c, 0x1441021, 0xaca20000, 0xaca30004, 0x24e2fff4, -0xa4a2000e, 0x24020006, 0xaca80008, 0xaca20018, 0x8ee204d4, 0xaca2001c, -0x8ee204b8, 0x3c030002, 0x431025, 0xaca20010, 0xaf860100, 0x92e204dc, -0x14400037, 0x24090001, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, -0x8c830000, 0x24020005, 0x1462001f, 0x0, 0x8ee34e18, 0x8ee24e1c, -0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c, -0x8ee54e18, 0x24420001, 0x10430007, 0x0, 0x8ee24e1c, 0x24420001, -0x10a20005, 0x0, 0x8002528, 0x0, 0x14a00005, 0x0, -0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, -0x50400013, 0xac800000, 0x800253e, 0x0, 0x8ee24e18, 0x24030040, -0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, -0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x24020005, 0xac820000, -0x24020001, 0xac820004, 0x1520000a, 0x2508fffc, 0xafab0010, 0x8ee27254, -0x3c040001, 0x248448e0, 0x3c050004, 0xafa20014, 0x8ee604d4, 0x800284a, -0x34a5f125, 0x34028100, 0xa5020000, 0x9582000e, 0x80025b8, 0xa5020002, -0x8f850100, 0x27623000, 0x24a60020, 0xc2102b, 0x50400001, 0x27662800, -0x8f820108, 0x14c20007, 0x2563000c, 0x8ee201a4, 0x4821, 0x24420001, -0xaee201a4, 0x80025a8, 0x8ee201a4, 0x2c64000c, 0x1441021, 0xaca20000, -0xaca30004, 0x8ee37254, 0x24e2fff4, 0xa4a2000e, 0x24020006, 0xaca20018, -0x24630010, 0xaca30008, 0x8ee204d4, 0xaca2001c, 0x8ee204b8, 0x3c030002, +0xac820000, 0x24020001, 0xac820004, 0x15200009, 0x3c050004, 0xafab0010, +0x8ee27254, 0x3c040001, 0x24844af0, 0xafa20014, 0x8ee604d4, 0x80028be, +0x34a5f004, 0x8ee2724c, 0x30e7ffff, 0x471021, 0xaee2724c, 0x8ee204d4, +0x8ee304ec, 0x8ee47248, 0x21100, 0x431021, 0xac44000c, 0x8ee27248, +0xafa20018, 0x8ee3724c, 0xafa3001c, 0x8ee2724c, 0x2c42003c, 0x10400004, +0x24620001, 0x2403fffe, 0x431024, 0xafa2001c, 0x8ee27254, 0x3c060001, +0x34c63800, 0x8ee3724c, 0x2405fff8, 0x471021, 0x24420007, 0x451024, +0x24630007, 0xaee27248, 0x8ee2725c, 0x8ee47248, 0x651824, 0x431023, +0xaee2725c, 0x3661021, 0x82202b, 0x14800004, 0x3c03ffff, 0x8ee27248, +0x431021, 0xaee27248, 0x8ee27248, 0xaee27254, 0x8f8200f0, 0x24470008, +0x27621800, 0xe2102b, 0x50400001, 0x27671000, 0x8f8200f4, 0x14e20007, +0x0, 0x8ee201b0, 0x4821, 0x24420001, 0xaee201b0, 0x80026c4, +0x8ee201b0, 0x8f8200f0, 0x24090001, 0x8fa30018, 0x8fa4001c, 0xac430000, +0xac440004, 0xaf8700f0, 0x15200012, 0xd1142, 0x8f8200f0, 0xafa20010, +0x8f8200f4, 0x3c040001, 0x24844afc, 0xafa20014, 0x8fa60018, 0x8fa7001c, +0x3c050004, 0xc002403, 0x34a5f005, 0x8ee20088, 0x24420001, 0xaee20088, +0x8ee20088, 0x80028d3, 0xaee0724c, 0x30430003, 0x24020002, 0x10620016, +0x28620003, 0x10400005, 0x24020001, 0x10620008, 0x0, 0x8002703, +0x0, 0x24020003, 0x10620017, 0x0, 0x8002703, 0x0, +0x8ee200e8, 0x8ee300ec, 0x24630001, 0x2c640001, 0x441021, 0xaee200e8, +0xaee300ec, 0x8ee200e8, 0x8002703, 0x8ee300ec, 0x8ee200f0, 0x8ee300f4, +0x24630001, 0x2c640001, 0x441021, 0xaee200f0, 0xaee300f4, 0x8ee200f0, +0x8002703, 0x8ee300f4, 0x8ee200f8, 0x8ee300fc, 0x24630001, 0x2c640001, +0x441021, 0xaee200f8, 0xaee300fc, 0x8ee200f8, 0x8ee300fc, 0x8ee2724c, +0x8ee400e0, 0x8ee500e4, 0x401821, 0x1021, 0xa32821, 0xa3302b, +0x822021, 0x862021, 0xaee400e0, 0xaee500e4, 0x80028d3, 0xaee0724c, +0x30e2ffff, 0x104001c1, 0x31a20200, 0x1040014d, 0x4821, 0x96e2045a, +0x30420010, 0x10400149, 0x0, 0x8f840100, 0x27623000, 0x24850020, +0xa2102b, 0x50400001, 0x27652800, 0x8f820108, 0x10a20004, 0x0, +0x8f820104, 0x14a20006, 0x2402000c, 0x8ee201a4, 0x24420001, 0xaee201a4, +0x800276e, 0x8ee201a4, 0xac8a0000, 0xac8b0004, 0x8ee37254, 0x24060005, +0xa482000e, 0xac860018, 0xac830008, 0x8ee204d4, 0xac82001c, 0x8ee204b8, +0xac820010, 0xaf850100, 0x92e204dc, 0x14400036, 0x24090001, 0x8ee24e18, +0x210c0, 0x24424e28, 0x2e22021, 0x8c820000, 0x1446001f, 0x0, +0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, +0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007, 0x0, +0x8ee24e1c, 0x24420001, 0x10a20005, 0x0, 0x8002758, 0x0, +0x14a00005, 0x0, 0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, +0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x800276e, 0x0, +0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, +0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, +0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x3c040001, +0xafab0010, 0x8ee27254, 0x3c040001, 0x24844af0, 0x3c050004, 0xafa20014, +0x8ee604d4, 0x80028be, 0x34a5f014, 0x8ee27254, 0x34843800, 0x3641821, +0x24420010, 0x43102b, 0x14400073, 0x0, 0x8ee27254, 0x24480010, +0x3641021, 0x102102b, 0x14400002, 0x3c02ffff, 0x1024021, 0x8f850100, +0x27623000, 0x24a60020, 0xc2102b, 0x50400001, 0x27662800, 0x8f820108, +0x10c20004, 0x0, 0x8f820104, 0x14c20007, 0x2563000c, 0x8ee201a4, +0x4821, 0x24420001, 0xaee201a4, 0x80027e2, 0x8ee201a4, 0x2c64000c, +0x1441021, 0xaca20000, 0xaca30004, 0x24e2fff4, 0xa4a2000e, 0x24020006, +0xaca80008, 0xaca20018, 0x8ee204d4, 0xaca2001c, 0x8ee204b8, 0x3c030002, 0x431025, 0xaca20010, 0xaf860100, 0x92e204dc, 0x14400037, 0x24090001, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x8c830000, 0x24020005, 0x1462001f, 0x0, 0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007, 0x0, 0x8ee24e1c, 0x24420001, 0x10a20005, 0x0, -0x8002592, 0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020, +0x80027cc, 0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, -0x80025a8, 0x0, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, +0x80027e2, 0x0, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, -0x1520000a, 0x34028100, 0xafab0010, 0x8ee27254, 0x3c040001, 0x248448e0, -0x3c050004, 0xafa20014, 0x8ee604d4, 0x800284a, 0x34a5f015, 0x8ee37254, -0xa462000c, 0x8ee37254, 0x9582000e, 0xa462000e, 0x8002619, 0x24e70004, -0x8f840100, 0x27623000, 0x24850020, 0xa2102b, 0x50400001, 0x27652800, -0x8f820108, 0x14a20007, 0x24020006, 0x8ee201a4, 0x4821, 0x24420001, -0xaee201a4, 0x800260f, 0x8ee201a4, 0xac8a0000, 0xac8b0004, 0x8ee37254, -0xa487000e, 0xac820018, 0xac830008, 0x8ee204d4, 0xac82001c, 0x8ee204b8, -0x3c030002, 0x431025, 0xac820010, 0xaf850100, 0x92e204dc, 0x14400037, +0x1520000a, 0x2508fffc, 0xafab0010, 0x8ee27254, 0x3c040001, 0x24844af0, +0x3c050004, 0xafa20014, 0x8ee604d4, 0x80028be, 0x34a5f015, 0x34028100, +0xa5020000, 0x9582000e, 0x800285f, 0xa5020002, 0x8f850100, 0x27623000, +0x24a60020, 0xc2102b, 0x50400001, 0x27662800, 0x8f820108, 0x10c20004, +0x0, 0x8f820104, 0x14c20007, 0x2563000c, 0x8ee201a4, 0x4821, +0x24420001, 0xaee201a4, 0x800284f, 0x8ee201a4, 0x2c64000c, 0x1441021, +0xaca20000, 0xaca30004, 0x8ee37254, 0x24e2fff4, 0xa4a2000e, 0x24020006, +0xaca20018, 0x24630010, 0xaca30008, 0x8ee204d4, 0xaca2001c, 0x8ee204b8, +0x3c030002, 0x431025, 0xaca20010, 0xaf860100, 0x92e204dc, 0x14400037, 0x24090001, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x8c830000, 0x24020005, 0x1462001f, 0x0, 0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007, 0x0, 0x8ee24e1c, 0x24420001, 0x10a20005, -0x0, 0x80025f9, 0x0, 0x14a00005, 0x0, 0x8f820108, +0x0, 0x8002839, 0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, 0x50400013, -0xac800000, 0x800260f, 0x0, 0x8ee24e18, 0x24030040, 0x24420001, +0xac800000, 0x800284f, 0x0, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, -0xac820004, 0x15200009, 0x3c050004, 0xafab0010, 0x8ee27254, 0x3c040001, -0x248448e0, 0xafa20014, 0x8ee604d4, 0x800284a, 0x34a5f004, 0x8ee2724c, -0x30e7ffff, 0x471021, 0xaee2724c, 0x8ee204d4, 0x8ee304ec, 0x8ee47248, -0x21100, 0x431021, 0xac44000c, 0x8ee27248, 0xafa20018, 0x8ee3724c, -0xafa3001c, 0x8ee2724c, 0x2c42003c, 0x10400004, 0x24620001, 0x2403fffe, -0x431024, 0xafa2001c, 0x8ee27254, 0x3c060001, 0x34c63800, 0x8ee3724c, -0x2405fff8, 0x471021, 0x24420007, 0x451024, 0x24630007, 0xaee27248, -0x8ee2725c, 0x8ee47248, 0x651824, 0x431023, 0xaee2725c, 0x3661021, -0x82202b, 0x14800004, 0x3c03ffff, 0x8ee27248, 0x431021, 0xaee27248, -0x8ee27248, 0xaee27254, 0x8f8200f0, 0x24470008, 0x27621800, 0xe2102b, -0x50400001, 0x27671000, 0x8f8200f4, 0x14e20007, 0x0, 0x8ee201b0, -0x4821, 0x24420001, 0xaee201b0, 0x800265c, 0x8ee201b0, 0x8f8200f0, -0x24090001, 0x8fa30018, 0x8fa4001c, 0xac430000, 0xac440004, 0xaf8700f0, -0x15200012, 0xd1142, 0x8f8200f0, 0xafa20010, 0x8f8200f4, 0x3c040001, -0x248448ec, 0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050004, 0xc0023a7, -0x34a5f005, 0x8ee20088, 0x24420001, 0xaee20088, 0x8ee20088, 0x800285f, -0xaee0724c, 0x30430003, 0x24020002, 0x10620016, 0x28620003, 0x10400005, -0x24020001, 0x10620008, 0x0, 0x800269b, 0x0, 0x24020003, -0x10620017, 0x0, 0x800269b, 0x0, 0x8ee200e8, 0x8ee300ec, -0x24630001, 0x2c640001, 0x441021, 0xaee200e8, 0xaee300ec, 0x8ee200e8, -0x800269b, 0x8ee300ec, 0x8ee200f0, 0x8ee300f4, 0x24630001, 0x2c640001, -0x441021, 0xaee200f0, 0xaee300f4, 0x8ee200f0, 0x800269b, 0x8ee300f4, -0x8ee200f8, 0x8ee300fc, 0x24630001, 0x2c640001, 0x441021, 0xaee200f8, -0xaee300fc, 0x8ee200f8, 0x8ee300fc, 0x8ee2724c, 0x8ee400e0, 0x8ee500e4, -0x401821, 0x1021, 0xa32821, 0xa3302b, 0x822021, 0x862021, -0xaee400e0, 0xaee500e4, 0x800285f, 0xaee0724c, 0x30e2ffff, 0x104001b5, -0x31a20200, 0x10400144, 0x4821, 0x96e2045a, 0x30420010, 0x10400140, -0x0, 0x8f840100, 0x27623000, 0x24850020, 0xa2102b, 0x50400001, -0x27652800, 0x8f820108, 0x14a20006, 0x2402000c, 0x8ee201a4, 0x24420001, -0xaee201a4, 0x8002703, 0x8ee201a4, 0xac8a0000, 0xac8b0004, 0x8ee37254, -0x24060005, 0xa482000e, 0xac860018, 0xac830008, 0x8ee204d4, 0xac82001c, -0x8ee204b8, 0xac820010, 0xaf850100, 0x92e204dc, 0x14400036, 0x24090001, -0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x8c820000, 0x1446001f, -0x0, 0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004, -0x24420001, 0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007, -0x0, 0x8ee24e1c, 0x24420001, 0x10a20005, 0x0, 0x80026ed, -0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020, 0xaf820108, -0x8f820108, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x8002703, -0x0, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021, -0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, -0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, -0x3c040001, 0xafab0010, 0x8ee27254, 0x3c040001, 0x248448e0, 0x3c050004, -0xafa20014, 0x8ee604d4, 0x800284a, 0x34a5f014, 0x8ee27254, 0x34843800, -0x3641821, 0x24420010, 0x43102b, 0x14400070, 0x0, 0x8ee27254, -0x24480010, 0x3641021, 0x102102b, 0x14400002, 0x3c02ffff, 0x1024021, -0x8f850100, 0x27623000, 0x24a60020, 0xc2102b, 0x50400001, 0x27662800, -0x8f820108, 0x14c20007, 0x2563000c, 0x8ee201a4, 0x4821, 0x24420001, -0xaee201a4, 0x8002774, 0x8ee201a4, 0x2c64000c, 0x1441021, 0xaca20000, -0xaca30004, 0x24e2fff4, 0xa4a2000e, 0x24020006, 0xaca80008, 0xaca20018, -0x8ee204d4, 0xaca2001c, 0x8ee204b8, 0x3c030002, 0x431025, 0xaca20010, -0xaf860100, 0x92e204dc, 0x14400037, 0x24090001, 0x8ee24e18, 0x210c0, -0x24424e28, 0x2e22021, 0x8c830000, 0x24020005, 0x1462001f, 0x0, -0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, -0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007, 0x0, -0x8ee24e1c, 0x24420001, 0x10a20005, 0x0, 0x800275e, 0x0, -0x14a00005, 0x0, 0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, -0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x8002774, 0x0, -0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, -0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, -0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x2508fffc, -0xafab0010, 0x8ee27254, 0x3c040001, 0x248448e0, 0x3c050004, 0xafa20014, -0x8ee604d4, 0x800284a, 0x34a5f015, 0x34028100, 0xa5020000, 0x9582000e, -0x80027ee, 0xa5020002, 0x8f850100, 0x27623000, 0x24a60020, 0xc2102b, -0x50400001, 0x27662800, 0x8f820108, 0x14c20007, 0x2563000c, 0x8ee201a4, -0x4821, 0x24420001, 0xaee201a4, 0x80027de, 0x8ee201a4, 0x2c64000c, -0x1441021, 0xaca20000, 0xaca30004, 0x8ee37254, 0x24e2fff4, 0xa4a2000e, -0x24020006, 0xaca20018, 0x24630010, 0xaca30008, 0x8ee204d4, 0xaca2001c, -0x8ee204b8, 0x3c030002, 0x431025, 0xaca20010, 0xaf860100, 0x92e204dc, -0x14400037, 0x24090001, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, -0x8c830000, 0x24020005, 0x1462001f, 0x0, 0x8ee34e18, 0x8ee24e1c, +0xac820004, 0x1520000a, 0x34028100, 0xafab0010, 0x8ee27254, 0x3c040001, +0x24844af0, 0x3c050004, 0xafa20014, 0x8ee604d4, 0x80028be, 0x34a5f016, +0x8ee37254, 0xa462000c, 0x8ee37254, 0x9582000e, 0xa462000e, 0x80028c2, +0x24e70004, 0x8f830100, 0x27623000, 0x24640020, 0x82102b, 0x50400001, +0x27642800, 0x8f820108, 0x10820004, 0x0, 0x8f820104, 0x14820007, +0x24050005, 0x8ee201a4, 0x4821, 0x24420001, 0xaee201a4, 0x80028b6, +0x8ee201a4, 0xac6a0000, 0xac6b0004, 0x8ee27254, 0xa467000e, 0xac650018, +0xac620008, 0x8ee204d4, 0xac62001c, 0x8ee204b8, 0xac620010, 0xaf840100, +0x92e204dc, 0x14400036, 0x24090001, 0x8ee24e18, 0x210c0, 0x24424e28, +0x2e22021, 0x8c820000, 0x1445001f, 0x0, 0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007, 0x0, 0x8ee24e1c, 0x24420001, -0x10a20005, 0x0, 0x80027c8, 0x0, 0x14a00005, 0x0, +0x10a20005, 0x0, 0x80028a0, 0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, -0x50400013, 0xac800000, 0x80027de, 0x0, 0x8ee24e18, 0x24030040, +0x50400013, 0xac800000, 0x80028b6, 0x0, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x24020005, 0xac820000, -0x24020001, 0xac820004, 0x1520000a, 0x34028100, 0xafab0010, 0x8ee27254, -0x3c040001, 0x248448e0, 0x3c050004, 0xafa20014, 0x8ee604d4, 0x800284a, -0x34a5f016, 0x8ee37254, 0xa462000c, 0x8ee37254, 0x9582000e, 0xa462000e, -0x800284e, 0x24e70004, 0x8f830100, 0x27623000, 0x24640020, 0x82102b, -0x50400001, 0x27642800, 0x8f820108, 0x14820007, 0x24050005, 0x8ee201a4, -0x4821, 0x24420001, 0xaee201a4, 0x8002842, 0x8ee201a4, 0xac6a0000, -0xac6b0004, 0x8ee27254, 0xa467000e, 0xac650018, 0xac620008, 0x8ee204d4, -0xac62001c, 0x8ee204b8, 0xac620010, 0xaf840100, 0x92e204dc, 0x14400036, -0x24090001, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x8c820000, +0x24020001, 0xac820004, 0x1520000b, 0x3c050004, 0x3c040001, 0x24844b08, +0xafab0010, 0xafa00014, 0x8ee604d4, 0x34a5f017, 0xc002403, 0x30e7ffff, +0x80028e1, 0x0, 0x8ee27254, 0x3c050001, 0x30e4ffff, 0x441021, +0xaee27254, 0x8ee2724c, 0x8ee37254, 0x34a53800, 0x441021, 0xaee2724c, +0x3651021, 0x62182b, 0x14600004, 0x3c03ffff, 0x8ee27254, 0x431021, +0xaee27254, 0x8ee304d4, 0x96e20458, 0x24630001, 0x2442ffff, 0x621824, +0xaee304d4, 0x8ee304d4, 0x8ee204d0, 0x14620005, 0x0, 0x8f820060, +0x2403fff7, 0x431024, 0xaf820060, 0x8fbf0020, 0x3e00008, 0x27bd0028, +0x27bdffe0, 0xafbf0018, 0x8ee304d8, 0x8ee204d0, 0x10620189, 0x0, +0x8ee204d8, 0x8ee304ec, 0x21100, 0x621821, 0x94670008, 0x92e204dd, +0x8c680000, 0x8c690004, 0x10400023, 0x946a000a, 0x8ee204b8, 0x34460400, +0x31420200, 0x1040001f, 0x0, 0x96e2045a, 0x30420010, 0x1040001b, +0x3c028000, 0x3c010001, 0x370821, 0xac2283c8, 0x8ee27254, 0x9464000e, +0x3c050001, 0x34a53800, 0x24420004, 0xaee27254, 0x8ee37254, 0x42400, +0x3651021, 0x3c010001, 0x370821, 0xac2483cc, 0x62182b, 0x14600005, +0x24e70004, 0x8ee27254, 0x3c03ffff, 0x431021, 0xaee27254, 0x8ee27254, +0x8002917, 0xaee27248, 0x8ee604b8, 0x8ee2725c, 0x30e4ffff, 0x44102a, +0x10400015, 0x0, 0x8f8200d8, 0x8ee37248, 0x431023, 0xaee2725c, +0x8ee2725c, 0x1c400007, 0x44102a, 0x8ee2725c, 0x3c030001, 0x431021, +0xaee2725c, 0x8ee2725c, 0x44102a, 0x10400006, 0x0, 0x8ee201b4, +0x24420001, 0xaee201b4, 0x8002a72, 0x8ee201b4, 0x3c020001, 0x571021, +0x8c4283c8, 0x54400001, 0x24e7fffc, 0x31420004, 0x104000b9, 0x30e2ffff, +0x3c020001, 0x571021, 0x8c4283c8, 0x1040002f, 0x5021, 0x8f840100, +0x27623000, 0x24850020, 0xa2102b, 0x50400001, 0x27652800, 0x8f820108, +0x10a20032, 0x0, 0x8f820104, 0x10a2002f, 0x24020015, 0xac880000, +0xac890004, 0x8ee37254, 0xa487000e, 0xac820018, 0xac830008, 0x8ee204d8, +0x3c030001, 0x771821, 0x8c6383cc, 0xac860010, 0x431025, 0xac82001c, +0xaf850100, 0x92e204dc, 0x14400066, 0x240a0001, 0x8ee24e18, 0x24030040, +0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, +0x8ee24e18, 0x210c0, 0x24424e28, 0x2e21821, 0x24020015, 0xac620000, +0x24020001, 0x80029bf, 0xac620004, 0x8f840100, 0x27623000, 0x24850020, +0xa2102b, 0x50400001, 0x27652800, 0x8f820108, 0x10a20004, 0x0, +0x8f820104, 0x14a20006, 0x24020006, 0x8ee201a4, 0x24420001, 0xaee201a4, +0x80029bf, 0x8ee201a4, 0xac880000, 0xac890004, 0x8ee37254, 0xa487000e, +0xac820018, 0xac830008, 0x8ee204d8, 0xac860010, 0xac82001c, 0xaf850100, +0x92e204dc, 0x14400037, 0x240a0001, 0x8ee24e18, 0x210c0, 0x24424e28, +0x2e22021, 0x8c830000, 0x24020005, 0x1462001f, 0x0, 0x8ee34e18, +0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, +0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007, 0x0, 0x8ee24e1c, +0x24420001, 0x10a20005, 0x0, 0x80029a9, 0x0, 0x14a00005, +0x0, 0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, +0x2c420011, 0x50400013, 0xac800000, 0x80029bf, 0x0, 0x8ee24e18, +0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, +0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x24020005, +0xac820000, 0x24020001, 0xac820004, 0x1540000a, 0x24020001, 0xafa90010, +0x8ee27254, 0x3c040001, 0x24844af0, 0x3c050004, 0xafa20014, 0x8ee604d4, +0x8002a4f, 0x34a5f204, 0xa2e204dd, 0x8ee204d8, 0x8ee304ec, 0x8ee47248, +0x3c060001, 0x34c63800, 0x3c010001, 0x370821, 0xac2083c8, 0x3c010001, +0x370821, 0xac2083cc, 0x21100, 0x431021, 0xac44000c, 0x8ee27254, +0x2405fff8, 0x30e3ffff, 0x431021, 0x24420007, 0x451024, 0x24630007, +0xaee27248, 0x8ee2725c, 0x8ee47248, 0x651824, 0x431023, 0xaee2725c, +0x3661021, 0x82202b, 0x14800004, 0x3c03ffff, 0x8ee27248, 0x431021, +0xaee27248, 0x8ee27248, 0x8002a64, 0xaee27254, 0x10400073, 0x0, +0x8f830100, 0x27623000, 0x24640020, 0x82102b, 0x14400002, 0x5021, +0x27642800, 0x8f820108, 0x10820004, 0x0, 0x8f820104, 0x14820006, +0x24050005, 0x8ee201a4, 0x24420001, 0xaee201a4, 0x8002a46, 0x8ee201a4, +0xac680000, 0xac690004, 0x8ee27254, 0xa467000e, 0xac650018, 0xac620008, +0x8ee204d8, 0xac660010, 0xac62001c, 0xaf840100, 0x92e204dc, 0x14400036, +0x240a0001, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x8c820000, 0x1445001f, 0x0, 0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007, 0x0, 0x8ee24e1c, 0x24420001, 0x10a20005, 0x0, -0x800282c, 0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020, +0x8002a30, 0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, -0x8002842, 0x0, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, +0x8002a46, 0x0, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, -0x1520000b, 0x3c050004, 0x3c040001, 0x248448f8, 0xafab0010, 0xafa00014, -0x8ee604d4, 0x34a5f017, 0xc0023a7, 0x30e7ffff, 0x800286d, 0x0, -0x8ee27254, 0x3c050001, 0x30e4ffff, 0x441021, 0xaee27254, 0x8ee2724c, -0x8ee37254, 0x34a53800, 0x441021, 0xaee2724c, 0x3651021, 0x62182b, -0x14600004, 0x3c03ffff, 0x8ee27254, 0x431021, 0xaee27254, 0x8ee304d4, -0x96e20458, 0x24630001, 0x2442ffff, 0x621824, 0xaee304d4, 0x8ee304d4, -0x8ee204d0, 0x14620005, 0x0, 0x8f820060, 0x2403fff7, 0x431024, -0xaf820060, 0x8fbf0020, 0x3e00008, 0x27bd0028, 0x27bdffe0, 0xafbf0018, -0x8ee304d8, 0x8ee204d0, 0x10620180, 0x0, 0x8ee204d8, 0x8ee304ec, -0x21100, 0x621821, 0x94670008, 0x92e204dd, 0x8c680000, 0x8c690004, -0x10400023, 0x946a000a, 0x8ee204b8, 0x34460400, 0x31420200, 0x1040001f, -0x0, 0x96e2045a, 0x30420010, 0x1040001b, 0x3c028000, 0x3c010001, -0x370821, 0xac2283c8, 0x8ee27254, 0x9464000e, 0x3c050001, 0x34a53800, -0x24420004, 0xaee27254, 0x8ee37254, 0x42400, 0x3651021, 0x3c010001, -0x370821, 0xac2483cc, 0x62182b, 0x14600005, 0x24e70004, 0x8ee27254, -0x3c03ffff, 0x431021, 0xaee27254, 0x8ee27254, 0x80028a3, 0xaee27248, -0x8ee604b8, 0x8ee2725c, 0x30e4ffff, 0x44102a, 0x10400015, 0x0, -0x8f8200d8, 0x8ee37248, 0x431023, 0xaee2725c, 0x8ee2725c, 0x1c400007, -0x44102a, 0x8ee2725c, 0x3c030001, 0x431021, 0xaee2725c, 0x8ee2725c, -0x44102a, 0x10400006, 0x0, 0x8ee201b4, 0x24420001, 0xaee201b4, -0x80029f5, 0x8ee201b4, 0x3c020001, 0x571021, 0x8c4283c8, 0x54400001, -0x24e7fffc, 0x31420004, 0x104000b3, 0x30e2ffff, 0x3c020001, 0x571021, -0x8c4283c8, 0x1040002c, 0x5021, 0x8f840100, 0x27623000, 0x24850020, -0xa2102b, 0x50400001, 0x27652800, 0x8f820108, 0x10a2002c, 0x24020015, -0xac880000, 0xac890004, 0x8ee37254, 0xa487000e, 0xac820018, 0xac830008, -0x8ee204d8, 0x3c030001, 0x771821, 0x8c6383cc, 0xac860010, 0x431025, -0xac82001c, 0xaf850100, 0x92e204dc, 0x14400063, 0x240a0001, 0x8ee24e18, -0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, -0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e21821, 0x24020015, -0xac620000, 0x24020001, 0x8002945, 0xac620004, 0x8f840100, 0x27623000, -0x24850020, 0xa2102b, 0x50400001, 0x27652800, 0x8f820108, 0x14a20006, -0x24020006, 0x8ee201a4, 0x24420001, 0xaee201a4, 0x8002945, 0x8ee201a4, -0xac880000, 0xac890004, 0x8ee37254, 0xa487000e, 0xac820018, 0xac830008, -0x8ee204d8, 0xac860010, 0xac82001c, 0xaf850100, 0x92e204dc, 0x14400037, -0x240a0001, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x8c830000, -0x24020005, 0x1462001f, 0x0, 0x8ee34e18, 0x8ee24e1c, 0x1062001b, -0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c, 0x8ee54e18, -0x24420001, 0x10430007, 0x0, 0x8ee24e1c, 0x24420001, 0x10a20005, -0x0, 0x800292f, 0x0, 0x14a00005, 0x0, 0x8f820108, -0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, 0x50400013, -0xac800000, 0x8002945, 0x0, 0x8ee24e18, 0x24030040, 0x24420001, -0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, -0x210c0, 0x24424e28, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, -0xac820004, 0x1540000a, 0x24020001, 0xafa90010, 0x8ee27254, 0x3c040001, -0x248448e0, 0x3c050004, 0xafa20014, 0x8ee604d4, 0x80029d2, 0x34a5f204, -0xa2e204dd, 0x8ee204d8, 0x8ee304ec, 0x8ee47248, 0x3c060001, 0x34c63800, -0x3c010001, 0x370821, 0xac2083c8, 0x3c010001, 0x370821, 0xac2083cc, -0x21100, 0x431021, 0xac44000c, 0x8ee27254, 0x2405fff8, 0x30e3ffff, -0x431021, 0x24420007, 0x451024, 0x24630007, 0xaee27248, 0x8ee2725c, -0x8ee47248, 0x651824, 0x431023, 0xaee2725c, 0x3661021, 0x82202b, -0x14800004, 0x3c03ffff, 0x8ee27248, 0x431021, 0xaee27248, 0x8ee27248, -0x80029e7, 0xaee27254, 0x10400070, 0x0, 0x8f830100, 0x27623000, -0x24640020, 0x82102b, 0x14400002, 0x5021, 0x27642800, 0x8f820108, -0x14820006, 0x24050005, 0x8ee201a4, 0x24420001, 0xaee201a4, 0x80029c9, -0x8ee201a4, 0xac680000, 0xac690004, 0x8ee27254, 0xa467000e, 0xac650018, -0xac620008, 0x8ee204d8, 0xac660010, 0xac62001c, 0xaf840100, 0x92e204dc, -0x14400036, 0x240a0001, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, -0x8c820000, 0x1445001f, 0x0, 0x8ee34e18, 0x8ee24e1c, 0x1062001b, -0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c, 0x8ee54e18, -0x24420001, 0x10430007, 0x0, 0x8ee24e1c, 0x24420001, 0x10a20005, -0x0, 0x80029b3, 0x0, 0x14a00005, 0x0, 0x8f820108, -0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, 0x50400013, -0xac800000, 0x80029c9, 0x0, 0x8ee24e18, 0x24030040, 0x24420001, -0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, -0x210c0, 0x24424e28, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, -0xac820004, 0x1540000c, 0x30e5ffff, 0x3c040001, 0x248448f8, 0x3c050004, -0xafa90010, 0xafa00014, 0x8ee604d4, 0x34a5f237, 0xc0023a7, 0x30e7ffff, -0x80029f5, 0x0, 0x8ee27254, 0x451021, 0xaee27254, 0x8ee2725c, -0x8ee37254, 0x3c040001, 0x34843800, 0xa2e004dd, 0x451023, 0xaee2725c, -0x3641021, 0x62182b, 0x14600004, 0x3c03ffff, 0x8ee27254, 0x431021, -0xaee27254, 0x8ee304d8, 0x96e20458, 0x24630001, 0x2442ffff, 0x621824, -0xaee304d8, 0x8ee304d8, 0x8ee204d0, 0x14620005, 0x0, 0x8f820060, -0x2403fff7, 0x431024, 0xaf820060, 0x8fbf0018, 0x3e00008, 0x27bd0020, -0x27bdffe0, 0xafbf001c, 0xafb00018, 0x8f820100, 0x8ee34e1c, 0x8f820104, -0x8f850108, 0x24020040, 0x24630001, 0x50620003, 0x1021, 0x8ee24e1c, -0x24420001, 0xaee24e1c, 0x8ee24e1c, 0x8ee34e1c, 0x210c0, 0x24424e28, -0x2e22021, 0x8ee24e18, 0x8c870004, 0x14620007, 0xa03021, 0x8f820108, -0x24420020, 0xaf820108, 0x8f820108, 0x8002a25, 0xac800000, 0x8ee24e1c, -0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e1c, 0x24420001, -0x210c0, 0x24424e28, 0x2e22021, 0x8c820004, 0x8f830108, 0x21140, -0x621821, 0xaf830108, 0xac800000, 0x8cc30018, 0x2c620002, 0x144000b7, -0x2c620004, 0x5440008a, 0x24030040, 0x2c620007, 0x104000b2, 0x2c620005, -0x144000b0, 0x0, 0x8ee204e0, 0x471021, 0xaee204e0, 0x8ee204e0, -0x8f43023c, 0x43102b, 0x144000b2, 0x0, 0x8ee304d4, 0x8ee204e8, -0x506200ae, 0xa2e004e4, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, -0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, -0x8021, 0x24420001, 0xaee201a0, 0x8002a93, 0x8ee201a0, 0x8ee204d4, -0xac62001c, 0x8ee404a0, 0x8ee504a4, 0x2462001c, 0xac620008, 0x24020008, -0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, -0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x24100001, 0x8ee24e20, -0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, -0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, -0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, -0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x8002a7d, -0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, -0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x8002a93, -0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, -0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, -0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x5600000b, -0x24100001, 0x8ee204d4, 0x3c040001, 0x24844904, 0xafa00014, 0xafa20010, -0x8ee605f8, 0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f006, 0x16000003, -0x24020001, 0x8002ae9, 0xa2e204e4, 0x8ee2016c, 0x24420001, 0xaee2016c, -0x8ee2016c, 0x8ee204d4, 0xa2e004e4, 0xaee004e0, 0xaee204e8, 0x8f42023c, -0x5040003c, 0xaee07264, 0x8ee20180, 0x24420001, 0xaee20180, 0x8ee20180, -0x8002ae9, 0xaee07264, 0x8ee204f4, 0x24420001, 0x50430003, 0x1021, -0x8ee204f4, 0x24420001, 0xaee204f4, 0x8ee204f4, 0x8cc30018, 0x21080, -0x571021, 0x8c4404f8, 0x24020003, 0x1462000f, 0x0, 0x3c020001, -0x571021, 0x904283a1, 0x10400014, 0x0, 0x8ee201c8, 0x8ee35230, -0x441021, 0xaee201c8, 0x8ee201cc, 0x641821, 0x306300ff, 0x8002ad9, -0xaee35230, 0x8ee201c4, 0x8ee30e00, 0x441021, 0xaee201c4, 0x8ee201cc, -0x641821, 0x306301ff, 0xaee30e00, 0x441021, 0xaee201cc, 0x8ee20000, -0x34420040, 0x8002ae9, 0xaee20000, 0x94c7000e, 0x8cc2001c, 0x3c040001, -0x24844910, 0xafa60014, 0xafa20010, 0x8cc60018, 0x3c050008, 0xc0023a7, -0x34a50910, 0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020, 0x27bdff98, -0xafbf0060, 0xafbe005c, 0xafb60058, 0xafb50054, 0xafb40050, 0xafb3004c, -0xafb20048, 0xafb10044, 0xafb00040, 0x8f830108, 0x8f820104, 0xafa00024, -0x106203d9, 0xafa0002c, 0x3c1e0001, 0x37de3800, 0x3c0bffff, 0x8f930108, -0x8e620018, 0x8f830104, 0x2443fffe, 0x2c620014, 0x104003c1, 0x31080, -0x3c010001, 0x220821, 0x8c224920, 0x400008, 0x0, 0x9663000e, -0x8ee2724c, 0x8ee404e0, 0x431021, 0xaee2724c, 0x8e63001c, 0x96e20458, -0x24840001, 0xaee404e0, 0x24630001, 0x2442ffff, 0x621824, 0xaee304d4, -0x8f42023c, 0x82202b, 0x148003ab, 0x0, 0x8f830120, 0x27623800, -0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, -0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8002b73, +0x1540000c, 0x30e5ffff, 0x3c040001, 0x24844b08, 0x3c050004, 0xafa90010, +0xafa00014, 0x8ee604d4, 0x34a5f237, 0xc002403, 0x30e7ffff, 0x8002a72, +0x0, 0x8ee27254, 0x451021, 0xaee27254, 0x8ee2725c, 0x8ee37254, +0x3c040001, 0x34843800, 0xa2e004dd, 0x451023, 0xaee2725c, 0x3641021, +0x62182b, 0x14600004, 0x3c03ffff, 0x8ee27254, 0x431021, 0xaee27254, +0x8ee304d8, 0x96e20458, 0x24630001, 0x2442ffff, 0x621824, 0xaee304d8, +0x8ee304d8, 0x8ee204d0, 0x14620005, 0x0, 0x8f820060, 0x2403fff7, +0x431024, 0xaf820060, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffe0, +0xafbf001c, 0xafb00018, 0x8f820100, 0x8ee34e1c, 0x8f820104, 0x8f850108, +0x24020040, 0x24630001, 0x50620003, 0x1021, 0x8ee24e1c, 0x24420001, +0xaee24e1c, 0x8ee24e1c, 0x8ee34e1c, 0x210c0, 0x24424e28, 0x2e22021, +0x8ee24e18, 0x8c870004, 0x14620007, 0xa03021, 0x8f820108, 0x24420020, +0xaf820108, 0x8f820108, 0x8002aa2, 0xac800000, 0x8ee24e1c, 0x24030040, +0x24420001, 0x50430003, 0x1021, 0x8ee24e1c, 0x24420001, 0x210c0, +0x24424e28, 0x2e22021, 0x8c820004, 0x8f830108, 0x21140, 0x621821, +0xaf830108, 0xac800000, 0x8cc30018, 0x2c620002, 0x144000ba, 0x2c620004, +0x5440008d, 0x24030040, 0x2c620007, 0x104000b5, 0x2c620005, 0x144000b3, +0x0, 0x8ee204e0, 0x471021, 0xaee204e0, 0x8ee204e0, 0x8f43023c, +0x43102b, 0x144000b5, 0x0, 0x8ee304d4, 0x8ee204e8, 0x506200b1, +0xa2e004e4, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, +0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124, 0x14c20007, +0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8002b13, 0x8ee201a0, 0x8ee204d4, 0xac62001c, 0x8ee404a0, 0x8ee504a4, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, -0x240c0040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, -0x24420001, 0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, -0x0, 0x8002b5d, 0x0, 0x14600005, 0x0, 0x8f820128, +0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, +0x24420001, 0x10430007, 0x0, 0x8ee24e24, 0x24420001, 0x10a20005, +0x0, 0x8002afd, 0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, -0xac800000, 0x8002b73, 0x0, 0x8ee24e20, 0x240c0040, 0x24420001, -0x504c0003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, -0x210c0, 0x24425028, 0x2e22021, 0x24020012, 0x240c0001, 0xac820000, -0xac8c0004, 0x5600000d, 0x24100001, 0x8ee204d4, 0x3c040001, 0x24844904, -0xafa00014, 0xafa20010, 0x8ee605f8, 0x8f470228, 0x3c050009, 0x34a5f006, -0xc0023a7, 0xafab0038, 0x8fab0038, 0x12000307, 0x240c0001, 0x8002e8b, -0x0, 0x966c001c, 0xafac002c, 0x9662001e, 0x3c0c8000, 0xafac0024, -0xae62001c, 0x8e75001c, 0x8ee204ec, 0x8ee404ec, 0x151900, 0x621021, -0x8c52000c, 0x92e27b88, 0x641821, 0x9476000a, 0x14400003, 0x32c20002, -0xaef27b94, 0xaef57b8c, 0x1040004b, 0x8021, 0x96e2045a, 0x30420002, -0x10400047, 0x0, 0x8e63001c, 0x8ee204ec, 0x32100, 0x821021, -0x8c42000c, 0x37e1821, 0x24420022, 0x43102b, 0x1440000a, 0x24050014, -0x8ee204ec, 0x821021, 0x8c44000c, 0xafab0038, 0xc002edf, 0x2484000e, -0x8fab0038, 0x8002bc7, 0x3050ffff, 0x8ee204ec, 0x821021, 0x8c42000c, -0x9450000e, 0x94430010, 0x94440012, 0x94450014, 0x2038021, 0x2048021, -0x2058021, 0x94430016, 0x94440018, 0x9445001a, 0x2038021, 0x2048021, -0x2058021, 0x9443001c, 0x9444001e, 0x94420020, 0x2038021, 0x2048021, -0x2028021, 0x101c02, 0x3202ffff, 0x628021, 0x8e63001c, 0x8ee204ec, -0x102402, 0x32900, 0xa21021, 0x8c43000c, 0x3202ffff, 0x828021, -0x37e1021, 0x24630018, 0x62182b, 0x14600009, 0x0, 0x8ee204ec, -0xa21021, 0x8c43000c, 0x101027, 0x3c01ffff, 0x230821, 0x8002be4, -0xa4220018, 0x8ee204ec, 0xa21021, 0x8c43000c, 0x101027, 0xa4620018, -0x96e2045a, 0x8821, 0x30420008, 0x14400063, 0xa021, 0x8e63001c, -0x8ee204ec, 0x33100, 0xc21021, 0x8c42000c, 0x37e1821, 0x24420022, -0x43102b, 0x14400035, 0x0, 0x8ee204ec, 0xc21021, 0x8c42000c, -0x24470010, 0x37e1021, 0xe2102b, 0x50400001, 0xeb3821, 0x8ee204ec, -0x94f10000, 0xc21021, 0x8c42000c, 0x24470016, 0x37e1021, 0xe2102b, -0x14400002, 0x2634ffec, 0xeb3821, 0x8ee204ec, 0x90e30001, 0xc21021, -0x8c42000c, 0x2447001a, 0x37e1021, 0xe2102b, 0x14400002, 0x2838821, +0xac800000, 0x8002b13, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, +0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, +0x210c0, 0x24425028, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, +0xac820004, 0x5600000b, 0x24100001, 0x8ee204d4, 0x3c040001, 0x24844b14, +0xafa00014, 0xafa20010, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403, +0x34a5f006, 0x16000003, 0x24020001, 0x8002b69, 0xa2e204e4, 0x8ee2016c, +0x24420001, 0xaee2016c, 0x8ee2016c, 0x8ee204d4, 0xa2e004e4, 0xaee004e0, +0xaee204e8, 0x8f42023c, 0x5040003c, 0xaee07264, 0x8ee20180, 0x24420001, +0xaee20180, 0x8ee20180, 0x8002b69, 0xaee07264, 0x8ee204f4, 0x24420001, +0x50430003, 0x1021, 0x8ee204f4, 0x24420001, 0xaee204f4, 0x8ee204f4, +0x8cc30018, 0x21080, 0x571021, 0x8c4404f8, 0x24020003, 0x1462000f, +0x0, 0x3c020001, 0x571021, 0x904283a1, 0x10400014, 0x0, +0x8ee201c8, 0x8ee35230, 0x441021, 0xaee201c8, 0x8ee201cc, 0x641821, +0x306300ff, 0x8002b59, 0xaee35230, 0x8ee201c4, 0x8ee30e00, 0x441021, +0xaee201c4, 0x8ee201cc, 0x641821, 0x306301ff, 0xaee30e00, 0x441021, +0xaee201cc, 0x8ee20000, 0x34420040, 0x8002b69, 0xaee20000, 0x94c7000e, +0x8cc2001c, 0x3c040001, 0x24844b20, 0xafa60014, 0xafa20010, 0x8cc60018, +0x3c050008, 0xc002403, 0x34a50910, 0x8fbf001c, 0x8fb00018, 0x3e00008, +0x27bd0020, 0x27bdff98, 0xafbf0060, 0xafbe005c, 0xafb60058, 0xafb50054, +0xafb40050, 0xafb3004c, 0xafb20048, 0xafb10044, 0xafb00040, 0x8f830108, +0x8f820104, 0xafa00024, 0x106203df, 0xafa0002c, 0x3c1e0001, 0x37de3800, +0x3c0bffff, 0x8f930108, 0x8e620018, 0x8f830104, 0x2443fffe, 0x2c620014, +0x104003c7, 0x31080, 0x3c010001, 0x220821, 0x8c224b30, 0x400008, +0x0, 0x9663000e, 0x8ee2724c, 0x8ee404e0, 0x431021, 0xaee2724c, +0x8e63001c, 0x96e20458, 0x24840001, 0xaee404e0, 0x24630001, 0x2442ffff, +0x621824, 0xaee304d4, 0x8f42023c, 0x82202b, 0x148003b1, 0x0, +0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, +0x8f820128, 0x10c20004, 0x0, 0x8f820124, 0x14c20007, 0x0, +0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8002bf6, 0x8ee201a0, +0x8ee204d4, 0xac62001c, 0x8ee404a0, 0x8ee504a4, 0x2462001c, 0xac620008, +0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004, +0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x24100001, +0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020012, +0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x240c0040, +0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, +0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, +0x8002be0, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, +0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, +0x8002bf6, 0x0, 0x8ee24e20, 0x240c0040, 0x24420001, 0x504c0003, +0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, +0x24425028, 0x2e22021, 0x24020012, 0x240c0001, 0xac820000, 0xac8c0004, +0x5600000d, 0x24100001, 0x8ee204d4, 0x3c040001, 0x24844b14, 0xafa00014, +0xafa20010, 0x8ee605f8, 0x8f470228, 0x3c050009, 0x34a5f006, 0xc002403, +0xafab0038, 0x8fab0038, 0x1200030a, 0x240c0001, 0x8002f11, 0x0, +0x966c001c, 0xafac002c, 0x9662001e, 0x3c0c8000, 0xafac0024, 0xae62001c, +0x8e75001c, 0x8ee204ec, 0x8ee404ec, 0x151900, 0x621021, 0x8c52000c, +0x92e27b88, 0x641821, 0x9476000a, 0x14400003, 0x32c20002, 0xaef27b94, +0xaef57b8c, 0x1040004b, 0x8021, 0x96e2045a, 0x30420002, 0x10400047, +0x0, 0x8e63001c, 0x8ee204ec, 0x32100, 0x821021, 0x8c42000c, +0x37e1821, 0x24420022, 0x43102b, 0x1440000a, 0x24050014, 0x8ee204ec, +0x821021, 0x8c44000c, 0xafab0038, 0xc002f65, 0x2484000e, 0x8fab0038, +0x8002c4a, 0x3050ffff, 0x8ee204ec, 0x821021, 0x8c42000c, 0x9450000e, +0x94430010, 0x94440012, 0x94450014, 0x2038021, 0x2048021, 0x2058021, +0x94430016, 0x94440018, 0x9445001a, 0x2038021, 0x2048021, 0x2058021, +0x9443001c, 0x9444001e, 0x94420020, 0x2038021, 0x2048021, 0x2028021, +0x101c02, 0x3202ffff, 0x628021, 0x8e63001c, 0x8ee204ec, 0x102402, +0x32900, 0xa21021, 0x8c43000c, 0x3202ffff, 0x828021, 0x37e1021, +0x24630018, 0x62182b, 0x14600009, 0x0, 0x8ee204ec, 0xa21021, +0x8c43000c, 0x101027, 0x3c01ffff, 0x230821, 0x8002c67, 0xa4220018, +0x8ee204ec, 0xa21021, 0x8c43000c, 0x101027, 0xa4620018, 0x96e2045a, +0x8821, 0x30420008, 0x14400063, 0xa021, 0x8e63001c, 0x8ee204ec, +0x33100, 0xc21021, 0x8c42000c, 0x37e1821, 0x24420022, 0x43102b, +0x14400035, 0x0, 0x8ee204ec, 0xc21021, 0x8c42000c, 0x24470010, +0x37e1021, 0xe2102b, 0x50400001, 0xeb3821, 0x8ee204ec, 0x94f10000, +0xc21021, 0x8c42000c, 0x24470016, 0x37e1021, 0xe2102b, 0x14400002, +0x2634ffec, 0xeb3821, 0x8ee204ec, 0x90e30001, 0xc21021, 0x8c42000c, +0x2447001a, 0x37e1021, 0xe2102b, 0x14400002, 0x2838821, 0xeb3821, +0x94e20000, 0x24e70002, 0x2228821, 0x37e1021, 0xe2102b, 0x50400001, 0xeb3821, 0x94e20000, 0x24e70002, 0x2228821, 0x37e1021, 0xe2102b, 0x50400001, 0xeb3821, 0x94e20000, 0x24e70002, 0x2228821, 0x37e1021, -0xe2102b, 0x50400001, 0xeb3821, 0x94e20000, 0x24e70002, 0x2228821, -0x37e1021, 0xe2102b, 0x50400001, 0xeb3821, 0x94e20000, 0x8002c45, -0x2228821, 0x8ee204ec, 0xc21021, 0x8c43000c, 0x8ee204ec, 0x94710010, -0x8ee304ec, 0xc21021, 0x8c44000c, 0xc31821, 0x8c62000c, 0x2634ffec, -0x90840017, 0x8ee304ec, 0x9442001a, 0x2848821, 0xc31821, 0x8c65000c, -0x8ee304ec, 0x2228821, 0x8ee204ec, 0xc31821, 0xc21021, 0x8c44000c, -0x8c62000c, 0x94a3001c, 0x9484001e, 0x94420020, 0x2238821, 0x2248821, -0x2228821, 0x111c02, 0x3222ffff, 0x628821, 0x111c02, 0x3222ffff, -0x628821, 0x32c20001, 0x104000b2, 0x0, 0x96e2045a, 0x30420001, -0x104000ae, 0x32c20080, 0x10400008, 0x0, 0x92e27b88, 0x14400005, -0x0, 0x240c0001, 0xa2ec7b88, 0xaef57b8c, 0xaef27b94, 0x8ee304ec, -0x151100, 0x431021, 0x8c47000c, 0x37e1821, 0x24e2000e, 0x43102b, -0x14400008, 0xe02021, 0x2405000e, 0xc002edf, 0xafab0038, 0x3042ffff, -0x8fab0038, 0x8002c7e, 0x2028021, 0x94e60000, 0x24e70002, 0x94e50000, -0x24e70002, 0x94e30000, 0x24e70002, 0x94e20000, 0x24e70002, 0x94e40000, -0x24e70002, 0x2068021, 0x2058021, 0x2038021, 0x2028021, 0x94e20000, -0x94e30002, 0x2048021, 0x2028021, 0x2038021, 0x101c02, 0x3202ffff, -0x628021, 0x101c02, 0x3202ffff, 0x8ee47b8c, 0x628021, 0x14950004, -0x3205ffff, 0x96620016, 0x8002c8c, 0x512021, 0x96620016, 0x542021, -0x41402, 0x3083ffff, 0x432021, 0x852023, 0x41402, 0x822021, -0x3084ffff, 0x50800001, 0x3404ffff, 0x8ee27b94, 0x24430017, 0x37e1021, -0x62102b, 0x50400001, 0x6b1821, 0x90630000, 0x24020011, 0x14620031, -0x24020006, 0x8ee27b94, 0x37e1821, 0x24420028, 0x43102b, 0x14400018, +0xe2102b, 0x50400001, 0xeb3821, 0x94e20000, 0x8002cc8, 0x2228821, +0x8ee204ec, 0xc21021, 0x8c43000c, 0x8ee204ec, 0x94710010, 0x8ee304ec, +0xc21021, 0x8c44000c, 0xc31821, 0x8c62000c, 0x2634ffec, 0x90840017, +0x8ee304ec, 0x9442001a, 0x2848821, 0xc31821, 0x8c65000c, 0x8ee304ec, +0x2228821, 0x8ee204ec, 0xc31821, 0xc21021, 0x8c44000c, 0x8c62000c, +0x94a3001c, 0x9484001e, 0x94420020, 0x2238821, 0x2248821, 0x2228821, +0x111c02, 0x3222ffff, 0x628821, 0x111c02, 0x3222ffff, 0x628821, +0x32c20001, 0x104000b2, 0x0, 0x96e2045a, 0x30420001, 0x104000ae, +0x32c20080, 0x10400008, 0x0, 0x92e27b88, 0x14400005, 0x0, +0x240c0001, 0xa2ec7b88, 0xaef57b8c, 0xaef27b94, 0x8ee304ec, 0x151100, +0x431021, 0x8c47000c, 0x37e1821, 0x24e2000e, 0x43102b, 0x14400008, +0xe02021, 0x2405000e, 0xc002f65, 0xafab0038, 0x3042ffff, 0x8fab0038, +0x8002d01, 0x2028021, 0x94e60000, 0x24e70002, 0x94e50000, 0x24e70002, +0x94e30000, 0x24e70002, 0x94e20000, 0x24e70002, 0x94e40000, 0x24e70002, +0x2068021, 0x2058021, 0x2038021, 0x2028021, 0x94e20000, 0x94e30002, +0x2048021, 0x2028021, 0x2038021, 0x101c02, 0x3202ffff, 0x628021, +0x101c02, 0x3202ffff, 0x8ee47b8c, 0x628021, 0x14950004, 0x3205ffff, +0x96620016, 0x8002d0f, 0x512021, 0x96620016, 0x542021, 0x41402, +0x3083ffff, 0x432021, 0x852023, 0x41402, 0x822021, 0x3084ffff, +0x50800001, 0x3404ffff, 0x8ee27b94, 0x24430017, 0x37e1021, 0x62102b, +0x50400001, 0x6b1821, 0x90630000, 0x24020011, 0x14620031, 0x24020006, +0x8ee27b94, 0x37e1821, 0x24420028, 0x43102b, 0x14400018, 0x0, +0x8ee27b8c, 0x12a2000a, 0x32c20100, 0x8ee27b94, 0x3c01ffff, 0x220821, +0x94220028, 0x822021, 0x41c02, 0x3082ffff, 0x622021, 0x32c20100, +0x14400004, 0x41027, 0x92e27b88, 0x14400002, 0x41027, 0x3044ffff, +0x8ee27b94, 0x3c01ffff, 0x220821, 0x8002d82, 0xa4240028, 0x8ee27b8c, +0x12a20008, 0x32c20100, 0x8ee27b94, 0x94420028, 0x822021, 0x41c02, +0x3082ffff, 0x622021, 0x32c20100, 0x14400004, 0x41027, 0x92e27b88, +0x14400002, 0x41027, 0x3044ffff, 0x8ee27b94, 0x8002d82, 0xa4440028, +0x1462002f, 0x37e1821, 0x8ee27b94, 0x24420032, 0x43102b, 0x14400018, 0x0, 0x8ee27b8c, 0x12a2000a, 0x32c20100, 0x8ee27b94, 0x3c01ffff, -0x220821, 0x94220028, 0x822021, 0x41c02, 0x3082ffff, 0x622021, +0x220821, 0x94220032, 0x822021, 0x41c02, 0x3082ffff, 0x622021, 0x32c20100, 0x14400004, 0x41027, 0x92e27b88, 0x14400002, 0x41027, -0x3044ffff, 0x8ee27b94, 0x3c01ffff, 0x220821, 0x8002cff, 0xa4240028, -0x8ee27b8c, 0x12a20008, 0x32c20100, 0x8ee27b94, 0x94420028, 0x822021, +0x3044ffff, 0x8ee27b94, 0x3c01ffff, 0x220821, 0x8002d82, 0xa4240032, +0x8ee27b8c, 0x12a20008, 0x32c20100, 0x8ee27b94, 0x94420032, 0x822021, 0x41c02, 0x3082ffff, 0x622021, 0x32c20100, 0x14400004, 0x41027, -0x92e27b88, 0x14400002, 0x41027, 0x3044ffff, 0x8ee27b94, 0x8002cff, -0xa4440028, 0x1462002f, 0x37e1821, 0x8ee27b94, 0x24420032, 0x43102b, -0x14400018, 0x0, 0x8ee27b8c, 0x12a2000a, 0x32c20100, 0x8ee27b94, -0x3c01ffff, 0x220821, 0x94220032, 0x822021, 0x41c02, 0x3082ffff, -0x622021, 0x32c20100, 0x14400004, 0x41027, 0x92e27b88, 0x14400002, -0x41027, 0x3044ffff, 0x8ee27b94, 0x3c01ffff, 0x220821, 0x8002cff, -0xa4240032, 0x8ee27b8c, 0x12a20008, 0x32c20100, 0x8ee27b94, 0x94420032, -0x822021, 0x41c02, 0x3082ffff, 0x622021, 0x32c20100, 0x14400004, -0x41027, 0x92e27b88, 0x14400002, 0x41027, 0x3044ffff, 0x8ee27b94, -0xa4440032, 0x8fac0024, 0x1180002c, 0x37e1821, 0x8e420000, 0xae42fffc, -0x2642000a, 0x43102b, 0x1440001b, 0x34038100, 0x26430004, 0x37e1021, -0x62102b, 0x14400003, 0x602021, 0x6b1821, 0x602021, 0x8c620000, -0x24630004, 0xae420000, 0x37e1021, 0x62102b, 0x50400001, 0x6b1821, -0x8c620000, 0xac820000, 0x34028100, 0xa4620000, 0x24630002, 0x37e1021, -0x62102b, 0x50400001, 0x6b1821, 0x97ac002e, 0x8002d29, 0xa46c0000, -0x8e420004, 0x8e440008, 0xa6430008, 0x97ac002e, 0xa64c000a, 0xae420000, -0xae440004, 0x9662000e, 0x2652fffc, 0x24420004, 0xa662000e, 0x9662000e, -0x8ee3724c, 0x621821, 0xaee3724c, 0xafb20018, 0x8ee3724c, 0xafa3001c, -0x8ee2724c, 0x2c42003c, 0x10400004, 0x24620001, 0x2403fffe, 0x431024, -0xafa2001c, 0x32c20080, 0x1040000c, 0x32c20100, 0x8ee27b98, 0x24430001, +0x92e27b88, 0x14400002, 0x41027, 0x3044ffff, 0x8ee27b94, 0xa4440032, +0x8fac0024, 0x1180002c, 0x37e1821, 0x8e420000, 0xae42fffc, 0x2642000a, +0x43102b, 0x1440001b, 0x34038100, 0x26430004, 0x37e1021, 0x62102b, +0x14400003, 0x602021, 0x6b1821, 0x602021, 0x8c620000, 0x24630004, +0xae420000, 0x37e1021, 0x62102b, 0x50400001, 0x6b1821, 0x8c620000, +0xac820000, 0x34028100, 0xa4620000, 0x24630002, 0x37e1021, 0x62102b, +0x50400001, 0x6b1821, 0x97ac002e, 0x8002dac, 0xa46c0000, 0x8e420004, +0x8e440008, 0xa6430008, 0x97ac002e, 0xa64c000a, 0xae420000, 0xae440004, +0x9662000e, 0x2652fffc, 0x24420004, 0xa662000e, 0x9662000e, 0x8ee3724c, +0x621821, 0xaee3724c, 0xafb20018, 0x8ee3724c, 0xafa3001c, 0x8ee2724c, +0x2c42003c, 0x10400004, 0x24620001, 0x2403fffe, 0x431024, 0xafa2001c, +0x32c20080, 0x1040000c, 0x32c20100, 0x8ee27b98, 0x24430001, 0x210c0, +0x571021, 0xaee37b98, 0x8fa30018, 0x8fa4001c, 0xac437b9c, 0xac447ba0, +0x8002e98, 0xaee0724c, 0x10400072, 0x0, 0x8ee27b98, 0x24430001, 0x210c0, 0x571021, 0xaee37b98, 0x8fa30018, 0x8fa4001c, 0xac437b9c, -0xac447ba0, 0x8002e15, 0xaee0724c, 0x10400072, 0x0, 0x8ee27b98, -0x24430001, 0x210c0, 0x571021, 0xaee37b98, 0x8fa30018, 0x8fa4001c, -0xac437b9c, 0xac447ba0, 0x8ee27b98, 0x10400063, 0x4821, 0x5021, -0x8f8200f0, 0x24480008, 0x27621800, 0x102102b, 0x50400001, 0x27681000, -0x8f8200f4, 0x15020007, 0x0, 0x8ee201b0, 0x8021, 0x24420001, -0xaee201b0, 0x8002d6f, 0x8ee201b0, 0x8f8300f0, 0x24100001, 0x1571021, -0x8c447b9c, 0x8c457ba0, 0xac640000, 0xac650004, 0xaf8800f0, 0x16000006, -0x2ea1021, 0x8ee20088, 0x24420001, 0xaee20088, 0x8002db4, 0x8ee20088, -0x8c427ba0, 0x8ee400e0, 0x8ee500e4, 0x8ee67b8c, 0x401821, 0x1021, -0xa32821, 0xa3382b, 0x822021, 0x872021, 0x8ee204ec, 0xc93021, -0x63100, 0xaee400e0, 0xaee500e4, 0xc23021, 0x94c2000a, 0x240c0002, -0x21142, 0x30430003, 0x106c0016, 0x28620003, 0x10400005, 0x240c0001, -0x106c0008, 0x0, 0x8002db4, 0x0, 0x240c0003, 0x106c0017, -0x0, 0x8002db4, 0x0, 0x8ee200e8, 0x8ee300ec, 0x24630001, -0x2c640001, 0x441021, 0xaee200e8, 0xaee300ec, 0x8ee200e8, 0x8002db4, -0x8ee300ec, 0x8ee200f0, 0x8ee300f4, 0x24630001, 0x2c640001, 0x441021, -0xaee200f0, 0xaee300f4, 0x8ee200f0, 0x8002db4, 0x8ee300f4, 0x8ee200f8, -0x8ee300fc, 0x24630001, 0x2c640001, 0x441021, 0xaee200f8, 0xaee300fc, -0x8ee200f8, 0x8ee300fc, 0x8ee27b98, 0x25290001, 0x122102b, 0x1440ffa0, -0x254a0008, 0xa2e07b88, 0x8002e14, 0xaee07b98, 0x8f8200f0, 0x24470008, -0x27621800, 0xe2102b, 0x50400001, 0x27671000, 0x8f8200f4, 0x14e20007, -0x0, 0x8ee201b0, 0x8021, 0x24420001, 0xaee201b0, 0x8002dd2, -0x8ee201b0, 0x8f8200f0, 0x24100001, 0x8fa30018, 0x8fa4001c, 0xac430000, -0xac440004, 0xaf8700f0, 0x16000007, 0x0, 0x8ee20088, 0x24420001, -0xaee20088, 0x8ee20088, 0x8002e15, 0xaee0724c, 0x8ee2724c, 0x8ee400e0, -0x8ee500e4, 0x240c0002, 0x401821, 0x1021, 0xa32821, 0xa3302b, -0x822021, 0x862021, 0x161142, 0x30430003, 0xaee400e0, 0xaee500e4, -0x106c0017, 0x2c620003, 0x10400005, 0x240c0001, 0x106c0008, 0x0, -0x8002e15, 0xaee0724c, 0x240c0003, 0x106c0019, 0x0, 0x8002e15, -0xaee0724c, 0x8ee200e8, 0x8ee300ec, 0x24630001, 0x2c640001, 0x441021, -0xaee200e8, 0xaee300ec, 0x8ee200e8, 0x8ee300ec, 0x8002e15, 0xaee0724c, +0xac447ba0, 0x8ee27b98, 0x10400063, 0x4821, 0x5021, 0x8f8200f0, +0x24480008, 0x27621800, 0x102102b, 0x50400001, 0x27681000, 0x8f8200f4, +0x15020007, 0x0, 0x8ee201b0, 0x8021, 0x24420001, 0xaee201b0, +0x8002df2, 0x8ee201b0, 0x8f8300f0, 0x24100001, 0x1571021, 0x8c447b9c, +0x8c457ba0, 0xac640000, 0xac650004, 0xaf8800f0, 0x16000006, 0x2ea1021, +0x8ee20088, 0x24420001, 0xaee20088, 0x8002e37, 0x8ee20088, 0x8c427ba0, +0x8ee400e0, 0x8ee500e4, 0x8ee67b8c, 0x401821, 0x1021, 0xa32821, +0xa3382b, 0x822021, 0x872021, 0x8ee204ec, 0xc93021, 0x63100, +0xaee400e0, 0xaee500e4, 0xc23021, 0x94c2000a, 0x240c0002, 0x21142, +0x30430003, 0x106c0016, 0x28620003, 0x10400005, 0x240c0001, 0x106c0008, +0x0, 0x8002e37, 0x0, 0x240c0003, 0x106c0017, 0x0, +0x8002e37, 0x0, 0x8ee200e8, 0x8ee300ec, 0x24630001, 0x2c640001, +0x441021, 0xaee200e8, 0xaee300ec, 0x8ee200e8, 0x8002e37, 0x8ee300ec, 0x8ee200f0, 0x8ee300f4, 0x24630001, 0x2c640001, 0x441021, 0xaee200f0, -0xaee300f4, 0x8ee200f0, 0x8ee300f4, 0x8002e15, 0xaee0724c, 0x8ee200f8, -0x8ee300fc, 0x24630001, 0x2c640001, 0x441021, 0xaee200f8, 0xaee300fc, -0x8ee200f8, 0x8ee300fc, 0xaee0724c, 0x8e62001c, 0x96e30458, 0x8ee404e0, -0x24420001, 0x2463ffff, 0x431024, 0x24840001, 0xaee204d4, 0xaee404e0, -0x8f42023c, 0x82202b, 0x148000a5, 0x0, 0x8f830120, 0x27623800, -0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, -0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8002e79, -0x8ee201a0, 0x8ee204d4, 0xac62001c, 0x8ee404a0, 0x8ee504a4, 0x2462001c, -0xac620008, 0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000, -0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, -0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, -0x24020012, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, -0x240c0040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, -0x24420001, 0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, -0x0, 0x8002e63, 0x0, 0x14600005, 0x0, 0x8f820128, -0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, -0xac800000, 0x8002e79, 0x0, 0x8ee24e20, 0x240c0040, 0x24420001, -0x504c0003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, -0x210c0, 0x24425028, 0x2e22021, 0x24020012, 0x240c0001, 0xac820000, -0xac8c0004, 0x5600000d, 0x24100001, 0x8ee204d4, 0x3c040001, 0x24844904, -0xafa00014, 0xafa20010, 0x8ee605f8, 0x8f470228, 0x3c050009, 0x34a5f006, -0xc0023a7, 0xafab0038, 0x8fab0038, 0x16000003, 0x240c0001, 0x8002ec6, -0xa2ec04e4, 0x8ee2016c, 0x24420001, 0xaee2016c, 0x8ee2016c, 0x8ee204d4, -0xa2e004e4, 0xaee004e0, 0xaee07264, 0xaee204e8, 0x8f42023c, 0x10400030, -0x0, 0x8ee20180, 0x24420001, 0xaee20180, 0x8002ec6, 0x8ee20180, -0x8ee204f4, 0x240c0040, 0x24420001, 0x504c0003, 0x1021, 0x8ee204f4, -0x24420001, 0xaee204f4, 0x8ee204f4, 0x8e630018, 0x240c0003, 0x21080, -0x571021, 0x146c000f, 0x8c4404f8, 0x3c020001, 0x571021, 0x904283a1, -0x10400014, 0x0, 0x8ee201c8, 0x8ee35230, 0x441021, 0xaee201c8, -0x8ee201cc, 0x641821, 0x306300ff, 0x8002ec1, 0xaee35230, 0x8ee201c4, -0x8ee30e00, 0x441021, 0xaee201c4, 0x8ee201cc, 0x641821, 0x306301ff, -0xaee30e00, 0x441021, 0xaee201cc, 0x8ee20000, 0x34420040, 0xaee20000, -0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 0x8f820108, 0x27633000, -0x43102b, 0x14400002, 0x27622800, 0xaf820108, 0x8f830108, 0x8f820104, -0x1462fc2c, 0x0, 0x8fbf0060, 0x8fbe005c, 0x8fb60058, 0x8fb50054, -0x8fb40050, 0x8fb3004c, 0x8fb20048, 0x8fb10044, 0x8fb00040, 0x3e00008, -0x27bd0068, 0x52843, 0x10a0000d, 0x3021, 0x3c030001, 0x34633800, -0x3c07ffff, 0x3631021, 0x82102b, 0x50400001, 0x872021, 0x94820000, -0x24840002, 0x24a5ffff, 0x14a0fff8, 0xc23021, 0x61c02, 0x30c2ffff, -0x623021, 0x61c02, 0x30c2ffff, 0x623021, 0x3e00008, 0x30c2ffff, -0x0, 0x0, 0x27bdff88, 0x240f0001, 0xafbf0070, 0xafbe006c, +0xaee300f4, 0x8ee200f0, 0x8002e37, 0x8ee300f4, 0x8ee200f8, 0x8ee300fc, +0x24630001, 0x2c640001, 0x441021, 0xaee200f8, 0xaee300fc, 0x8ee200f8, +0x8ee300fc, 0x8ee27b98, 0x25290001, 0x122102b, 0x1440ffa0, 0x254a0008, +0xa2e07b88, 0x8002e97, 0xaee07b98, 0x8f8200f0, 0x24470008, 0x27621800, +0xe2102b, 0x50400001, 0x27671000, 0x8f8200f4, 0x14e20007, 0x0, +0x8ee201b0, 0x8021, 0x24420001, 0xaee201b0, 0x8002e55, 0x8ee201b0, +0x8f8200f0, 0x24100001, 0x8fa30018, 0x8fa4001c, 0xac430000, 0xac440004, +0xaf8700f0, 0x16000007, 0x0, 0x8ee20088, 0x24420001, 0xaee20088, +0x8ee20088, 0x8002e98, 0xaee0724c, 0x8ee2724c, 0x8ee400e0, 0x8ee500e4, +0x240c0002, 0x401821, 0x1021, 0xa32821, 0xa3302b, 0x822021, +0x862021, 0x161142, 0x30430003, 0xaee400e0, 0xaee500e4, 0x106c0017, +0x2c620003, 0x10400005, 0x240c0001, 0x106c0008, 0x0, 0x8002e98, +0xaee0724c, 0x240c0003, 0x106c0019, 0x0, 0x8002e98, 0xaee0724c, +0x8ee200e8, 0x8ee300ec, 0x24630001, 0x2c640001, 0x441021, 0xaee200e8, +0xaee300ec, 0x8ee200e8, 0x8ee300ec, 0x8002e98, 0xaee0724c, 0x8ee200f0, +0x8ee300f4, 0x24630001, 0x2c640001, 0x441021, 0xaee200f0, 0xaee300f4, +0x8ee200f0, 0x8ee300f4, 0x8002e98, 0xaee0724c, 0x8ee200f8, 0x8ee300fc, +0x24630001, 0x2c640001, 0x441021, 0xaee200f8, 0xaee300fc, 0x8ee200f8, +0x8ee300fc, 0xaee0724c, 0x8e62001c, 0x96e30458, 0x8ee404e0, 0x24420001, +0x2463ffff, 0x431024, 0x24840001, 0xaee204d4, 0xaee404e0, 0x8f42023c, +0x82202b, 0x148000a8, 0x0, 0x8f830120, 0x27623800, 0x24660020, +0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, +0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x8021, 0x24420001, +0xaee201a0, 0x8002eff, 0x8ee201a0, 0x8ee204d4, 0xac62001c, 0x8ee404a0, +0x8ee504a4, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, +0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, +0x92e24e10, 0x14400037, 0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, +0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0, 0x8ee34e20, +0x8ee24e24, 0x1062001b, 0x240c0040, 0x8c820004, 0x24420001, 0xac820004, +0x8ee24e24, 0x8ee34e20, 0x24420001, 0x104c0007, 0x0, 0x8ee24e24, +0x24420001, 0x10620005, 0x0, 0x8002ee9, 0x0, 0x14600005, +0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, +0x2c420011, 0x50400013, 0xac800000, 0x8002eff, 0x0, 0x8ee24e20, +0x240c0040, 0x24420001, 0x504c0003, 0x1021, 0x8ee24e20, 0x24420001, +0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020012, +0x240c0001, 0xac820000, 0xac8c0004, 0x5600000d, 0x24100001, 0x8ee204d4, +0x3c040001, 0x24844b14, 0xafa00014, 0xafa20010, 0x8ee605f8, 0x8f470228, +0x3c050009, 0x34a5f006, 0xc002403, 0xafab0038, 0x8fab0038, 0x16000003, +0x240c0001, 0x8002f4c, 0xa2ec04e4, 0x8ee2016c, 0x24420001, 0xaee2016c, +0x8ee2016c, 0x8ee204d4, 0xa2e004e4, 0xaee004e0, 0xaee07264, 0xaee204e8, +0x8f42023c, 0x10400030, 0x0, 0x8ee20180, 0x24420001, 0xaee20180, +0x8002f4c, 0x8ee20180, 0x8ee204f4, 0x240c0040, 0x24420001, 0x504c0003, +0x1021, 0x8ee204f4, 0x24420001, 0xaee204f4, 0x8ee204f4, 0x8e630018, +0x240c0003, 0x21080, 0x571021, 0x146c000f, 0x8c4404f8, 0x3c020001, +0x571021, 0x904283a1, 0x10400014, 0x0, 0x8ee201c8, 0x8ee35230, +0x441021, 0xaee201c8, 0x8ee201cc, 0x641821, 0x306300ff, 0x8002f47, +0xaee35230, 0x8ee201c4, 0x8ee30e00, 0x441021, 0xaee201c4, 0x8ee201cc, +0x641821, 0x306301ff, 0xaee30e00, 0x441021, 0xaee201cc, 0x8ee20000, +0x34420040, 0xaee20000, 0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, +0x8f820108, 0x27633000, 0x43102b, 0x14400002, 0x27622800, 0xaf820108, +0x8f830108, 0x8f820104, 0x1462fc26, 0x0, 0x8fbf0060, 0x8fbe005c, +0x8fb60058, 0x8fb50054, 0x8fb40050, 0x8fb3004c, 0x8fb20048, 0x8fb10044, +0x8fb00040, 0x3e00008, 0x27bd0068, 0x52843, 0x10a0000d, 0x3021, +0x3c030001, 0x34633800, 0x3c07ffff, 0x3631021, 0x82102b, 0x50400001, +0x872021, 0x94820000, 0x24840002, 0x24a5ffff, 0x14a0fff8, 0xc23021, +0x61c02, 0x30c2ffff, 0x623021, 0x61c02, 0x30c2ffff, 0x623021, +0x3e00008, 0x30c2ffff, 0x27bdff88, 0x240f0001, 0xafbf0070, 0xafbe006c, 0xafb60068, 0xafb50064, 0xafb40060, 0xafb3005c, 0xafb20058, 0xafb10054, 0xafb00050, 0xa3a00027, 0xafaf002c, 0x8ee204c4, 0x8021, 0x30420001, 0x1440002a, 0xa3a00037, 0x8f8700e0, 0x8f8800c4, 0x8f8200e8, 0xe22023, @@ -1344,30 +1366,30 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] = { 0xaee400c8, 0xaee500cc, 0x8f8300c8, 0x3c02000a, 0x3442efff, 0x1032023, 0x44102b, 0x10400003, 0x3c02000a, 0x3442f000, 0x822021, 0x801821, 0x8ee400c0, 0x8ee500c4, 0x1021, 0xa32821, 0xa3302b, 0x822021, -0x862021, 0xaee400c0, 0xaee500c4, 0xaf8800c8, 0xaf8700e4, 0x8003429, +0x862021, 0xaee400c0, 0xaee500c4, 0xaf8800c8, 0xaf8700e4, 0x80034bc, 0xaf8700e8, 0x3c020001, 0x571021, 0x904283b0, 0x1040000b, 0x0, 0x3c140001, 0x297a021, 0x8e9483b4, 0x3c130001, 0x2779821, 0x8e7383b8, -0x3c120001, 0x2579021, 0x80030ff, 0x8e5283bc, 0x8f8300e0, 0x8f8200e4, +0x3c120001, 0x2579021, 0x8003183, 0x8e5283bc, 0x8f8300e0, 0x8f8200e4, 0x10430007, 0x8821, 0x8f8200e4, 0x24110001, 0x8c430000, 0x8c440004, 0xafa30018, 0xafa4001c, 0x1620000e, 0x3c02ffff, 0x8f8200c4, 0xafa20010, -0x8f8200c8, 0x3c040001, 0x248449d0, 0xafa20014, 0x8f8600e0, 0x8f8700e4, -0x3c050006, 0xc0023a7, 0x34a5f000, 0x8003429, 0x0, 0x8fa3001c, +0x8f8200c8, 0x3c040001, 0x24844be0, 0xafa20014, 0x8f8600e0, 0x8f8700e4, +0x3c050006, 0xc002403, 0x34a5f000, 0x80034bc, 0x0, 0x8fa3001c, 0x8fb20018, 0x3074ffff, 0x2694fffc, 0x621024, 0x10400058, 0x2409821, 0x3c020080, 0x621024, 0x1040000a, 0x3c040040, 0x8ee2007c, 0x24420001, -0xaee2007c, 0x8ee2007c, 0x8ee201ec, 0x24420001, 0xaee201ec, 0x8003423, +0xaee2007c, 0x8ee2007c, 0x8ee201ec, 0x24420001, 0xaee201ec, 0x80034b6, 0x8ee201ec, 0x3c060004, 0x3c0b0001, 0x3c0a0002, 0x3c050010, 0x3c090008, 0x8ee20080, 0x3c080020, 0x34078000, 0x24420001, 0xaee20080, 0x8ee20080, 0x8fa2001c, 0x441824, 0x10660021, 0xc3102b, 0x14400007, 0x0, -0x106b0011, 0x0, 0x106a0015, 0x0, 0x8002fb5, 0x42042, +0x106b0011, 0x0, 0x106a0015, 0x0, 0x8003039, 0x42042, 0x10650023, 0xa3102b, 0x14400005, 0x0, 0x10690019, 0x0, -0x8002fb5, 0x42042, 0x10680021, 0x0, 0x8002fb5, 0x42042, -0x8ee20034, 0x24420001, 0xaee20034, 0x8ee20034, 0x8002fb5, 0x42042, -0x8ee201dc, 0x24420001, 0xaee201dc, 0x8ee201dc, 0x8002fb5, 0x42042, -0x8ee201e0, 0x24420001, 0xaee201e0, 0x8ee201e0, 0x8002fb5, 0x42042, -0x8ee201e4, 0x24420001, 0xaee201e4, 0x8ee201e4, 0x8002fb5, 0x42042, -0x8ee20030, 0x24420001, 0xaee20030, 0x8ee20030, 0x8002fb5, 0x42042, -0x8ee201e8, 0x24420001, 0xaee201e8, 0x8ee201e8, 0x42042, 0x1087046d, -0x0, 0x8002f7a, 0x0, 0x3c020001, 0x571021, 0x904283a2, +0x8003039, 0x42042, 0x10680021, 0x0, 0x8003039, 0x42042, +0x8ee20034, 0x24420001, 0xaee20034, 0x8ee20034, 0x8003039, 0x42042, +0x8ee201dc, 0x24420001, 0xaee201dc, 0x8ee201dc, 0x8003039, 0x42042, +0x8ee201e0, 0x24420001, 0xaee201e0, 0x8ee201e0, 0x8003039, 0x42042, +0x8ee201e4, 0x24420001, 0xaee201e4, 0x8ee201e4, 0x8003039, 0x42042, +0x8ee20030, 0x24420001, 0xaee20030, 0x8ee20030, 0x8003039, 0x42042, +0x8ee201e8, 0x24420001, 0xaee201e8, 0x8ee201e8, 0x42042, 0x1087047c, +0x0, 0x8002ffe, 0x0, 0x3c020001, 0x571021, 0x904283a2, 0x14400084, 0x24020001, 0x3c030001, 0x771821, 0x906383a3, 0x1462007f, 0x3c020100, 0x8e430000, 0x621024, 0x1040006f, 0x2402ffff, 0x14620005, 0x24100001, 0x96430004, 0x3402ffff, 0x10620075, 0x0, 0x92e204c8, @@ -1376,20 +1398,20 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] = { 0x2821, 0x96660000, 0x520c0, 0x971021, 0x9442776e, 0x14460009, 0x971021, 0x94437770, 0x96620002, 0x14620005, 0x971021, 0x94437772, 0x96620004, 0x50620008, 0x24070001, 0x3c020001, 0x571021, 0x8c4283a4, -0x24a50001, 0xa2102a, 0x5440ffee, 0x520c0, 0x30e200ff, 0x10400431, -0x0, 0x8003041, 0x0, 0x2402021, 0xc00229d, 0x24050006, -0x3044001f, 0x428c0, 0x2e51021, 0x9442726c, 0x30424000, 0x14400425, +0x24a50001, 0xa2102a, 0x5440ffee, 0x520c0, 0x30e200ff, 0x10400440, +0x0, 0x80030c5, 0x0, 0x2402021, 0xc0022f8, 0x24050006, +0x3044001f, 0x428c0, 0x2e51021, 0x9442726c, 0x30424000, 0x14400434, 0xb71021, 0x9443726e, 0x96620000, 0x1462000b, 0x418c0, 0xb71021, 0x94437270, 0x96620002, 0x14620006, 0x418c0, 0xb71021, 0x94437272, 0x96620004, 0x10620035, 0x418c0, 0x2e31021, 0x9442726c, 0x30428000, -0x14400412, 0x2e31021, 0x944b726c, 0x96670000, 0xb28c0, 0xb71021, -0x9442736e, 0x8003023, 0x3021, 0x420c0, 0x2e41021, 0x9443736c, +0x14400421, 0x2e31021, 0x944b726c, 0x96670000, 0xb28c0, 0xb71021, +0x9442736e, 0x80030a7, 0x3021, 0x420c0, 0x2e41021, 0x9443736c, 0x2e41021, 0x944b736c, 0x30638000, 0x14600010, 0xb28c0, 0xb71021, 0x9442736e, 0x1447fff5, 0x1602021, 0xb71021, 0x94437370, 0x96620002, 0x5462fff1, 0x420c0, 0xb71021, 0x94437372, 0x96620004, 0x5462ffec, -0x420c0, 0x24060001, 0x30c200ff, 0x104003f1, 0x0, 0x8003041, -0x0, 0x97430202, 0x96420000, 0x146203eb, 0x0, 0x97430204, -0x96420002, 0x146203e7, 0x0, 0x97430206, 0x96420004, 0x146203e3, +0x420c0, 0x24060001, 0x30c200ff, 0x10400400, 0x0, 0x80030c5, +0x0, 0x97430202, 0x96420000, 0x146203fa, 0x0, 0x97430204, +0x96420002, 0x146203f6, 0x0, 0x97430206, 0x96420004, 0x146203f2, 0x0, 0x92420000, 0x3a030001, 0x30420001, 0x431024, 0x10400074, 0x2402ffff, 0x8e630000, 0x14620004, 0x3402ffff, 0x96630004, 0x1062006f, 0x240f0002, 0x3c020001, 0x571021, 0x904283a2, 0x1440006a, 0x240f0003, @@ -1399,33 +1421,33 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] = { 0x14460009, 0x971021, 0x94437770, 0x96620002, 0x14620005, 0x971021, 0x94437772, 0x96620004, 0x50620008, 0x24070001, 0x3c020001, 0x571021, 0x8c4283a4, 0x24a50001, 0xa2102a, 0x5440ffee, 0x520c0, 0x30e200ff, -0x14400044, 0x240f0003, 0x8003423, 0x0, 0x2402021, 0xc00229d, +0x14400044, 0x240f0003, 0x80034b6, 0x0, 0x2402021, 0xc0022f8, 0x24050006, 0x3044001f, 0x428c0, 0x2e51021, 0x9442726c, 0x30424000, -0x144003a0, 0xb71021, 0x9443726e, 0x96620000, 0x1462000b, 0x418c0, +0x144003af, 0xb71021, 0x9443726e, 0x96620000, 0x1462000b, 0x418c0, 0xb71021, 0x94437270, 0x96620002, 0x14620006, 0x418c0, 0xb71021, 0x94437272, 0x96620004, 0x10620027, 0x418c0, 0x2e31021, 0x9442726c, -0x30428000, 0x1440038d, 0x2e31021, 0x944b726c, 0x96670000, 0xb28c0, -0xb71021, 0x9442736e, 0x80030a8, 0x3021, 0x420c0, 0x2e41021, +0x30428000, 0x1440039c, 0x2e31021, 0x944b726c, 0x96670000, 0xb28c0, +0xb71021, 0x9442736e, 0x800312c, 0x3021, 0x420c0, 0x2e41021, 0x9443736c, 0x2e41021, 0x944b736c, 0x30638000, 0x14600010, 0xb28c0, 0xb71021, 0x9442736e, 0x1447fff5, 0x1602021, 0xb71021, 0x94437370, 0x96620002, 0x5462fff1, 0x420c0, 0xb71021, 0x94437372, 0x96620004, -0x5462ffec, 0x420c0, 0x24060001, 0x30c200ff, 0x1040036c, 0x0, -0x80030bb, 0x240f0003, 0x240f0001, 0xafaf002c, 0x8f420260, 0x54102b, +0x5462ffec, 0x420c0, 0x24060001, 0x30c200ff, 0x1040037b, 0x0, +0x800313f, 0x240f0003, 0x240f0001, 0xafaf002c, 0x8f420260, 0x54102b, 0x1040003a, 0x0, 0x8f8300e4, 0x8f8200e0, 0x10620003, 0x24630008, 0xaf8300e4, 0xaf8300e8, 0x8ee400c0, 0x8ee500c4, 0x2801821, 0x1021, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xaee400c0, 0xaee500c4, 0x8ee20058, 0x24420001, 0xaee20058, 0x8ee20058, 0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x8f8200e0, 0xafa20010, 0x8f8200e4, 0x3c040001, -0x248449d8, 0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050006, 0xc0023a7, -0x34a5f003, 0x8003429, 0x0, 0x8ee25230, 0xafa20010, 0x8ee25234, -0x3c040001, 0x248449e4, 0xafa20014, 0x8ee60e00, 0x8ee70e08, 0x3c050006, -0xc0023a7, 0x34a5f002, 0x8ee201bc, 0x24420001, 0xaee201bc, 0x8ee20000, -0x8ee301bc, 0x2403ffbf, 0x431024, 0x80033cd, 0xaee20000, 0x96e20468, -0x54102b, 0x10400003, 0x0, 0x240f0001, 0xa3af0027, 0x128002f2, +0x24844be8, 0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050006, 0xc002403, +0x34a5f003, 0x80034bc, 0x0, 0x8ee25230, 0xafa20010, 0x8ee25234, +0x3c040001, 0x24844bf4, 0xafa20014, 0x8ee60e00, 0x8ee70e08, 0x3c050006, +0xc002403, 0x34a5f002, 0x8ee201bc, 0x24420001, 0xaee201bc, 0x8ee20000, +0x8ee301bc, 0x2403ffbf, 0x431024, 0x8003460, 0xaee20000, 0x96e20468, +0x54102b, 0x10400003, 0x0, 0x240f0001, 0xa3af0027, 0x12800301, 0x24160007, 0x24150040, 0x241e0001, 0x240e0012, 0x8ee2723c, 0x8f430280, -0x24420001, 0x304203ff, 0x106202c4, 0x0, 0x93a20027, 0x10400014, +0x24420001, 0x304203ff, 0x106202d3, 0x0, 0x93a20027, 0x10400014, 0x0, 0x8ee35230, 0x8ee25234, 0x10620009, 0x26ed5234, 0x8ee65234, -0x8ee35234, 0x21140, 0x24425238, 0x2e28021, 0x24630001, 0x800312b, +0x8ee35234, 0x21140, 0x24425238, 0x2e28021, 0x24630001, 0x80031af, 0x306b00ff, 0x92e27238, 0x1440ffca, 0x0, 0x8ee201d0, 0x24420001, 0xaee201d0, 0x8ee201d0, 0x8ee30e00, 0x8ee20e08, 0x1062ffc2, 0x26ed0e08, 0x8ee60e08, 0x8ee30e08, 0x21140, 0x24420e10, 0x2e28021, 0x24630001, @@ -1439,307 +1461,310 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] = { 0x439823, 0x26820007, 0x2404fff8, 0x9603000a, 0x446024, 0x6a1821, 0x6c102b, 0x10400002, 0x1803821, 0x603821, 0xae130018, 0x8f880120, 0x24e20007, 0x443824, 0x27623800, 0x25090020, 0x122102b, 0x50400001, -0x27693000, 0x8f820128, 0x15220007, 0x1401821, 0x8ee201a0, 0x8821, -0x24420001, 0xaee201a0, 0x80031b5, 0x8ee201a0, 0x8e040000, 0x8e050004, -0x1021, 0xad130008, 0xa507000e, 0xad160018, 0xad06001c, 0xa3302b, -0xa32823, 0x822023, 0x862023, 0xad040000, 0xad050004, 0x8ee204b0, -0xad020010, 0xaf890120, 0x92e24e10, 0x14400033, 0x24110001, 0x8ee24e20, -0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x1456001f, 0x0, -0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001, -0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10550007, 0x0, -0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x80031a2, 0x0, -0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, -0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x80031b5, 0x0, -0x8ee24e20, 0x24420001, 0x50550003, 0x1021, 0x8ee24e20, 0x24420001, -0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0xac960000, -0xac9e0004, 0x16200018, 0x3c050006, 0x8e020018, 0x3c040001, 0x248449f0, -0xafa20010, 0x8e020000, 0x8e030004, 0x34a5f009, 0x2003021, 0xc0023a7, -0xafa30014, 0x93a20037, 0x1040020a, 0x340f8100, 0x8e420004, 0x8e430008, -0x8e44000c, 0xa64f000c, 0xae420000, 0xae430004, 0xae440008, 0x96020016, -0x80033cd, 0xa642000e, 0x14ec015f, 0x28a1823, 0x960c000a, 0x9603000e, -0x28a1023, 0xa602000a, 0x34620004, 0xa602000e, 0x8f880120, 0x27623800, -0x25090020, 0x122102b, 0x14400002, 0x306affff, 0x27693000, 0x8f820128, -0x15220007, 0x24040020, 0x8ee201a0, 0x8821, 0x24420001, 0xaee201a0, -0x8003230, 0x8ee201a0, 0x8ee5723c, 0x8ee60480, 0x8ee70484, 0xa504000e, -0x24040004, 0xad100008, 0xad040018, 0x52940, 0xa01821, 0x1021, -0xe33821, 0xe3202b, 0xc23021, 0xc43021, 0xad060000, 0xad070004, -0x8ee2723c, 0xad02001c, 0x8ee204b4, 0xad020010, 0xaf890120, 0x92e24e10, +0x27693000, 0x8f820128, 0x11220004, 0x0, 0x8f820124, 0x15220007, +0x1401821, 0x8ee201a0, 0x8821, 0x24420001, 0xaee201a0, 0x800323c, +0x8ee201a0, 0x8e040000, 0x8e050004, 0x1021, 0xad130008, 0xa507000e, +0xad160018, 0xad06001c, 0xa3302b, 0xa32823, 0x822023, 0x862023, +0xad040000, 0xad050004, 0x8ee204b0, 0xad020010, 0xaf890120, 0x92e24e10, 0x14400033, 0x24110001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x1456001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10550007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, -0x0, 0x800321d, 0x0, 0x14600005, 0x0, 0x8f820128, +0x0, 0x8003229, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, -0xac800000, 0x8003230, 0x0, 0x8ee24e20, 0x24420001, 0x50550003, +0xac800000, 0x800323c, 0x0, 0x8ee24e20, 0x24420001, 0x50550003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, -0x24425028, 0x2e22021, 0xac960000, 0xac9e0004, 0x1620000d, 0x0, -0xa60c000a, 0xa60a000e, 0x8f820100, 0xafa20010, 0x8f820104, 0x3c040001, -0x248449fc, 0x3c050006, 0xafa20014, 0x8ee6723c, 0x8003398, 0x34a5f00b, -0x3c010001, 0x370821, 0xa02083b0, 0xadab0000, 0x8ee201cc, 0x8ee3723c, -0x2442ffff, 0xaee201cc, 0x8ee201cc, 0x24630001, 0x306303ff, 0x26e25234, -0x15a20006, 0xaee3723c, 0x8ee201c8, 0x2442ffff, 0xaee201c8, 0x8003255, -0x8ee201c8, 0x8ee201c4, 0x2442ffff, 0xaee201c4, 0x8ee201c4, 0x8f420240, -0x10400070, 0x0, 0x8ee20e0c, 0x24420001, 0xaee20e0c, 0x8f430240, -0x43102b, 0x1440016d, 0xa021, 0x8f830120, 0x27623800, 0x24660020, -0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 0x0, -0x8ee201a0, 0x8821, 0x24420001, 0xaee201a0, 0x80032b2, 0x8ee201a0, -0x8ee2723c, 0xac62001c, 0x8ee40498, 0x8ee5049c, 0x2462001c, 0xac620008, -0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004, -0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400033, 0x24110001, -0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x144e001f, -0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, -0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10550007, -0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x800329f, -0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, -0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x80032b2, -0x0, 0x8ee24e20, 0x24420001, 0x50550003, 0x1021, 0x8ee24e20, -0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, -0xac8e0000, 0xac9e0004, 0x5620000d, 0x24110001, 0x8ee2723c, 0x3c040001, -0x24844a08, 0xafa00014, 0xafa20010, 0x8ee6723c, 0x8f470280, 0x3c050009, -0x34a5f008, 0xc0023a7, 0xafae0048, 0x8fae0048, 0x56200001, 0xaee00e0c, -0x8ee20184, 0x24420001, 0xaee20184, 0x8003328, 0x8ee20184, 0x8f830120, -0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, -0x14c20007, 0x0, 0x8ee201a0, 0x8821, 0x24420001, 0xaee201a0, -0x800331a, 0x8ee201a0, 0x8ee2723c, 0xac62001c, 0x8ee40498, 0x8ee5049c, -0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, 0xac620018, -0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, -0x14400033, 0x24110001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, -0x8c820000, 0x144e001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, -0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, -0x24420001, 0x10550007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, -0x0, 0x8003307, 0x0, 0x14600005, 0x0, 0x8f820128, -0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, -0xac800000, 0x800331a, 0x0, 0x8ee24e20, 0x24420001, 0x50550003, -0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, -0x24425028, 0x2e22021, 0xac8e0000, 0xac9e0004, 0x1620000d, 0x0, -0x8ee2723c, 0x3c040001, 0x24844a08, 0xafa00014, 0xafa20010, 0x8ee6723c, -0x8f470280, 0x3c050009, 0x34a5f008, 0xc0023a7, 0xafae0048, 0x8fae0048, -0x8ee20170, 0x24420001, 0xaee20170, 0x8ee20170, 0x80033cb, 0xa021, -0x960c000a, 0x183102b, 0x54400001, 0x1801821, 0xa603000a, 0x8f880120, -0x27623800, 0x25090020, 0x122102b, 0x50400001, 0x27693000, 0x8f820128, +0x24425028, 0x2e22021, 0xac960000, 0xac9e0004, 0x16200018, 0x3c050006, +0x8e020018, 0x3c040001, 0x24844c00, 0xafa20010, 0x8e020000, 0x8e030004, +0x34a5f009, 0x2003021, 0xc002403, 0xafa30014, 0x93a20037, 0x10400216, +0x340f8100, 0x8e420004, 0x8e430008, 0x8e44000c, 0xa64f000c, 0xae420000, +0xae430004, 0xae440008, 0x96020016, 0x8003460, 0xa642000e, 0x14ec0168, +0x28a1823, 0x960c000a, 0x9603000e, 0x28a1023, 0xa602000a, 0x34620004, +0xa602000e, 0x8f880120, 0x27623800, 0x25090020, 0x122102b, 0x14400002, +0x306affff, 0x27693000, 0x8f820128, 0x11220004, 0x0, 0x8f820124, 0x15220007, 0x24040020, 0x8ee201a0, 0x8821, 0x24420001, 0xaee201a0, -0x800338c, 0x8ee201a0, 0x8ee5723c, 0x8ee60480, 0x8ee70484, 0xa504000e, +0x80032ba, 0x8ee201a0, 0x8ee5723c, 0x8ee60480, 0x8ee70484, 0xa504000e, 0x24040004, 0xad100008, 0xad040018, 0x52940, 0xa01821, 0x1021, 0xe33821, 0xe3202b, 0xc23021, 0xc43021, 0xad060000, 0xad070004, 0x8ee2723c, 0xad02001c, 0x8ee204b4, 0xad020010, 0xaf890120, 0x92e24e10, -0x14400033, 0x24110001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, -0x8c820000, 0x1456001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, -0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, -0x24420001, 0x10550007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, -0x0, 0x8003379, 0x0, 0x14600005, 0x0, 0x8f820128, -0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, -0xac800000, 0x800338c, 0x0, 0x8ee24e20, 0x24420001, 0x50550003, -0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, -0x24425028, 0x2e22021, 0xac960000, 0xac9e0004, 0x1620001d, 0x0, -0xa60c000a, 0x8f820100, 0xafa20010, 0x8f820104, 0x3c040001, 0x248449fc, -0x3c050006, 0xafa20014, 0x8ee6723c, 0x34a5f00d, 0xc0023a7, 0x2003821, -0x93a20037, 0x10400031, 0x340f8100, 0x8e420004, 0x8e430008, 0x8e44000c, -0xa64f000c, 0xae420000, 0xae430004, 0xae440008, 0x96020016, 0xa642000e, -0x9602000e, 0x3042fdff, 0x80033cd, 0xa602000e, 0x8ee201cc, 0x2442ffff, -0xaee201cc, 0x8ee201cc, 0x8ee201c4, 0x3c04001f, 0x3c010001, 0x370821, -0xa03e83b0, 0x2442ffff, 0xaee201c4, 0x9603000a, 0x3484ffff, 0x8ee201c4, -0x6a1821, 0x2639821, 0x93202b, 0x10800003, 0x3c02fff5, 0x34421000, -0x2629821, 0xadab0000, 0x8ee2723c, 0x24420001, 0x304203ff, 0xaee2723c, -0x8f420240, 0x10400004, 0x283a023, 0x8ee20e0c, 0x24420001, 0xaee20e0c, -0xa3a00027, 0x1680fd38, 0x0, 0x12800024, 0x0, 0x3c010001, -0x370821, 0xac3483b4, 0x3c010001, 0x370821, 0xac3383b8, 0x3c010001, -0x370821, 0xac3283bc, 0x93a20037, 0x10400008, 0x0, 0x3c020001, -0x571021, 0x8c4283bc, 0x24420004, 0x3c010001, 0x370821, 0xac2283bc, -0x8ee2723c, 0x8f430280, 0x24420001, 0x304203ff, 0x14620006, 0x0, -0x8ee201c0, 0x24420001, 0xaee201c0, 0x8003429, 0x8ee201c0, 0x8ee201b8, -0x24420001, 0xaee201b8, 0x8003429, 0x8ee201b8, 0x97a4001e, 0x2484fffc, -0x801821, 0x8ee400c0, 0x8ee500c4, 0x1021, 0xa32821, 0xa3302b, -0x822021, 0x862021, 0xaee400c0, 0xaee500c4, 0x8faf002c, 0x24020002, -0x11e2000f, 0x29e20003, 0x14400017, 0x24020003, 0x15e20015, 0x0, -0x8ee200d0, 0x8ee300d4, 0x24630001, 0x2c640001, 0x441021, 0xaee200d0, -0xaee300d4, 0x8ee200d0, 0x8003423, 0x8ee300d4, 0x8ee200d8, 0x8ee300dc, -0x24630001, 0x2c640001, 0x441021, 0xaee200d8, 0xaee300dc, 0x8ee200d8, -0x8003423, 0x8ee300dc, 0x8ee200c8, 0x8ee300cc, 0x24630001, 0x2c640001, -0x441021, 0xaee200c8, 0xaee300cc, 0x8ee200c8, 0x8ee300cc, 0x8f8300e4, -0x8f8200e0, 0x10620003, 0x24630008, 0xaf8300e4, 0xaf8300e8, 0x8fbf0070, -0x8fbe006c, 0x8fb60068, 0x8fb50064, 0x8fb40060, 0x8fb3005c, 0x8fb20058, -0x8fb10054, 0x8fb00050, 0x3e00008, 0x27bd0078, 0x27bdffb0, 0xafb50044, -0xa821, 0xafb00030, 0x8021, 0xafbf004c, 0xafb60048, 0xafb40040, -0xafb3003c, 0xafb20038, 0xafb10034, 0x8ee204c4, 0x24140001, 0x30420001, -0x1440002a, 0xb021, 0x8f8700e0, 0x8f8800c4, 0x8f8200e8, 0xe22023, -0x2c821000, 0x50400001, 0x24841000, 0x420c2, 0x801821, 0x8ee400c8, -0x8ee500cc, 0x1021, 0xa32821, 0xa3302b, 0x822021, 0x862021, -0xaee400c8, 0xaee500cc, 0x8f8300c8, 0x3c02000a, 0x3442efff, 0x1032023, -0x44102b, 0x10400003, 0x3c02000a, 0x3442f000, 0x822021, 0x801821, -0x8ee400c0, 0x8ee500c4, 0x1021, 0xa32821, 0xa3302b, 0x822021, -0x862021, 0xaee400c0, 0xaee500c4, 0xaf8800c8, 0xaf8700e4, 0x80037aa, -0xaf8700e8, 0x3c020001, 0x571021, 0x904283b0, 0x1040000b, 0x0, -0x3c130001, 0x2779821, 0x8e7383b4, 0x3c110001, 0x2378821, 0x8e3183b8, -0x3c120001, 0x2579021, 0x8003645, 0x8e5283bc, 0x8f8300e0, 0x8f8200e4, -0x10430007, 0x4821, 0x8f8200e4, 0x24090001, 0x8c430000, 0x8c440004, -0xafa30018, 0xafa4001c, 0x1520000e, 0x3c02ffff, 0x8f8200c4, 0xafa20010, -0x8f8200c8, 0x3c040001, 0x248449d0, 0xafa20014, 0x8f8600e0, 0x8f8700e4, -0x3c050006, 0xc0023a7, 0x34a5f000, 0x80037aa, 0x0, 0x8fa3001c, -0x8fb20018, 0x3073ffff, 0x2673fffc, 0x621024, 0x10400058, 0x2408821, -0x3c020080, 0x621024, 0x1040000a, 0x3c040040, 0x8ee2007c, 0x24420001, -0xaee2007c, 0x8ee2007c, 0x8ee201ec, 0x24420001, 0xaee201ec, 0x80037a4, -0x8ee201ec, 0x3c060004, 0x3c0b0001, 0x3c0a0002, 0x3c050010, 0x3c090008, -0x8ee20080, 0x3c080020, 0x34078000, 0x24420001, 0xaee20080, 0x8ee20080, -0x8fa2001c, 0x441824, 0x10660021, 0xc3102b, 0x14400007, 0x0, -0x106b0011, 0x0, 0x106a0015, 0x0, 0x80034ef, 0x42042, -0x10650023, 0xa3102b, 0x14400005, 0x0, 0x10690019, 0x0, -0x80034ef, 0x42042, 0x10680021, 0x0, 0x80034ef, 0x42042, -0x8ee20034, 0x24420001, 0xaee20034, 0x8ee20034, 0x80034ef, 0x42042, -0x8ee201dc, 0x24420001, 0xaee201dc, 0x8ee201dc, 0x80034ef, 0x42042, -0x8ee201e0, 0x24420001, 0xaee201e0, 0x8ee201e0, 0x80034ef, 0x42042, -0x8ee201e4, 0x24420001, 0xaee201e4, 0x8ee201e4, 0x80034ef, 0x42042, -0x8ee20030, 0x24420001, 0xaee20030, 0x8ee20030, 0x80034ef, 0x42042, -0x8ee201e8, 0x24420001, 0xaee201e8, 0x8ee201e8, 0x42042, 0x108702b4, -0x0, 0x80034b4, 0x0, 0x3c020001, 0x571021, 0x904283a2, -0x14400084, 0x24020001, 0x3c030001, 0x771821, 0x906383a3, 0x1462007f, -0x3c020100, 0x8e430000, 0x621024, 0x1040006f, 0x2402ffff, 0x14620005, -0x24100001, 0x96430004, 0x3402ffff, 0x10620075, 0x0, 0x92e204c8, -0x14400072, 0x0, 0x3c020001, 0x571021, 0x8c4283a4, 0x28420005, -0x10400020, 0x3821, 0x3c020001, 0x571021, 0x8c4283a4, 0x18400016, -0x2821, 0x96260000, 0x520c0, 0x971021, 0x9442776e, 0x14460009, -0x971021, 0x94437770, 0x96220002, 0x14620005, 0x971021, 0x94437772, -0x96220004, 0x50620008, 0x24070001, 0x3c020001, 0x571021, 0x8c4283a4, -0x24a50001, 0xa2102a, 0x5440ffee, 0x520c0, 0x30e200ff, 0x10400278, -0x0, 0x800357b, 0x0, 0x2402021, 0xc00229d, 0x24050006, -0x3044001f, 0x428c0, 0x2e51021, 0x9442726c, 0x30424000, 0x1440026c, -0xb71021, 0x9443726e, 0x96220000, 0x1462000b, 0x418c0, 0xb71021, -0x94437270, 0x96220002, 0x14620006, 0x418c0, 0xb71021, 0x94437272, -0x96220004, 0x10620035, 0x418c0, 0x2e31021, 0x9442726c, 0x30428000, -0x14400259, 0x2e31021, 0x9448726c, 0x96270000, 0x828c0, 0xb71021, -0x9442736e, 0x800355d, 0x3021, 0x420c0, 0x2e41021, 0x9443736c, -0x2e41021, 0x9448736c, 0x30638000, 0x14600010, 0x828c0, 0xb71021, -0x9442736e, 0x1447fff5, 0x1002021, 0xb71021, 0x94437370, 0x96220002, -0x5462fff1, 0x420c0, 0xb71021, 0x94437372, 0x96220004, 0x5462ffec, -0x420c0, 0x24060001, 0x30c200ff, 0x10400238, 0x0, 0x800357b, -0x0, 0x97430202, 0x96420000, 0x14620232, 0x0, 0x97430204, -0x96420002, 0x1462022e, 0x0, 0x97430206, 0x96420004, 0x1462022a, -0x0, 0x92420000, 0x3a030001, 0x30420001, 0x431024, 0x10400074, -0x2402ffff, 0x8e230000, 0x14620004, 0x3402ffff, 0x96230004, 0x1062006f, -0x24140002, 0x3c020001, 0x571021, 0x904283a2, 0x1440006a, 0x24140003, -0x92e204c8, 0x14400067, 0x0, 0x3c020001, 0x571021, 0x8c4283a4, -0x28420005, 0x10400020, 0x3821, 0x3c020001, 0x571021, 0x8c4283a4, -0x18400016, 0x2821, 0x96260000, 0x520c0, 0x971021, 0x9442776e, -0x14460009, 0x971021, 0x94437770, 0x96220002, 0x14620005, 0x971021, -0x94437772, 0x96220004, 0x50620008, 0x24070001, 0x3c020001, 0x571021, -0x8c4283a4, 0x24a50001, 0xa2102a, 0x5440ffee, 0x520c0, 0x30e200ff, -0x14400044, 0x24140003, 0x80037a4, 0x0, 0x2402021, 0xc00229d, -0x24050006, 0x3044001f, 0x428c0, 0x2e51021, 0x9442726c, 0x30424000, -0x144001e7, 0xb71021, 0x9443726e, 0x96220000, 0x1462000b, 0x418c0, -0xb71021, 0x94437270, 0x96220002, 0x14620006, 0x418c0, 0xb71021, -0x94437272, 0x96220004, 0x10620027, 0x418c0, 0x2e31021, 0x9442726c, -0x30428000, 0x144001d4, 0x2e31021, 0x9448726c, 0x96270000, 0x828c0, -0xb71021, 0x9442736e, 0x80035e2, 0x3021, 0x420c0, 0x2e41021, -0x9443736c, 0x2e41021, 0x9448736c, 0x30638000, 0x14600010, 0x828c0, -0xb71021, 0x9442736e, 0x1447fff5, 0x1002021, 0xb71021, 0x94437370, -0x96220002, 0x5462fff1, 0x420c0, 0xb71021, 0x94437372, 0x96220004, -0x5462ffec, 0x420c0, 0x24060001, 0x30c200ff, 0x104001b3, 0x0, -0x80035f5, 0x24140003, 0x24140001, 0x8f420260, 0x53102b, 0x10400049, -0x0, 0x8f8300e4, 0x8f8200e0, 0x10620003, 0x24630008, 0xaf8300e4, -0xaf8300e8, 0x8ee400c0, 0x8ee500c4, 0x2601821, 0x1021, 0xa32821, -0xa3302b, 0x822021, 0x862021, 0xaee400c0, 0xaee500c4, 0x8ee20058, -0x24420001, 0xaee20058, 0x8ee20058, 0x8ee2007c, 0x24420001, 0xaee2007c, -0x8ee2007c, 0x8f8200e0, 0xafa20010, 0x8f8200e4, 0x3c040001, 0x248449d8, -0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050006, 0xc0023a7, 0x34a5f003, -0x80037aa, 0x0, 0x8ee25230, 0xafa20010, 0x8ee25234, 0x3c040001, -0x248449e4, 0xafa20014, 0x8ee60e00, 0x8ee70e08, 0xc0023a7, 0x34a5f002, -0x8ee201bc, 0x24420001, 0xaee201bc, 0x8ee20000, 0x8ee301bc, 0x2403ffbf, -0x431024, 0x8003752, 0xaee20000, 0x8ee25230, 0xafa20010, 0x8ee25234, -0x3c040001, 0x248449e4, 0xafa20014, 0x8ee60e00, 0x8ee70e08, 0x3c050006, -0xc0023a7, 0x34a5f002, 0x8ee201bc, 0x24420001, 0xaee201bc, 0x8003752, -0x8ee201bc, 0x96e20468, 0x53102b, 0x54400001, 0x3c158000, 0x1260012e, -0x3c0c001f, 0x358cffff, 0x8ee2723c, 0x8f430280, 0x24420001, 0x304203ff, -0x10620105, 0x0, 0x12a00014, 0x0, 0x8ee35230, 0x8ee25234, -0x10620009, 0x26ee5234, 0x8eeb5234, 0x8ee35234, 0x21140, 0x24425238, -0x2e28021, 0x24630001, 0x800366f, 0x306800ff, 0x92e27238, 0x1440ffc0, -0x3c050006, 0x8ee201d0, 0x24420001, 0xaee201d0, 0x8ee201d0, 0x8ee30e00, -0x8ee20e08, 0x1062ffcb, 0x26ee0e08, 0x8eeb0e08, 0xa821, 0x8ee30e08, -0x21140, 0x24420e10, 0x2e28021, 0x24630001, 0x306801ff, 0x96e2046a, -0x30420010, 0x10400017, 0x34028100, 0x9643000c, 0x14620014, 0x0, -0x3c020001, 0x571021, 0x904283b0, 0x1440000f, 0x0, 0x9642000e, -0xa6020016, 0x8e420008, 0x8e430004, 0x8e440000, 0x2673fffc, 0xae42000c, -0xae430008, 0xae440004, 0x9602000e, 0x26310004, 0x24160001, 0x34420200, -0xa602000e, 0x9603000a, 0x2605021, 0x73102b, 0x10400002, 0x2606821, -0x605021, 0x2d42003d, 0x1040002a, 0x3821, 0x9623000c, 0x24020800, -0x54620027, 0xae110018, 0x3c020001, 0x571021, 0x904283b0, 0x54400022, -0xae110018, 0x26220017, 0x182102b, 0x10400013, 0x0, 0x3c02fff5, -0x511021, 0x90421017, 0x38430006, 0x2c630001, 0x38420011, 0x2c420001, -0x621825, 0x10600013, 0x26220010, 0x182102b, 0x1040000e, 0x0, -0x3c07fff5, 0xf13821, 0x94e71010, 0x80036bb, 0x24e7000e, 0x92220017, -0x38430006, 0x2c630001, 0x38420011, 0x2c420001, 0x621825, 0x50600004, -0xae110018, 0x96270010, 0x24e7000e, 0xae110018, 0x3c020001, 0x571021, -0x904283b0, 0x2102b, 0x14e00002, 0x24ec0, 0x1403821, 0x8f830120, -0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, +0x14400033, 0x24110001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, +0x8c820000, 0x1456001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, +0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, +0x24420001, 0x10550007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, +0x0, 0x80032a7, 0x0, 0x14600005, 0x0, 0x8f820128, +0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, +0xac800000, 0x80032ba, 0x0, 0x8ee24e20, 0x24420001, 0x50550003, +0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, +0x24425028, 0x2e22021, 0xac960000, 0xac9e0004, 0x1620000d, 0x0, +0xa60c000a, 0xa60a000e, 0x8f820100, 0xafa20010, 0x8f820104, 0x3c040001, +0x24844c0c, 0x3c050006, 0xafa20014, 0x8ee6723c, 0x800342b, 0x34a5f00b, +0x3c010001, 0x370821, 0xa02083b0, 0xadab0000, 0x8ee201cc, 0x8ee3723c, +0x2442ffff, 0xaee201cc, 0x8ee201cc, 0x24630001, 0x306303ff, 0x26e25234, +0x15a20006, 0xaee3723c, 0x8ee201c8, 0x2442ffff, 0xaee201c8, 0x80032df, +0x8ee201c8, 0x8ee201c4, 0x2442ffff, 0xaee201c4, 0x8ee201c4, 0x8f420240, +0x10400073, 0x0, 0x8ee20e0c, 0x24420001, 0xaee20e0c, 0x8f430240, +0x43102b, 0x14400176, 0xa021, 0x8f830120, 0x27623800, 0x24660020, +0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, +0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x8821, 0x24420001, +0xaee201a0, 0x800333f, 0x8ee201a0, 0x8ee2723c, 0xac62001c, 0x8ee40498, +0x8ee5049c, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, +0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, +0x92e24e10, 0x14400033, 0x24110001, 0x8ee24e20, 0x210c0, 0x24425028, +0x2e22021, 0x8c820000, 0x144e001f, 0x0, 0x8ee34e20, 0x8ee24e24, +0x1062001b, 0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, +0x8ee34e20, 0x24420001, 0x10550007, 0x0, 0x8ee24e24, 0x24420001, +0x10620005, 0x0, 0x800332c, 0x0, 0x14600005, 0x0, +0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, +0x50400010, 0xac800000, 0x800333f, 0x0, 0x8ee24e20, 0x24420001, +0x50550003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, +0x210c0, 0x24425028, 0x2e22021, 0xac8e0000, 0xac9e0004, 0x5620000d, +0x24110001, 0x8ee2723c, 0x3c040001, 0x24844c18, 0xafa00014, 0xafa20010, +0x8ee6723c, 0x8f470280, 0x3c050009, 0x34a5f008, 0xc002403, 0xafae0048, +0x8fae0048, 0x56200001, 0xaee00e0c, 0x8ee20184, 0x24420001, 0xaee20184, +0x80033b8, 0x8ee20184, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, +0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124, +0x14c20007, 0x0, 0x8ee201a0, 0x8821, 0x24420001, 0xaee201a0, +0x80033aa, 0x8ee201a0, 0x8ee2723c, 0xac62001c, 0x8ee40498, 0x8ee5049c, +0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, 0xac620018, +0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, +0x14400033, 0x24110001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, +0x8c820000, 0x144e001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, +0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, +0x24420001, 0x10550007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, +0x0, 0x8003397, 0x0, 0x14600005, 0x0, 0x8f820128, +0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, +0xac800000, 0x80033aa, 0x0, 0x8ee24e20, 0x24420001, 0x50550003, +0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, +0x24425028, 0x2e22021, 0xac8e0000, 0xac9e0004, 0x1620000d, 0x0, +0x8ee2723c, 0x3c040001, 0x24844c18, 0xafa00014, 0xafa20010, 0x8ee6723c, +0x8f470280, 0x3c050009, 0x34a5f008, 0xc002403, 0xafae0048, 0x8fae0048, +0x8ee20170, 0x24420001, 0xaee20170, 0x8ee20170, 0x800345e, 0xa021, +0x960c000a, 0x183102b, 0x54400001, 0x1801821, 0xa603000a, 0x8f880120, +0x27623800, 0x25090020, 0x122102b, 0x50400001, 0x27693000, 0x8f820128, +0x11220004, 0x0, 0x8f820124, 0x15220007, 0x24040020, 0x8ee201a0, +0x8821, 0x24420001, 0xaee201a0, 0x800341f, 0x8ee201a0, 0x8ee5723c, +0x8ee60480, 0x8ee70484, 0xa504000e, 0x24040004, 0xad100008, 0xad040018, +0x52940, 0xa01821, 0x1021, 0xe33821, 0xe3202b, 0xc23021, +0xc43021, 0xad060000, 0xad070004, 0x8ee2723c, 0xad02001c, 0x8ee204b4, +0xad020010, 0xaf890120, 0x92e24e10, 0x14400033, 0x24110001, 0x8ee24e20, +0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x1456001f, 0x0, +0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001, +0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10550007, 0x0, +0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x800340c, 0x0, +0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, +0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x800341f, 0x0, +0x8ee24e20, 0x24420001, 0x50550003, 0x1021, 0x8ee24e20, 0x24420001, +0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0xac960000, +0xac9e0004, 0x1620001d, 0x0, 0xa60c000a, 0x8f820100, 0xafa20010, +0x8f820104, 0x3c040001, 0x24844c0c, 0x3c050006, 0xafa20014, 0x8ee6723c, +0x34a5f00d, 0xc002403, 0x2003821, 0x93a20037, 0x10400031, 0x340f8100, +0x8e420004, 0x8e430008, 0x8e44000c, 0xa64f000c, 0xae420000, 0xae430004, +0xae440008, 0x96020016, 0xa642000e, 0x9602000e, 0x3042fdff, 0x8003460, +0xa602000e, 0x8ee201cc, 0x2442ffff, 0xaee201cc, 0x8ee201cc, 0x8ee201c4, +0x3c04001f, 0x3c010001, 0x370821, 0xa03e83b0, 0x2442ffff, 0xaee201c4, +0x9603000a, 0x3484ffff, 0x8ee201c4, 0x6a1821, 0x2639821, 0x93202b, +0x10800003, 0x3c02fff5, 0x34421000, 0x2629821, 0xadab0000, 0x8ee2723c, +0x24420001, 0x304203ff, 0xaee2723c, 0x8f420240, 0x10400004, 0x283a023, +0x8ee20e0c, 0x24420001, 0xaee20e0c, 0xa3a00027, 0x1680fd29, 0x0, +0x12800024, 0x0, 0x3c010001, 0x370821, 0xac3483b4, 0x3c010001, +0x370821, 0xac3383b8, 0x3c010001, 0x370821, 0xac3283bc, 0x93a20037, +0x10400008, 0x0, 0x3c020001, 0x571021, 0x8c4283bc, 0x24420004, +0x3c010001, 0x370821, 0xac2283bc, 0x8ee2723c, 0x8f430280, 0x24420001, +0x304203ff, 0x14620006, 0x0, 0x8ee201c0, 0x24420001, 0xaee201c0, +0x80034bc, 0x8ee201c0, 0x8ee201b8, 0x24420001, 0xaee201b8, 0x80034bc, +0x8ee201b8, 0x97a4001e, 0x2484fffc, 0x801821, 0x8ee400c0, 0x8ee500c4, +0x1021, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xaee400c0, +0xaee500c4, 0x8faf002c, 0x24020002, 0x11e2000f, 0x29e20003, 0x14400017, +0x24020003, 0x15e20015, 0x0, 0x8ee200d0, 0x8ee300d4, 0x24630001, +0x2c640001, 0x441021, 0xaee200d0, 0xaee300d4, 0x8ee200d0, 0x80034b6, +0x8ee300d4, 0x8ee200d8, 0x8ee300dc, 0x24630001, 0x2c640001, 0x441021, +0xaee200d8, 0xaee300dc, 0x8ee200d8, 0x80034b6, 0x8ee300dc, 0x8ee200c8, +0x8ee300cc, 0x24630001, 0x2c640001, 0x441021, 0xaee200c8, 0xaee300cc, +0x8ee200c8, 0x8ee300cc, 0x8f8300e4, 0x8f8200e0, 0x10620003, 0x24630008, +0xaf8300e4, 0xaf8300e8, 0x8fbf0070, 0x8fbe006c, 0x8fb60068, 0x8fb50064, +0x8fb40060, 0x8fb3005c, 0x8fb20058, 0x8fb10054, 0x8fb00050, 0x3e00008, +0x27bd0078, 0x27bdffb0, 0xafb50044, 0xa821, 0xafb00030, 0x8021, +0xafbf004c, 0xafb60048, 0xafb40040, 0xafb3003c, 0xafb20038, 0xafb10034, +0x8ee204c4, 0x24140001, 0x30420001, 0x1440002a, 0xb021, 0x8f8700e0, +0x8f8800c4, 0x8f8200e8, 0xe22023, 0x2c821000, 0x50400001, 0x24841000, +0x420c2, 0x801821, 0x8ee400c8, 0x8ee500cc, 0x1021, 0xa32821, +0xa3302b, 0x822021, 0x862021, 0xaee400c8, 0xaee500cc, 0x8f8300c8, +0x3c02000a, 0x3442efff, 0x1032023, 0x44102b, 0x10400003, 0x3c02000a, +0x3442f000, 0x822021, 0x801821, 0x8ee400c0, 0x8ee500c4, 0x1021, +0xa32821, 0xa3302b, 0x822021, 0x862021, 0xaee400c0, 0xaee500c4, +0xaf8800c8, 0xaf8700e4, 0x8003840, 0xaf8700e8, 0x3c020001, 0x571021, +0x904283b0, 0x1040000b, 0x0, 0x3c130001, 0x2779821, 0x8e7383b4, +0x3c110001, 0x2378821, 0x8e3183b8, 0x3c120001, 0x2579021, 0x80036d8, +0x8e5283bc, 0x8f8300e0, 0x8f8200e4, 0x10430007, 0x4821, 0x8f8200e4, +0x24090001, 0x8c430000, 0x8c440004, 0xafa30018, 0xafa4001c, 0x1520000e, +0x3c02ffff, 0x8f8200c4, 0xafa20010, 0x8f8200c8, 0x3c040001, 0x24844be0, +0xafa20014, 0x8f8600e0, 0x8f8700e4, 0x3c050006, 0xc002403, 0x34a5f000, +0x8003840, 0x0, 0x8fa3001c, 0x8fb20018, 0x3073ffff, 0x2673fffc, +0x621024, 0x10400058, 0x2408821, 0x3c020080, 0x621024, 0x1040000a, +0x3c040040, 0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x8ee201ec, +0x24420001, 0xaee201ec, 0x800383a, 0x8ee201ec, 0x3c060004, 0x3c0b0001, +0x3c0a0002, 0x3c050010, 0x3c090008, 0x8ee20080, 0x3c080020, 0x34078000, +0x24420001, 0xaee20080, 0x8ee20080, 0x8fa2001c, 0x441824, 0x10660021, +0xc3102b, 0x14400007, 0x0, 0x106b0011, 0x0, 0x106a0015, +0x0, 0x8003582, 0x42042, 0x10650023, 0xa3102b, 0x14400005, +0x0, 0x10690019, 0x0, 0x8003582, 0x42042, 0x10680021, +0x0, 0x8003582, 0x42042, 0x8ee20034, 0x24420001, 0xaee20034, +0x8ee20034, 0x8003582, 0x42042, 0x8ee201dc, 0x24420001, 0xaee201dc, +0x8ee201dc, 0x8003582, 0x42042, 0x8ee201e0, 0x24420001, 0xaee201e0, +0x8ee201e0, 0x8003582, 0x42042, 0x8ee201e4, 0x24420001, 0xaee201e4, +0x8ee201e4, 0x8003582, 0x42042, 0x8ee20030, 0x24420001, 0xaee20030, +0x8ee20030, 0x8003582, 0x42042, 0x8ee201e8, 0x24420001, 0xaee201e8, +0x8ee201e8, 0x42042, 0x108702b7, 0x0, 0x8003547, 0x0, +0x3c020001, 0x571021, 0x904283a2, 0x14400084, 0x24020001, 0x3c030001, +0x771821, 0x906383a3, 0x1462007f, 0x3c020100, 0x8e430000, 0x621024, +0x1040006f, 0x2402ffff, 0x14620005, 0x24100001, 0x96430004, 0x3402ffff, +0x10620075, 0x0, 0x92e204c8, 0x14400072, 0x0, 0x3c020001, +0x571021, 0x8c4283a4, 0x28420005, 0x10400020, 0x3821, 0x3c020001, +0x571021, 0x8c4283a4, 0x18400016, 0x2821, 0x96260000, 0x520c0, +0x971021, 0x9442776e, 0x14460009, 0x971021, 0x94437770, 0x96220002, +0x14620005, 0x971021, 0x94437772, 0x96220004, 0x50620008, 0x24070001, +0x3c020001, 0x571021, 0x8c4283a4, 0x24a50001, 0xa2102a, 0x5440ffee, +0x520c0, 0x30e200ff, 0x1040027b, 0x0, 0x800360e, 0x0, +0x2402021, 0xc0022f8, 0x24050006, 0x3044001f, 0x428c0, 0x2e51021, +0x9442726c, 0x30424000, 0x1440026f, 0xb71021, 0x9443726e, 0x96220000, +0x1462000b, 0x418c0, 0xb71021, 0x94437270, 0x96220002, 0x14620006, +0x418c0, 0xb71021, 0x94437272, 0x96220004, 0x10620035, 0x418c0, +0x2e31021, 0x9442726c, 0x30428000, 0x1440025c, 0x2e31021, 0x9448726c, +0x96270000, 0x828c0, 0xb71021, 0x9442736e, 0x80035f0, 0x3021, +0x420c0, 0x2e41021, 0x9443736c, 0x2e41021, 0x9448736c, 0x30638000, +0x14600010, 0x828c0, 0xb71021, 0x9442736e, 0x1447fff5, 0x1002021, +0xb71021, 0x94437370, 0x96220002, 0x5462fff1, 0x420c0, 0xb71021, +0x94437372, 0x96220004, 0x5462ffec, 0x420c0, 0x24060001, 0x30c200ff, +0x1040023b, 0x0, 0x800360e, 0x0, 0x97430202, 0x96420000, +0x14620235, 0x0, 0x97430204, 0x96420002, 0x14620231, 0x0, +0x97430206, 0x96420004, 0x1462022d, 0x0, 0x92420000, 0x3a030001, +0x30420001, 0x431024, 0x10400074, 0x2402ffff, 0x8e230000, 0x14620004, +0x3402ffff, 0x96230004, 0x1062006f, 0x24140002, 0x3c020001, 0x571021, +0x904283a2, 0x1440006a, 0x24140003, 0x92e204c8, 0x14400067, 0x0, +0x3c020001, 0x571021, 0x8c4283a4, 0x28420005, 0x10400020, 0x3821, +0x3c020001, 0x571021, 0x8c4283a4, 0x18400016, 0x2821, 0x96260000, +0x520c0, 0x971021, 0x9442776e, 0x14460009, 0x971021, 0x94437770, +0x96220002, 0x14620005, 0x971021, 0x94437772, 0x96220004, 0x50620008, +0x24070001, 0x3c020001, 0x571021, 0x8c4283a4, 0x24a50001, 0xa2102a, +0x5440ffee, 0x520c0, 0x30e200ff, 0x14400044, 0x24140003, 0x800383a, +0x0, 0x2402021, 0xc0022f8, 0x24050006, 0x3044001f, 0x428c0, +0x2e51021, 0x9442726c, 0x30424000, 0x144001ea, 0xb71021, 0x9443726e, +0x96220000, 0x1462000b, 0x418c0, 0xb71021, 0x94437270, 0x96220002, +0x14620006, 0x418c0, 0xb71021, 0x94437272, 0x96220004, 0x10620027, +0x418c0, 0x2e31021, 0x9442726c, 0x30428000, 0x144001d7, 0x2e31021, +0x9448726c, 0x96270000, 0x828c0, 0xb71021, 0x9442736e, 0x8003675, +0x3021, 0x420c0, 0x2e41021, 0x9443736c, 0x2e41021, 0x9448736c, +0x30638000, 0x14600010, 0x828c0, 0xb71021, 0x9442736e, 0x1447fff5, +0x1002021, 0xb71021, 0x94437370, 0x96220002, 0x5462fff1, 0x420c0, +0xb71021, 0x94437372, 0x96220004, 0x5462ffec, 0x420c0, 0x24060001, +0x30c200ff, 0x104001b6, 0x0, 0x8003688, 0x24140003, 0x24140001, +0x8f420260, 0x53102b, 0x10400049, 0x0, 0x8f8300e4, 0x8f8200e0, +0x10620003, 0x24630008, 0xaf8300e4, 0xaf8300e8, 0x8ee400c0, 0x8ee500c4, +0x2601821, 0x1021, 0xa32821, 0xa3302b, 0x822021, 0x862021, +0xaee400c0, 0xaee500c4, 0x8ee20058, 0x24420001, 0xaee20058, 0x8ee20058, +0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x8f8200e0, 0xafa20010, +0x8f8200e4, 0x3c040001, 0x24844be8, 0xafa20014, 0x8fa60018, 0x8fa7001c, +0x3c050006, 0xc002403, 0x34a5f003, 0x8003840, 0x0, 0x8ee25230, +0xafa20010, 0x8ee25234, 0x3c040001, 0x24844bf4, 0xafa20014, 0x8ee60e00, +0x8ee70e08, 0xc002403, 0x34a5f002, 0x8ee201bc, 0x24420001, 0xaee201bc, +0x8ee20000, 0x8ee301bc, 0x2403ffbf, 0x431024, 0x80037e8, 0xaee20000, +0x8ee25230, 0xafa20010, 0x8ee25234, 0x3c040001, 0x24844bf4, 0xafa20014, +0x8ee60e00, 0x8ee70e08, 0x3c050006, 0xc002403, 0x34a5f002, 0x8ee201bc, +0x24420001, 0xaee201bc, 0x80037e8, 0x8ee201bc, 0x96e20468, 0x53102b, +0x54400001, 0x3c158000, 0x12600131, 0x3c0c001f, 0x358cffff, 0x8ee2723c, +0x8f430280, 0x24420001, 0x304203ff, 0x10620108, 0x0, 0x12a00014, +0x0, 0x8ee35230, 0x8ee25234, 0x10620009, 0x26ee5234, 0x8eeb5234, +0x8ee35234, 0x21140, 0x24425238, 0x2e28021, 0x24630001, 0x8003702, +0x306800ff, 0x92e27238, 0x1440ffc0, 0x3c050006, 0x8ee201d0, 0x24420001, +0xaee201d0, 0x8ee201d0, 0x8ee30e00, 0x8ee20e08, 0x1062ffcb, 0x26ee0e08, +0x8eeb0e08, 0xa821, 0x8ee30e08, 0x21140, 0x24420e10, 0x2e28021, +0x24630001, 0x306801ff, 0x96e2046a, 0x30420010, 0x10400017, 0x34028100, +0x9643000c, 0x14620014, 0x0, 0x3c020001, 0x571021, 0x904283b0, +0x1440000f, 0x0, 0x9642000e, 0xa6020016, 0x8e420008, 0x8e430004, +0x8e440000, 0x2673fffc, 0xae42000c, 0xae430008, 0xae440004, 0x9602000e, +0x26310004, 0x24160001, 0x34420200, 0xa602000e, 0x9603000a, 0x2605021, +0x73102b, 0x10400002, 0x2606821, 0x605021, 0x2d42003d, 0x1040002a, +0x3821, 0x9623000c, 0x24020800, 0x54620027, 0xae110018, 0x3c020001, +0x571021, 0x904283b0, 0x54400022, 0xae110018, 0x26220017, 0x182102b, +0x10400013, 0x0, 0x3c02fff5, 0x511021, 0x90421017, 0x38430006, +0x2c630001, 0x38420011, 0x2c420001, 0x621825, 0x10600013, 0x26220010, +0x182102b, 0x1040000e, 0x0, 0x3c07fff5, 0xf13821, 0x94e71010, +0x800374e, 0x24e7000e, 0x92220017, 0x38430006, 0x2c630001, 0x38420011, +0x2c420001, 0x621825, 0x50600004, 0xae110018, 0x96270010, 0x24e7000e, +0xae110018, 0x3c020001, 0x571021, 0x904283b0, 0x2102b, 0x14e00002, +0x24ec0, 0x1403821, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, +0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124, 0x14c20007, 0x2402000b, 0x8ee201a0, 0x4821, 0x24420001, 0xaee201a0, -0x8003719, 0x8ee201a0, 0x8e040000, 0x8e050004, 0xac620018, 0x1751025, +0x80037af, 0x8ee201a0, 0x8e040000, 0x8e050004, 0xac620018, 0x1751025, 0x491025, 0xac710008, 0xa467000e, 0xac62001c, 0xac640000, 0xac650004, 0x8ee204b0, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400038, 0x24090001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 0x14620020, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001c, 0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee34e24, 0x8ee54e20, 0x24020040, 0x24630001, 0x10620007, 0x0, 0x8ee24e24, 0x24420001, 0x10a20005, -0x0, 0x8003703, 0x0, 0x14a00005, 0x0, 0x8f820128, +0x0, 0x8003799, 0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, -0xac800000, 0x8003719, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, +0xac800000, 0x80037af, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, -0xac820004, 0x15200018, 0x3c050006, 0x8e020018, 0x3c040001, 0x248449f0, -0xafa20010, 0x8e020000, 0x8e030004, 0x34a5f009, 0x2003021, 0xc0023a7, +0xac820004, 0x15200018, 0x3c050006, 0x8e020018, 0x3c040001, 0x24844c00, +0xafa20010, 0x8e020000, 0x8e030004, 0x34a5f009, 0x2003021, 0xc002403, 0xafa30014, 0x32c200ff, 0x1040002b, 0x34028100, 0x8e430004, 0x8e440008, 0x8e45000c, 0xa642000c, 0xae430000, 0xae440004, 0xae450008, 0x96020016, -0x8003752, 0xa642000e, 0x154d000a, 0x0, 0x9602000e, 0xa613000a, -0x34420004, 0xa602000e, 0x3c010001, 0x370821, 0xa02083b0, 0x8003750, +0x80037e8, 0xa642000e, 0x154d000a, 0x0, 0x9602000e, 0xa613000a, +0x34420004, 0xa602000e, 0x3c010001, 0x370821, 0xa02083b0, 0x80037e6, 0x9821, 0x9604000a, 0x93102b, 0x10400002, 0x2601821, 0x801821, 0x24020001, 0xa603000a, 0x3c010001, 0x370821, 0xa02283b0, 0x9604000a, 0x2248821, 0x191102b, 0x10400003, 0x3c02fff5, 0x34421000, 0x2228821, -0x2649823, 0xa821, 0x1660fef7, 0xadc80000, 0x12600021, 0x32c200ff, +0x2649823, 0xa821, 0x1660fef4, 0xadc80000, 0x12600021, 0x32c200ff, 0x3c010001, 0x370821, 0xac3383b4, 0x3c010001, 0x370821, 0xac3183b8, 0x3c010001, 0x370821, 0x10400008, 0xac3283bc, 0x3c020001, 0x571021, 0x8c4283bc, 0x24420004, 0x3c010001, 0x370821, 0xac2283bc, 0x8ee2723c, 0x8f430280, 0x24420001, 0x14620006, 0x0, 0x8ee201c0, 0x24420001, -0xaee201c0, 0x80037aa, 0x8ee201c0, 0x8ee201b8, 0x24420001, 0xaee201b8, -0x80037aa, 0x8ee201b8, 0x97a4001e, 0x2484fffc, 0x801821, 0x8ee400c0, +0xaee201c0, 0x8003840, 0x8ee201c0, 0x8ee201b8, 0x24420001, 0xaee201b8, +0x8003840, 0x8ee201b8, 0x97a4001e, 0x2484fffc, 0x801821, 0x8ee400c0, 0x8ee500c4, 0x1021, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0x24020002, 0xaee400c0, 0xaee500c4, 0x1282000f, 0x2a820003, 0x14400017, 0x24020003, 0x16820015, 0x0, 0x8ee200d0, 0x8ee300d4, 0x24630001, -0x2c640001, 0x441021, 0xaee200d0, 0xaee300d4, 0x8ee200d0, 0x80037a4, +0x2c640001, 0x441021, 0xaee200d0, 0xaee300d4, 0x8ee200d0, 0x800383a, 0x8ee300d4, 0x8ee200d8, 0x8ee300dc, 0x24630001, 0x2c640001, 0x441021, -0xaee200d8, 0xaee300dc, 0x8ee200d8, 0x80037a4, 0x8ee300dc, 0x8ee200c8, +0xaee200d8, 0xaee300dc, 0x8ee200d8, 0x800383a, 0x8ee300dc, 0x8ee200c8, 0x8ee300cc, 0x24630001, 0x2c640001, 0x441021, 0xaee200c8, 0xaee300cc, 0x8ee200c8, 0x8ee300cc, 0x8f8300e4, 0x8f8200e0, 0x10620003, 0x24630008, 0xaf8300e4, 0xaf8300e8, 0x8fbf004c, 0x8fb60048, 0x8fb50044, 0x8fb40040, 0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008, 0x27bd0050, -0x27bdff90, 0xafbe0064, 0xf021, 0xafbf0068, 0xafb60060, 0xafb5005c, +0x27bdff90, 0xafb60060, 0xb021, 0xafbf0068, 0xafbe0064, 0xafb5005c, 0xafb40058, 0xafb30054, 0xafb20050, 0xafb1004c, 0xafb00048, 0x8ee204c4, -0x8821, 0x24160001, 0x30420001, 0x1440002a, 0xa3a0002f, 0x8f8700e0, +0x8821, 0x24150001, 0x30420001, 0x1440002a, 0xa3a0002f, 0x8f8700e0, 0x8f8800c4, 0x8f8200e8, 0xe22023, 0x2c821000, 0x50400001, 0x24841000, 0x420c2, 0x801821, 0x8ee400c8, 0x8ee500cc, 0x1021, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xaee400c8, 0xaee500cc, 0x8f8300c8, 0x3c02000a, 0x3442efff, 0x1032023, 0x44102b, 0x10400003, 0x3c02000a, 0x3442f000, 0x822021, 0x801821, 0x8ee400c0, 0x8ee500c4, 0x1021, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xaee400c0, 0xaee500c4, -0xaf8800c8, 0xaf8700e4, 0x8003bb3, 0xaf8700e8, 0x3c020001, 0x571021, +0xaf8800c8, 0xaf8700e4, 0x8003c4b, 0xaf8700e8, 0x3c020001, 0x571021, 0x904283b0, 0x1040000b, 0x0, 0x3c130001, 0x2779821, 0x8e7383b4, -0x3c100001, 0x2178021, 0x8e1083b8, 0x3c120001, 0x2579021, 0x80039b3, +0x3c100001, 0x2178021, 0x8e1083b8, 0x3c120001, 0x2579021, 0x8003a49, 0x8e5283bc, 0x8f8300e0, 0x8f8200e4, 0x10430007, 0x3821, 0x8f8200e4, 0x24070001, 0x8c430000, 0x8c440004, 0xafa30018, 0xafa4001c, 0x14e0000e, -0x3c02ffff, 0x8f8200c4, 0xafa20010, 0x8f8200c8, 0x3c040001, 0x24844a14, -0xafa20014, 0x8f8600e0, 0x8f8700e4, 0x3c050006, 0xc0023a7, 0x34a5f200, -0x8003bb3, 0x0, 0x8fa3001c, 0x8fb20018, 0x3073ffff, 0x2673fffc, +0x3c02ffff, 0x8f8200c4, 0xafa20010, 0x8f8200c8, 0x3c040001, 0x24844c24, +0xafa20014, 0x8f8600e0, 0x8f8700e4, 0x3c050006, 0xc002403, 0x34a5f200, +0x8003c4b, 0x0, 0x8fa3001c, 0x8fb20018, 0x3073ffff, 0x2673fffc, 0x621024, 0x10400058, 0x2408021, 0x3c020080, 0x621024, 0x1040000a, 0x3c040040, 0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x8ee201ec, -0x24420001, 0xaee201ec, 0x8003bad, 0x8ee201ec, 0x3c060004, 0x3c0b0001, +0x24420001, 0xaee201ec, 0x8003c45, 0x8ee201ec, 0x3c060004, 0x3c0b0001, 0x3c0a0002, 0x3c050010, 0x3c090008, 0x8ee20080, 0x3c080020, 0x34078000, 0x24420001, 0xaee20080, 0x8ee20080, 0x8fa2001c, 0x441824, 0x10660021, 0xc3102b, 0x14400007, 0x0, 0x106b0011, 0x0, 0x106a0015, -0x0, 0x8003870, 0x42042, 0x10650023, 0xa3102b, 0x14400005, -0x0, 0x10690019, 0x0, 0x8003870, 0x42042, 0x10680021, -0x0, 0x8003870, 0x42042, 0x8ee20034, 0x24420001, 0xaee20034, -0x8ee20034, 0x8003870, 0x42042, 0x8ee201dc, 0x24420001, 0xaee201dc, -0x8ee201dc, 0x8003870, 0x42042, 0x8ee201e0, 0x24420001, 0xaee201e0, -0x8ee201e0, 0x8003870, 0x42042, 0x8ee201e4, 0x24420001, 0xaee201e4, -0x8ee201e4, 0x8003870, 0x42042, 0x8ee20030, 0x24420001, 0xaee20030, -0x8ee20030, 0x8003870, 0x42042, 0x8ee201e8, 0x24420001, 0xaee201e8, -0x8ee201e8, 0x42042, 0x1087033c, 0x0, 0x8003835, 0x0, +0x0, 0x8003906, 0x42042, 0x10650023, 0xa3102b, 0x14400005, +0x0, 0x10690019, 0x0, 0x8003906, 0x42042, 0x10680021, +0x0, 0x8003906, 0x42042, 0x8ee20034, 0x24420001, 0xaee20034, +0x8ee20034, 0x8003906, 0x42042, 0x8ee201dc, 0x24420001, 0xaee201dc, +0x8ee201dc, 0x8003906, 0x42042, 0x8ee201e0, 0x24420001, 0xaee201e0, +0x8ee201e0, 0x8003906, 0x42042, 0x8ee201e4, 0x24420001, 0xaee201e4, +0x8ee201e4, 0x8003906, 0x42042, 0x8ee20030, 0x24420001, 0xaee20030, +0x8ee20030, 0x8003906, 0x42042, 0x8ee201e8, 0x24420001, 0xaee201e8, +0x8ee201e8, 0x42042, 0x1087033e, 0x0, 0x80038cb, 0x0, 0x3c020001, 0x571021, 0x904283a2, 0x14400084, 0x24020001, 0x3c030001, 0x771821, 0x906383a3, 0x1462007f, 0x3c020100, 0x8e430000, 0x621024, 0x1040006f, 0x2402ffff, 0x14620005, 0x24110001, 0x96430004, 0x3402ffff, @@ -1749,491 +1774,487 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] = { 0x971021, 0x9442776e, 0x14460009, 0x971021, 0x94437770, 0x96020002, 0x14620005, 0x971021, 0x94437772, 0x96020004, 0x50620008, 0x24070001, 0x3c020001, 0x571021, 0x8c4283a4, 0x24a50001, 0xa2102a, 0x5440ffee, -0x520c0, 0x30e200ff, 0x10400300, 0x0, 0x80038fc, 0x0, -0x2402021, 0xc00229d, 0x24050006, 0x3044001f, 0x428c0, 0x2e51021, -0x9442726c, 0x30424000, 0x144002f4, 0xb71021, 0x9443726e, 0x96020000, +0x520c0, 0x30e200ff, 0x10400302, 0x0, 0x8003992, 0x0, +0x2402021, 0xc0022f8, 0x24050006, 0x3044001f, 0x428c0, 0x2e51021, +0x9442726c, 0x30424000, 0x144002f6, 0xb71021, 0x9443726e, 0x96020000, 0x1462000b, 0x418c0, 0xb71021, 0x94437270, 0x96020002, 0x14620006, 0x418c0, 0xb71021, 0x94437272, 0x96020004, 0x10620035, 0x418c0, -0x2e31021, 0x9442726c, 0x30428000, 0x144002e1, 0x2e31021, 0x944e726c, -0x96070000, 0xe28c0, 0xb71021, 0x9442736e, 0x80038de, 0x3021, -0x420c0, 0x2e41021, 0x9443736c, 0x2e41021, 0x944e736c, 0x30638000, -0x14600010, 0xe28c0, 0xb71021, 0x9442736e, 0x1447fff5, 0x1c02021, +0x2e31021, 0x9442726c, 0x30428000, 0x144002e3, 0x2e31021, 0x944d726c, +0x96070000, 0xd28c0, 0xb71021, 0x9442736e, 0x8003974, 0x3021, +0x420c0, 0x2e41021, 0x9443736c, 0x2e41021, 0x944d736c, 0x30638000, +0x14600010, 0xd28c0, 0xb71021, 0x9442736e, 0x1447fff5, 0x1a02021, 0xb71021, 0x94437370, 0x96020002, 0x5462fff1, 0x420c0, 0xb71021, 0x94437372, 0x96020004, 0x5462ffec, 0x420c0, 0x24060001, 0x30c200ff, -0x104002c0, 0x0, 0x80038fc, 0x0, 0x97430202, 0x96420000, -0x146202ba, 0x0, 0x97430204, 0x96420002, 0x146202b6, 0x0, -0x97430206, 0x96420004, 0x146202b2, 0x0, 0x92420000, 0x3a230001, +0x104002c2, 0x0, 0x8003992, 0x0, 0x97430202, 0x96420000, +0x146202bc, 0x0, 0x97430204, 0x96420002, 0x146202b8, 0x0, +0x97430206, 0x96420004, 0x146202b4, 0x0, 0x92420000, 0x3a230001, 0x30420001, 0x431024, 0x10400074, 0x2402ffff, 0x8e030000, 0x14620004, -0x3402ffff, 0x96030004, 0x1062006f, 0x24160002, 0x3c020001, 0x571021, -0x904283a2, 0x1440006a, 0x24160003, 0x92e204c8, 0x14400067, 0x0, +0x3402ffff, 0x96030004, 0x1062006f, 0x24150002, 0x3c020001, 0x571021, +0x904283a2, 0x1440006a, 0x24150003, 0x92e204c8, 0x14400067, 0x0, 0x3c020001, 0x571021, 0x8c4283a4, 0x28420005, 0x10400020, 0x3821, 0x3c020001, 0x571021, 0x8c4283a4, 0x18400016, 0x2821, 0x96060000, 0x520c0, 0x971021, 0x9442776e, 0x14460009, 0x971021, 0x94437770, 0x96020002, 0x14620005, 0x971021, 0x94437772, 0x96020004, 0x50620008, 0x24070001, 0x3c020001, 0x571021, 0x8c4283a4, 0x24a50001, 0xa2102a, -0x5440ffee, 0x520c0, 0x30e200ff, 0x14400044, 0x24160003, 0x8003bad, -0x0, 0x2402021, 0xc00229d, 0x24050006, 0x3044001f, 0x428c0, -0x2e51021, 0x9442726c, 0x30424000, 0x1440026f, 0xb71021, 0x9443726e, +0x5440ffee, 0x520c0, 0x30e200ff, 0x14400044, 0x24150003, 0x8003c45, +0x0, 0x2402021, 0xc0022f8, 0x24050006, 0x3044001f, 0x428c0, +0x2e51021, 0x9442726c, 0x30424000, 0x14400271, 0xb71021, 0x9443726e, 0x96020000, 0x1462000b, 0x418c0, 0xb71021, 0x94437270, 0x96020002, 0x14620006, 0x418c0, 0xb71021, 0x94437272, 0x96020004, 0x10620027, -0x418c0, 0x2e31021, 0x9442726c, 0x30428000, 0x1440025c, 0x2e31021, -0x944e726c, 0x96070000, 0xe28c0, 0xb71021, 0x9442736e, 0x8003963, -0x3021, 0x420c0, 0x2e41021, 0x9443736c, 0x2e41021, 0x944e736c, -0x30638000, 0x14600010, 0xe28c0, 0xb71021, 0x9442736e, 0x1447fff5, -0x1c02021, 0xb71021, 0x94437370, 0x96020002, 0x5462fff1, 0x420c0, +0x418c0, 0x2e31021, 0x9442726c, 0x30428000, 0x1440025e, 0x2e31021, +0x944d726c, 0x96070000, 0xd28c0, 0xb71021, 0x9442736e, 0x80039f9, +0x3021, 0x420c0, 0x2e41021, 0x9443736c, 0x2e41021, 0x944d736c, +0x30638000, 0x14600010, 0xd28c0, 0xb71021, 0x9442736e, 0x1447fff5, +0x1a02021, 0xb71021, 0x94437370, 0x96020002, 0x5462fff1, 0x420c0, 0xb71021, 0x94437372, 0x96020004, 0x5462ffec, 0x420c0, 0x24060001, -0x30c200ff, 0x1040023b, 0x0, 0x8003976, 0x24160003, 0x24160001, +0x30c200ff, 0x1040023d, 0x0, 0x8003a0c, 0x24150003, 0x24150001, 0x8f420260, 0x53102b, 0x10400036, 0x0, 0x8f8300e4, 0x8f8200e0, 0x10620003, 0x24630008, 0xaf8300e4, 0xaf8300e8, 0x8ee400c0, 0x8ee500c4, 0x2601821, 0x1021, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xaee400c0, 0xaee500c4, 0x8ee20058, 0x24420001, 0xaee20058, 0x8ee20058, 0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x8f8200e0, 0xafa20010, -0x8f8200e4, 0x3c040001, 0x24844a20, 0xafa20014, 0x8fa60018, 0x8fa7001c, -0x3c050006, 0xc0023a7, 0x34a5f203, 0x8003bb3, 0x0, 0x8ee25230, -0xafa20010, 0x8ee25234, 0x3c040001, 0x24844a2c, 0xafa20014, 0x8ee60e00, -0x8ee70e08, 0x3c050006, 0xc0023a7, 0x34a5f202, 0x8ee201bc, 0x24420001, -0xaee201bc, 0x8003b5a, 0x8ee201bc, 0x96e20468, 0x53102b, 0x54400001, -0x3c1e8000, 0x126001c9, 0x3c0f001f, 0x35efffff, 0x3c18fff5, 0x37181000, -0x8ee2723c, 0x8f430280, 0x24420001, 0x304203ff, 0x1062019d, 0x0, -0x13c00012, 0x0, 0x8ee35230, 0x8ee25234, 0x1062000a, 0x26f95234, -0x8ef55234, 0xafb90024, 0x8ee35234, 0x21140, 0x24425238, 0x2e28821, -0x24630001, 0x80039de, 0x306e00ff, 0x8ee201d0, 0x24420001, 0xaee201d0, -0x8ee201d0, 0x8ee30e00, 0x8ee20e08, 0x1062ffcb, 0x26f90e08, 0x8ef50e08, -0xf021, 0xafb90024, 0x8ee30e08, 0x21140, 0x24420e10, 0x2e28821, -0x24630001, 0x306e01ff, 0x96e2046a, 0x30420010, 0x10400018, 0x34028100, -0x9643000c, 0x14620015, 0x0, 0x3c020001, 0x571021, 0x904283b0, -0x14400010, 0x0, 0x9642000e, 0xa6220016, 0x8e420008, 0x8e430004, -0x8e440000, 0x2673fffc, 0xae42000c, 0xae430008, 0xae440004, 0x9622000e, -0x26100004, 0x24190001, 0xa3b9002f, 0x34420200, 0xa622000e, 0x8e220000, -0x8e230004, 0x3c040001, 0x34843800, 0x2003021, 0x306b0007, 0x20b8023, -0x3641021, 0x202102b, 0x10400005, 0x26b9821, 0x2041023, 0x3621823, -0x3c020020, 0x438023, 0x26620007, 0x9623000a, 0x2419fff8, 0x59a024, -0x6b1821, 0x74102b, 0x10400002, 0x2806821, 0x606821, 0x1a01821, -0x24620007, 0x2419fff8, 0x596824, 0x26d102b, 0x14400004, 0x1b32823, -0x1a32823, 0x8003a1c, 0xc31021, 0xd31021, 0x4b2023, 0x1e4102b, -0x54400001, 0x982021, 0x25620040, 0x4d102b, 0x14400035, 0x6021, -0x94c3000c, 0x24020800, 0x54620032, 0xae260018, 0x3c020001, 0x571021, -0x904283b0, 0x5440002d, 0xae260018, 0x24c20017, 0x1e2102b, 0x10400013, -0x0, 0x3c02fff5, 0x461021, 0x90421017, 0x38430006, 0x2c630001, -0x38420011, 0x2c420001, 0x621825, 0x10600014, 0x24c20010, 0x1e2102b, -0x1040000e, 0x0, 0x3c0cfff5, 0x1866021, 0x958c1010, 0x8003a4d, -0x2582000e, 0x90c20017, 0x38430006, 0x2c630001, 0x38420011, 0x2c420001, -0x621825, 0x10600005, 0x1801821, 0x94cc0010, 0x2582000e, 0x4b6021, -0x1801821, 0x24620007, 0x2419fff8, 0x596024, 0xc31021, 0x4b2023, -0x1e4102b, 0x10400002, 0x1832823, 0x982021, 0xae260018, 0x3c020001, -0x571021, 0x904283b0, 0x2102b, 0x216c0, 0x15800002, 0xafa20044, -0x1a06021, 0x30820001, 0x10400007, 0x4021, 0x90880000, 0x24840001, -0x1e4102b, 0x10400002, 0x24a5ffff, 0x982021, 0x50a00012, 0x81c02, +0x8f8200e4, 0x3c040001, 0x24844c30, 0xafa20014, 0x8fa60018, 0x8fa7001c, +0x3c050006, 0xc002403, 0x34a5f203, 0x8003c4b, 0x0, 0x8ee25230, +0xafa20010, 0x8ee25234, 0x3c040001, 0x24844c3c, 0xafa20014, 0x8ee60e00, +0x8ee70e08, 0x3c050006, 0xc002403, 0x34a5f202, 0x8ee201bc, 0x24420001, +0xaee201bc, 0x8003bf2, 0x8ee201bc, 0x96e20468, 0x53102b, 0x54400001, +0x3c168000, 0x126001cb, 0x3c0e001f, 0x35ceffff, 0x3c0ffff5, 0x35ef1000, +0x241e0040, 0x8ee2723c, 0x8f430280, 0x24420001, 0x304203ff, 0x1062019e, +0x0, 0x12c00012, 0x0, 0x8ee35230, 0x8ee25234, 0x1062000a, +0x26f85234, 0x8ef45234, 0xafb80024, 0x8ee35234, 0x21140, 0x24425238, +0x2e28821, 0x24630001, 0x8003a75, 0x306d00ff, 0x8ee201d0, 0x24420001, +0xaee201d0, 0x8ee201d0, 0x8ee30e00, 0x8ee20e08, 0x1062ffca, 0x26f80e08, +0x8ef40e08, 0xb021, 0xafb80024, 0x8ee30e08, 0x21140, 0x24420e10, +0x2e28821, 0x24630001, 0x306d01ff, 0x96e2046a, 0x30420010, 0x10400018, +0x34028100, 0x9643000c, 0x14620015, 0x0, 0x3c020001, 0x571021, +0x904283b0, 0x14400010, 0x0, 0x9642000e, 0xa6220016, 0x8e420008, +0x8e430004, 0x8e440000, 0x2673fffc, 0xae42000c, 0xae430008, 0xae440004, +0x9622000e, 0x26100004, 0x24180001, 0xa3b8002f, 0x34420200, 0xa622000e, +0x8e220000, 0x8e230004, 0x3c040001, 0x34843800, 0x2003021, 0x306a0007, +0x20a8023, 0x3641021, 0x202102b, 0x10400005, 0x26a9821, 0x2041023, +0x3621823, 0x3c020020, 0x438023, 0x26620007, 0x9623000a, 0x2418fff8, +0x58c824, 0x6a1821, 0x79102b, 0x10400002, 0x3206021, 0x606021, +0x1801821, 0x24620007, 0x2418fff8, 0x586024, 0x26c102b, 0x14400004, +0x1932823, 0x1832823, 0x8003ab3, 0xc31021, 0xd31021, 0x4a2023, +0x1c4102b, 0x54400001, 0x8f2021, 0x25420040, 0x4c102b, 0x14400035, +0x5821, 0x94c3000c, 0x24020800, 0x54620032, 0xae260018, 0x3c020001, +0x571021, 0x904283b0, 0x5440002d, 0xae260018, 0x24c20017, 0x1c2102b, +0x10400013, 0x0, 0x3c02fff5, 0x461021, 0x90421017, 0x38430006, +0x2c630001, 0x38420011, 0x2c420001, 0x621825, 0x10600014, 0x24c20010, +0x1c2102b, 0x1040000e, 0x0, 0x3c0bfff5, 0x1665821, 0x956b1010, +0x8003ae4, 0x2562000e, 0x90c20017, 0x38430006, 0x2c630001, 0x38420011, +0x2c420001, 0x621825, 0x10600005, 0x1601821, 0x94cb0010, 0x2562000e, +0x4a5821, 0x1601821, 0x24620007, 0x2418fff8, 0x585824, 0xc31021, +0x4a2023, 0x1c4102b, 0x10400002, 0x1632823, 0x8f2021, 0xae260018, +0x3c020001, 0x571021, 0x904283b0, 0x2102b, 0x216c0, 0x15600002, +0xafa20044, 0x1805821, 0x30820001, 0x10400007, 0x4021, 0x90880000, +0x24840001, 0x1c4102b, 0x10400002, 0x24a5ffff, 0x8f2021, 0x50a00012, +0x81c02, 0x2ca20002, 0x54400009, 0x24a5ffff, 0x94820000, 0x24840002, +0x1024021, 0x1c4102b, 0x10400006, 0x24a5fffe, 0x8003b11, 0x8f2021, +0x90820000, 0x21200, 0x1024021, 0x14a0fff2, 0x2ca20002, 0x81c02, +0x3102ffff, 0x624021, 0x3108ffff, 0x1402821, 0x11400011, 0x2002021, 0x2ca20002, 0x54400009, 0x24a5ffff, 0x94820000, 0x24840002, 0x1024021, -0x1e4102b, 0x10400006, 0x24a5fffe, 0x8003a7a, 0x982021, 0x90820000, +0x1c4102b, 0x10400006, 0x24a5fffe, 0x8003b28, 0x8f2021, 0x90820000, 0x21200, 0x1024021, 0x14a0fff2, 0x2ca20002, 0x81c02, 0x3102ffff, -0x624021, 0x3108ffff, 0x1602821, 0x11600011, 0x2002021, 0x2ca20002, -0x54400009, 0x24a5ffff, 0x94820000, 0x24840002, 0x1024021, 0x1e4102b, -0x10400006, 0x24a5fffe, 0x8003a91, 0x982021, 0x90820000, 0x21200, -0x1024021, 0x14a0fff2, 0x2ca20002, 0x81c02, 0x3102ffff, 0x624021, -0x81c02, 0x3102ffff, 0x8f890120, 0x624021, 0x27623800, 0x252a0020, -0x142102b, 0x14400002, 0x3108ffff, 0x276a3000, 0x8f820128, 0x15420007, -0x1602821, 0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0, 0x8003b21, -0x8ee201a0, 0x8e260000, 0x8e270004, 0x81400, 0x3443000b, 0xad300008, -0xa52c000e, 0xad230018, 0x8fb90044, 0x2021, 0x2be1025, 0x591025, -0xad22001c, 0xe5102b, 0xe53823, 0xc43023, 0xc23023, 0xad260000, -0xad270004, 0x8ee204b0, 0xad220010, 0xaf8a0120, 0x92e24e10, 0x14400061, -0x24070001, 0x2462ffee, 0x2c420002, 0x14400003, 0x24020011, 0x14620025, -0x0, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, -0x24020012, 0x1462000f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062000b, -0x24190040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, -0x24420001, 0x1059002b, 0x0, 0x8003aff, 0x0, 0x8ee24e20, -0x24190040, 0x24420001, 0x50590003, 0x1021, 0x8ee24e20, 0x24420001, -0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8003b1e, -0x24020012, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, -0x24020007, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, -0x24190040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, -0x24420001, 0x10590007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, -0x0, 0x8003b0b, 0x0, 0x14600005, 0x0, 0x8f820128, -0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, -0xac800000, 0x8003b21, 0x0, 0x8ee24e20, 0x24190040, 0x24420001, -0x50590003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, -0x210c0, 0x24425028, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, -0xac820004, 0x14e00019, 0x3c050006, 0x3c040001, 0x248449f0, 0x8e220018, -0x34a5f209, 0xafa20010, 0x8e220000, 0x8e230004, 0x2203021, 0x1803821, -0xc0023a7, 0xafa30014, 0x93a2002f, 0x1040002a, 0x34028100, 0x8e430004, -0x8e440008, 0x8e45000c, 0xa642000c, 0xae430000, 0xae440004, 0xae450008, -0x96220016, 0x8003b5a, 0xa642000e, 0x15b4000a, 0x26b1823, 0x9622000e, -0xa623000a, 0x34420004, 0xa622000e, 0x3c010001, 0x370821, 0xa02083b0, -0x8003b57, 0x9821, 0x9624000a, 0x83102b, 0x54400001, 0x801821, -0x24020001, 0xa623000a, 0x3c010001, 0x370821, 0xa02283b0, 0x9622000a, -0x4b1821, 0x2038021, 0x1f0102b, 0x54400001, 0x2188021, 0x2639823, -0xf021, 0x8fb90024, 0x1660fe5f, 0xaf2e0000, 0x12600022, 0x0, -0x3c010001, 0x370821, 0xac3383b4, 0x3c010001, 0x370821, 0xac3083b8, -0x3c010001, 0x370821, 0xac3283bc, 0x93a2002f, 0x10400008, 0x0, -0x3c020001, 0x571021, 0x8c4283bc, 0x24420004, 0x3c010001, 0x370821, -0xac2283bc, 0x8f430280, 0x8ee2723c, 0x14620006, 0x0, 0x8ee201c0, -0x24420001, 0xaee201c0, 0x8003bb3, 0x8ee201c0, 0x8ee201b8, 0x24420001, -0xaee201b8, 0x8003bb3, 0x8ee201b8, 0x97a4001e, 0x2484fffc, 0x801821, -0x8ee400c0, 0x8ee500c4, 0x1021, 0xa32821, 0xa3302b, 0x822021, -0x862021, 0x24020002, 0xaee400c0, 0xaee500c4, 0x12c2000f, 0x2ac20003, -0x14400017, 0x24020003, 0x16c20015, 0x0, 0x8ee200d0, 0x8ee300d4, -0x24630001, 0x2c640001, 0x441021, 0xaee200d0, 0xaee300d4, 0x8ee200d0, -0x8003bad, 0x8ee300d4, 0x8ee200d8, 0x8ee300dc, 0x24630001, 0x2c640001, -0x441021, 0xaee200d8, 0xaee300dc, 0x8ee200d8, 0x8003bad, 0x8ee300dc, -0x8ee200c8, 0x8ee300cc, 0x24630001, 0x2c640001, 0x441021, 0xaee200c8, -0xaee300cc, 0x8ee200c8, 0x8ee300cc, 0x8f8300e4, 0x8f8200e0, 0x10620003, -0x24630008, 0xaf8300e4, 0xaf8300e8, 0x8fbf0068, 0x8fbe0064, 0x8fb60060, -0x8fb5005c, 0x8fb40058, 0x8fb30054, 0x8fb20050, 0x8fb1004c, 0x8fb00048, -0x3e00008, 0x27bd0070, 0x27bdffe0, 0xafbf0018, 0x8ee30e04, 0x8ee20dfc, -0x10620071, 0x0, 0x8ee30dfc, 0x8ee20e04, 0x622023, 0x4820001, -0x24840200, 0x8ee30e08, 0x8ee20e04, 0x43102b, 0x14400004, 0x24020200, -0x8ee30e04, 0x8003bd5, 0x431823, 0x8ee20e08, 0x8ee30e04, 0x431023, +0x624021, 0x81c02, 0x3102ffff, 0x8f890120, 0x624021, 0x27623800, +0x25230020, 0x62102b, 0x14400002, 0x3108ffff, 0x27633000, 0x8f820128, +0x10620004, 0x0, 0x8f820124, 0x14620007, 0x1402821, 0x8ee201a0, +0x3821, 0x24420001, 0xaee201a0, 0x8003bb9, 0x8ee201a0, 0x8e260000, +0x8e270004, 0x81400, 0x3448000b, 0xad300008, 0xa52b000e, 0xad280018, +0x8fb80044, 0x2021, 0x2961025, 0x581025, 0xad22001c, 0xe5102b, +0xe53823, 0xc43023, 0xc23023, 0xad260000, 0xad270004, 0x8ee204b0, +0xad220010, 0xaf830120, 0x92e24e10, 0x1440005f, 0x24070001, 0x2502ffee, +0x2c420002, 0x14400003, 0x24020011, 0x15020024, 0x0, 0x8ee24e20, +0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020012, 0x1462000f, +0x0, 0x8ee34e20, 0x8ee24e24, 0x1062000b, 0x0, 0x8c820004, +0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x105e002a, +0x0, 0x8003b98, 0x0, 0x8ee24e20, 0x24420001, 0x505e0003, +0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, +0x24425028, 0x2e22021, 0x8003bb6, 0x24020012, 0x8ee24e20, 0x210c0, +0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 0x1462001f, 0x0, +0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001, +0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x105e0007, 0x0, +0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x8003ba4, 0x0, +0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, +0x8c820004, 0x2c420011, 0x50400012, 0xac800000, 0x8003bb9, 0x0, +0x8ee24e20, 0x24420001, 0x505e0003, 0x1021, 0x8ee24e20, 0x24420001, +0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020007, +0xac820000, 0x24020001, 0xac820004, 0x14e00019, 0x3c050006, 0x3c040001, +0x24844c00, 0x8e220018, 0x34a5f209, 0xafa20010, 0x8e220000, 0x8e230004, +0x2203021, 0x1603821, 0xc002403, 0xafa30014, 0x93a2002f, 0x1040002a, +0x34028100, 0x8e430004, 0x8e440008, 0x8e45000c, 0xa642000c, 0xae430000, +0xae440004, 0xae450008, 0x96220016, 0x8003bf2, 0xa642000e, 0x1599000a, +0x26a1823, 0x9622000e, 0xa623000a, 0x34420004, 0xa622000e, 0x3c010001, +0x370821, 0xa02083b0, 0x8003bef, 0x9821, 0x9624000a, 0x83102b, +0x54400001, 0x801821, 0x24020001, 0xa623000a, 0x3c010001, 0x370821, +0xa02283b0, 0x9622000a, 0x4a1821, 0x2038021, 0x1d0102b, 0x54400001, +0x20f8021, 0x2639823, 0xb021, 0x8fb80024, 0x1660fe5e, 0xaf0d0000, +0x12600022, 0x0, 0x3c010001, 0x370821, 0xac3383b4, 0x3c010001, +0x370821, 0xac3083b8, 0x3c010001, 0x370821, 0xac3283bc, 0x93a2002f, +0x10400008, 0x0, 0x3c020001, 0x571021, 0x8c4283bc, 0x24420004, +0x3c010001, 0x370821, 0xac2283bc, 0x8f430280, 0x8ee2723c, 0x14620006, +0x0, 0x8ee201c0, 0x24420001, 0xaee201c0, 0x8003c4b, 0x8ee201c0, +0x8ee201b8, 0x24420001, 0xaee201b8, 0x8003c4b, 0x8ee201b8, 0x97a4001e, +0x2484fffc, 0x801821, 0x8ee400c0, 0x8ee500c4, 0x1021, 0xa32821, +0xa3302b, 0x822021, 0x862021, 0x24020002, 0xaee400c0, 0xaee500c4, +0x12a2000f, 0x2aa20003, 0x14400017, 0x24020003, 0x16a20015, 0x0, +0x8ee200d0, 0x8ee300d4, 0x24630001, 0x2c640001, 0x441021, 0xaee200d0, +0xaee300d4, 0x8ee200d0, 0x8003c45, 0x8ee300d4, 0x8ee200d8, 0x8ee300dc, +0x24630001, 0x2c640001, 0x441021, 0xaee200d8, 0xaee300dc, 0x8ee200d8, +0x8003c45, 0x8ee300dc, 0x8ee200c8, 0x8ee300cc, 0x24630001, 0x2c640001, +0x441021, 0xaee200c8, 0xaee300cc, 0x8ee200c8, 0x8ee300cc, 0x8f8300e4, +0x8f8200e0, 0x10620003, 0x24630008, 0xaf8300e4, 0xaf8300e8, 0x8fbf0068, +0x8fbe0064, 0x8fb60060, 0x8fb5005c, 0x8fb40058, 0x8fb30054, 0x8fb20050, +0x8fb1004c, 0x8fb00048, 0x3e00008, 0x27bd0070, 0x27bdffe0, 0xafbf0018, +0x8ee30e04, 0x8ee20dfc, 0x10620074, 0x0, 0x8ee30dfc, 0x8ee20e04, +0x622023, 0x4820001, 0x24840200, 0x8ee30e08, 0x8ee20e04, 0x43102b, +0x14400004, 0x24020200, 0x8ee30e04, 0x8003c6d, 0x431823, 0x8ee20e08, +0x8ee30e04, 0x431023, 0x2443ffff, 0x804821, 0x69102a, 0x54400001, +0x604821, 0x8f870100, 0x27623000, 0x24e80020, 0x102102b, 0x50400001, +0x27682800, 0x8f820108, 0x11020004, 0x0, 0x8f820104, 0x15020007, +0x1021, 0x8ee201a4, 0x2021, 0x24420001, 0xaee201a4, 0x8003caf, +0x8ee201a4, 0x8ee40e04, 0x42140, 0x801821, 0x8ee40460, 0x8ee50464, +0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, +0x8ee30e04, 0x91140, 0xa4e2000e, 0x24020002, 0xace20018, 0x31940, +0x24630e10, 0x2e31021, 0xace20008, 0x8ee20e04, 0xace2001c, 0x8ee204bc, +0xace20010, 0xaf880100, 0x92e204dc, 0x14400011, 0x24040001, 0x8ee24e18, +0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, +0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e21821, 0x24020002, +0xac620000, 0x24020001, 0xac620004, 0x1480000e, 0x24030040, 0x8ee20e04, +0xafa20010, 0x8ee20e08, 0x3c050007, 0xafa20014, 0x8ee60dfc, 0x8ee70e00, +0x3c040001, 0x24844c44, 0xc002403, 0x34a5f001, 0x8003ccd, 0x0, +0x8ee204f0, 0x24420001, 0x50430003, 0x1021, 0x8ee204f0, 0x24420001, +0xaee204f0, 0x8ee204f0, 0x21080, 0x571021, 0xac4904f8, 0x8ee20e04, +0x491021, 0x304201ff, 0xaee20e04, 0x8ee30e04, 0x8ee20dfc, 0x14620005, +0x0, 0x8f820060, 0x2403fdff, 0x431024, 0xaf820060, 0x8fbf0018, +0x3e00008, 0x27bd0020, 0x27bdffe0, 0xafbf0018, 0x8ee3522c, 0x8ee25228, +0x10620074, 0x0, 0x8ee35228, 0x8ee2522c, 0x622023, 0x4820001, +0x24840100, 0x8ee35234, 0x8ee2522c, 0x43102b, 0x14400004, 0x24020100, +0x8ee3522c, 0x8003cef, 0x431823, 0x8ee25234, 0x8ee3522c, 0x431023, 0x2443ffff, 0x804821, 0x69102a, 0x54400001, 0x604821, 0x8f870100, 0x27623000, 0x24e80020, 0x102102b, 0x50400001, 0x27682800, 0x8f820108, -0x15020007, 0x1021, 0x8ee201a4, 0x2021, 0x24420001, 0xaee201a4, -0x8003c14, 0x8ee201a4, 0x8ee40e04, 0x42140, 0x801821, 0x8ee40460, -0x8ee50464, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, -0xace50004, 0x8ee30e04, 0x91140, 0xa4e2000e, 0x24020002, 0xace20018, -0x31940, 0x24630e10, 0x2e31021, 0xace20008, 0x8ee20e04, 0xace2001c, -0x8ee204bc, 0xace20010, 0xaf880100, 0x92e204dc, 0x14400011, 0x24040001, -0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, -0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e21821, -0x24020002, 0xac620000, 0x24020001, 0xac620004, 0x1480000e, 0x24030040, -0x8ee20e04, 0xafa20010, 0x8ee20e08, 0x3c050007, 0xafa20014, 0x8ee60dfc, -0x8ee70e00, 0x3c040001, 0x24844a34, 0xc0023a7, 0x34a5f001, 0x8003c32, -0x0, 0x8ee204f0, 0x24420001, 0x50430003, 0x1021, 0x8ee204f0, -0x24420001, 0xaee204f0, 0x8ee204f0, 0x21080, 0x571021, 0xac4904f8, -0x8ee20e04, 0x491021, 0x304201ff, 0xaee20e04, 0x8ee30e04, 0x8ee20dfc, -0x14620005, 0x0, 0x8f820060, 0x2403fdff, 0x431024, 0xaf820060, -0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffe0, 0xafbf0018, 0x8ee3522c, -0x8ee25228, 0x10620071, 0x0, 0x8ee35228, 0x8ee2522c, 0x622023, -0x4820001, 0x24840100, 0x8ee35234, 0x8ee2522c, 0x43102b, 0x14400004, -0x24020100, 0x8ee3522c, 0x8003c54, 0x431823, 0x8ee25234, 0x8ee3522c, -0x431023, 0x2443ffff, 0x804821, 0x69102a, 0x54400001, 0x604821, -0x8f870100, 0x27623000, 0x24e80020, 0x102102b, 0x50400001, 0x27682800, -0x8f820108, 0x15020007, 0x1021, 0x8ee201a4, 0x2021, 0x24420001, -0xaee201a4, 0x8003c93, 0x8ee201a4, 0x8ee4522c, 0x42140, 0x801821, -0x8ee40470, 0x8ee50474, 0xa32821, 0xa3302b, 0x822021, 0x862021, -0xace40000, 0xace50004, 0x8ee3522c, 0x91140, 0xa4e2000e, 0x24020003, -0xace20018, 0x31940, 0x24635238, 0x2e31021, 0xace20008, 0x8ee2522c, -0xace2001c, 0x8ee204bc, 0xace20010, 0xaf880100, 0x92e204dc, 0x14400011, -0x24040001, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021, -0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, -0x2e21821, 0x24020003, 0xac620000, 0x24020001, 0xac620004, 0x1480000e, -0x24030040, 0x8ee2522c, 0xafa20010, 0x8ee25234, 0x3c050007, 0xafa20014, -0x8ee65228, 0x8ee75230, 0x3c040001, 0x24844a40, 0xc0023a7, 0x34a5f010, -0x8003cb1, 0x0, 0x8ee204f0, 0x24420001, 0x50430003, 0x1021, -0x8ee204f0, 0x24420001, 0xaee204f0, 0x8ee204f0, 0x21080, 0x571021, -0xac4904f8, 0x8ee2522c, 0x491021, 0x304200ff, 0xaee2522c, 0x8ee3522c, -0x8ee25228, 0x14620005, 0x0, 0x8f820060, 0x2403feff, 0x431024, -0xaf820060, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x8f820120, 0x8ee34e24, -0x8f820124, 0x8f860128, 0x24020040, 0x24630001, 0x50620003, 0x1021, -0x8ee24e24, 0x24420001, 0xaee24e24, 0x8ee24e24, 0x8ee44e24, 0x8ee34e20, -0x210c0, 0x24425028, 0x14830007, 0x2e22821, 0x8f820128, 0x24420020, -0xaf820128, 0x8f820128, 0x8003ce4, 0xaca00000, 0x8ee24e24, 0x24030040, -0x24420001, 0x50430003, 0x1021, 0x8ee24e24, 0x24420001, 0x210c0, -0x24425028, 0x2e22821, 0x8ca20004, 0x8f830128, 0x21140, 0x621821, -0xaf830128, 0xaca00000, 0x8cc20018, 0x2443fffe, 0x2c620012, 0x10400008, -0x31080, 0x3c010001, 0x220821, 0x8c224a50, 0x400008, 0x0, -0x24020001, 0xaee24e14, 0x3e00008, 0x0, 0x27bdffc8, 0xafbf0030, -0xafb5002c, 0xafb40028, 0xafb30024, 0xafb20020, 0xafb1001c, 0xafb00018, -0x8f830128, 0x8f820124, 0x106202a7, 0xa021, 0x3c11001f, 0x3631ffff, -0x3c12fff5, 0x36521000, 0x24150012, 0x24130040, 0x8f8c0128, 0x8f820128, -0x24420020, 0xaf820128, 0x9182001b, 0x8f830128, 0x2443fffe, 0x2c620012, -0x10400293, 0x31080, 0x3c010001, 0x220821, 0x8c224aa8, 0x400008, -0x0, 0x8f420218, 0x30420100, 0x10400007, 0x0, 0x95830016, -0x95820018, 0x621823, 0x31402, 0x431021, 0xa5820016, 0x8d82001c, -0x3c038000, 0x3044ffff, 0x436824, 0x3c030800, 0x431824, 0x11a00004, -0xad84001c, 0x41140, 0x8003d2a, 0x24425238, 0x41140, 0x24420e10, -0x2e25821, 0x9562000e, 0x3042fffc, 0x10600004, 0xa562000e, 0x95840016, -0x8003e12, 0x0, 0x8d690018, 0x4021, 0x952a0000, 0x25290002, -0x95270000, 0x25290002, 0x95260000, 0x25290002, 0x95250000, 0x25290002, -0x95240000, 0x25290002, 0x95230000, 0x25290002, 0x95220000, 0x25290002, -0x1475021, 0x1465021, 0x1455021, 0x1445021, 0x1435021, 0x1425021, -0xa1c02, 0x3142ffff, 0x625021, 0xa1c02, 0x3142ffff, 0x625021, -0x96e2046a, 0x314effff, 0x30420002, 0x10400044, 0x5021, 0x25220014, -0x222102b, 0x10400014, 0x1201821, 0x2405000a, 0x2021, 0x223102b, -0x54400001, 0x721821, 0x94620000, 0x24630002, 0x24a5ffff, 0x14a0fff9, -0x822021, 0x41c02, 0x3082ffff, 0x622021, 0x41402, 0x3083ffff, -0x431021, 0x3042ffff, 0x8003d85, 0x1425021, 0x952a0000, 0x25290002, -0x95280000, 0x25290002, 0x95270000, 0x25290002, 0x95260000, 0x25290002, -0x95250000, 0x25290002, 0x95230000, 0x25290002, 0x95220000, 0x25290002, -0x95240000, 0x25290002, 0x1485021, 0x1475021, 0x1465021, 0x1455021, -0x1435021, 0x1425021, 0x95220000, 0x95230002, 0x1445021, 0x1425021, -0x1435021, 0xa1c02, 0x3142ffff, 0x625021, 0xa1c02, 0x3142ffff, -0x625021, 0x3148ffff, 0x51000001, 0x3408ffff, 0x8d620018, 0x9443000c, -0x24020800, 0x54620005, 0xa5680010, 0x9562000e, 0x34420002, 0xa562000e, -0xa5680010, 0x96e2046a, 0x2821, 0x30420008, 0x14400056, 0x3021, -0x8d630018, 0x24620024, 0x222102b, 0x10400034, 0x24690010, 0x229102b, -0x54400001, 0x1324821, 0x95250000, 0x24690014, 0x229102b, 0x10400002, -0x24a5ffec, 0x1324821, 0x95220000, 0x30420fff, 0x14400003, 0x25290002, -0x8003db2, 0x24140001, 0xa021, 0xa03021, 0x229102b, 0x54400001, -0x1324821, 0x91220001, 0x25290002, 0xa22821, 0x229102b, 0x54400001, -0x1324821, 0x25290002, 0x229102b, 0x54400001, 0x1324821, 0x95220000, -0x25290002, 0xa22821, 0x229102b, 0x54400001, 0x1324821, 0x95220000, -0x25290002, 0xa22821, 0x229102b, 0x54400001, 0x1324821, 0x95220000, -0x25290002, 0xa22821, 0x229102b, 0x54400001, 0x1324821, 0x95220000, -0x8003deb, 0xa22821, 0x94650010, 0x94620014, 0x24690016, 0x30420fff, -0x14400003, 0x24a5ffec, 0x8003dde, 0x24140001, 0xa021, 0xa03021, -0x91230001, 0x25290004, 0x95220000, 0x25290002, 0x95240000, 0x25290002, -0xa32821, 0xa22821, 0x95220000, 0x95230002, 0xa42821, 0xa22821, -0xa32821, 0x51c02, 0x30a2ffff, 0x622821, 0x51c02, 0x30a2ffff, -0x622821, 0x96e2046a, 0x30420001, 0x1040001e, 0x2021, 0x95820016, -0x4e2023, 0x41402, 0x822021, 0x328200ff, 0x50400002, 0x862021, -0x852021, 0x41402, 0x822021, 0x3084ffff, 0x50800001, 0x3404ffff, -0x8d620018, 0x24430017, 0x223102b, 0x54400001, 0x721821, 0x90620000, -0x38430011, 0x2c630001, 0x38420006, 0x2c420001, 0x621825, 0x10600004, -0x0, 0x9562000e, 0x34420001, 0xa562000e, 0x9562000e, 0x240a0002, -0x30420004, 0x10400002, 0xa5640012, 0x240a0004, 0x8f880120, 0x27623800, -0x25090020, 0x122102b, 0x50400001, 0x27693000, 0x8f820128, 0x15220007, -0x24040020, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8003e9e, -0x8ee201a0, 0x8ee5723c, 0x8ee60480, 0x8ee70484, 0xad0b0008, 0xa504000e, -0xad0a0018, 0x52940, 0xa01821, 0x1021, 0xe33821, 0xe3202b, -0xc23021, 0xc43021, 0xad060000, 0xad070004, 0x8ee2723c, 0x4d1025, -0xad02001c, 0x8ee204b4, 0xad020010, 0xaf890120, 0x92e24e10, 0x14400060, -0x24100001, 0x2543ffee, 0x2c630002, 0x39420011, 0x2c420001, 0x621825, -0x10600024, 0x0, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, -0x8c820000, 0x1455000f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062000b, -0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, -0x24420001, 0x1053002b, 0x0, 0x8003e7d, 0x0, 0x8ee24e20, -0x24420001, 0x50530003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, -0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020001, 0x8003e9d, -0xac950000, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, -0x24020007, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, -0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, -0x24420001, 0x10530007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, -0x0, 0x8003e89, 0x0, 0x14600005, 0x0, 0x8f820128, -0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400012, -0xac800000, 0x8003e9e, 0x0, 0x8ee24e20, 0x24420001, 0x50530003, -0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, -0x24425028, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, -0x1600000d, 0x0, 0x8f820120, 0x3c040001, 0x24844a98, 0xafa00014, -0xafa20010, 0x8d86001c, 0x8f870124, 0x3c050008, 0xc0023a7, 0x34a50001, -0x8003fa0, 0x0, 0x8ee2723c, 0x24420001, 0x304203ff, 0x11a00006, -0xaee2723c, 0x8ee201c8, 0x2442ffff, 0xaee201c8, 0x8003eba, 0x8ee201c8, -0x8ee201c4, 0x2442ffff, 0xaee201c4, 0x8ee201c4, 0x8ee201cc, 0x2442ffff, -0xaee201cc, 0x8003fa0, 0x8ee201cc, 0x8f420240, 0x104000df, 0x0, -0x8ee20e0c, 0x24420001, 0x8003fa0, 0xaee20e0c, 0x9582001e, 0xad82001c, -0x8f420240, 0x1040006f, 0x0, 0x8ee20e0c, 0x24420001, 0xaee20e0c, -0x8f430240, 0x43102b, 0x144000cf, 0x0, 0x8f830120, 0x27623800, -0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, -0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8003f26, +0x11020004, 0x0, 0x8f820104, 0x15020007, 0x1021, 0x8ee201a4, +0x2021, 0x24420001, 0xaee201a4, 0x8003d31, 0x8ee201a4, 0x8ee4522c, +0x42140, 0x801821, 0x8ee40470, 0x8ee50474, 0xa32821, 0xa3302b, +0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee3522c, 0x91140, +0xa4e2000e, 0x24020003, 0xace20018, 0x31940, 0x24635238, 0x2e31021, +0xace20008, 0x8ee2522c, 0xace2001c, 0x8ee204bc, 0xace20010, 0xaf880100, +0x92e204dc, 0x14400011, 0x24040001, 0x8ee24e18, 0x24030040, 0x24420001, +0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, +0x210c0, 0x24424e28, 0x2e21821, 0x24020003, 0xac620000, 0x24020001, +0xac620004, 0x1480000e, 0x24030040, 0x8ee2522c, 0xafa20010, 0x8ee25234, +0x3c050007, 0xafa20014, 0x8ee65228, 0x8ee75230, 0x3c040001, 0x24844c50, +0xc002403, 0x34a5f010, 0x8003d4f, 0x0, 0x8ee204f0, 0x24420001, +0x50430003, 0x1021, 0x8ee204f0, 0x24420001, 0xaee204f0, 0x8ee204f0, +0x21080, 0x571021, 0xac4904f8, 0x8ee2522c, 0x491021, 0x304200ff, +0xaee2522c, 0x8ee3522c, 0x8ee25228, 0x14620005, 0x0, 0x8f820060, +0x2403feff, 0x431024, 0xaf820060, 0x8fbf0018, 0x3e00008, 0x27bd0020, +0x8f820120, 0x8ee34e24, 0x8f820124, 0x8f860128, 0x24020040, 0x24630001, +0x50620003, 0x1021, 0x8ee24e24, 0x24420001, 0xaee24e24, 0x8ee24e24, +0x8ee44e24, 0x8ee34e20, 0x210c0, 0x24425028, 0x14830007, 0x2e22821, +0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8003d82, 0xaca00000, +0x8ee24e24, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e24, +0x24420001, 0x210c0, 0x24425028, 0x2e22821, 0x8ca20004, 0x8f830128, +0x21140, 0x621821, 0xaf830128, 0xaca00000, 0x8cc20018, 0x2443fffe, +0x2c620012, 0x10400008, 0x31080, 0x3c010001, 0x220821, 0x8c224c60, +0x400008, 0x0, 0x24020001, 0xaee24e14, 0x3e00008, 0x0, +0x27bdffc8, 0xafbf0030, 0xafb5002c, 0xafb40028, 0xafb30024, 0xafb20020, +0xafb1001c, 0xafb00018, 0x8f830128, 0x8f820124, 0x106202b0, 0x9821, +0x3c11001f, 0x3631ffff, 0x3c12fff5, 0x36521000, 0x24150012, 0x24140040, +0x8f8c0128, 0x8f820128, 0x24420020, 0xaf820128, 0x9182001b, 0x8f830128, +0x2443fffe, 0x2c620012, 0x1040029c, 0x31080, 0x3c010001, 0x220821, +0x8c224cb8, 0x400008, 0x0, 0x8f420218, 0x30420100, 0x10400007, +0x0, 0x95830016, 0x95820018, 0x621823, 0x31402, 0x431021, +0xa5820016, 0x8d82001c, 0x3c038000, 0x3044ffff, 0x436824, 0x3c030800, +0x431824, 0x11a00004, 0xad84001c, 0x41140, 0x8003dc8, 0x24425238, +0x41140, 0x24420e10, 0x2e25821, 0x9562000e, 0x3042fffc, 0x10600004, +0xa562000e, 0x95840016, 0x8003eb0, 0x0, 0x8d690018, 0x4021, +0x952a0000, 0x25290002, 0x95270000, 0x25290002, 0x95260000, 0x25290002, +0x95250000, 0x25290002, 0x95240000, 0x25290002, 0x95230000, 0x25290002, +0x95220000, 0x25290002, 0x1475021, 0x1465021, 0x1455021, 0x1445021, +0x1435021, 0x1425021, 0xa1c02, 0x3142ffff, 0x625021, 0xa1c02, +0x3142ffff, 0x625021, 0x96e2046a, 0x314effff, 0x30420002, 0x10400044, +0x5021, 0x25220014, 0x222102b, 0x10400014, 0x1201821, 0x2405000a, +0x2021, 0x223102b, 0x54400001, 0x721821, 0x94620000, 0x24630002, +0x24a5ffff, 0x14a0fff9, 0x822021, 0x41c02, 0x3082ffff, 0x622021, +0x41402, 0x3083ffff, 0x431021, 0x3042ffff, 0x8003e23, 0x1425021, +0x952a0000, 0x25290002, 0x95280000, 0x25290002, 0x95270000, 0x25290002, +0x95260000, 0x25290002, 0x95250000, 0x25290002, 0x95230000, 0x25290002, +0x95220000, 0x25290002, 0x95240000, 0x25290002, 0x1485021, 0x1475021, +0x1465021, 0x1455021, 0x1435021, 0x1425021, 0x95220000, 0x95230002, +0x1445021, 0x1425021, 0x1435021, 0xa1c02, 0x3142ffff, 0x625021, +0xa1c02, 0x3142ffff, 0x625021, 0x3148ffff, 0x51000001, 0x3408ffff, +0x8d620018, 0x9443000c, 0x24020800, 0x54620005, 0xa5680010, 0x9562000e, +0x34420002, 0xa562000e, 0xa5680010, 0x96e2046a, 0x2821, 0x30420008, +0x14400056, 0x3021, 0x8d630018, 0x24620024, 0x222102b, 0x10400034, +0x24690010, 0x229102b, 0x54400001, 0x1324821, 0x95250000, 0x24690014, +0x229102b, 0x10400002, 0x24a5ffec, 0x1324821, 0x95220000, 0x30420fff, +0x14400003, 0x25290002, 0x8003e50, 0x24130001, 0x9821, 0xa03021, +0x229102b, 0x54400001, 0x1324821, 0x91220001, 0x25290002, 0xa22821, +0x229102b, 0x54400001, 0x1324821, 0x25290002, 0x229102b, 0x54400001, +0x1324821, 0x95220000, 0x25290002, 0xa22821, 0x229102b, 0x54400001, +0x1324821, 0x95220000, 0x25290002, 0xa22821, 0x229102b, 0x54400001, +0x1324821, 0x95220000, 0x25290002, 0xa22821, 0x229102b, 0x54400001, +0x1324821, 0x95220000, 0x8003e89, 0xa22821, 0x94650010, 0x94620014, +0x24690016, 0x30420fff, 0x14400003, 0x24a5ffec, 0x8003e7c, 0x24130001, +0x9821, 0xa03021, 0x91230001, 0x25290004, 0x95220000, 0x25290002, +0x95240000, 0x25290002, 0xa32821, 0xa22821, 0x95220000, 0x95230002, +0xa42821, 0xa22821, 0xa32821, 0x51c02, 0x30a2ffff, 0x622821, +0x51c02, 0x30a2ffff, 0x622821, 0x96e2046a, 0x30420001, 0x1040001e, +0x2021, 0x95820016, 0x4e2023, 0x41402, 0x822021, 0x326200ff, +0x50400002, 0x862021, 0x852021, 0x41402, 0x822021, 0x3084ffff, +0x50800001, 0x3404ffff, 0x8d620018, 0x24430017, 0x223102b, 0x54400001, +0x721821, 0x90620000, 0x38430011, 0x2c630001, 0x38420006, 0x2c420001, +0x621825, 0x10600004, 0x0, 0x9562000e, 0x34420001, 0xa562000e, +0x9562000e, 0x240a0002, 0x30420004, 0x10400002, 0xa5640012, 0x240a0004, +0x8f880120, 0x27623800, 0x25090020, 0x122102b, 0x50400001, 0x27693000, +0x8f820128, 0x11220004, 0x0, 0x8f820124, 0x15220007, 0x24040020, +0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8003f3f, 0x8ee201a0, +0x8ee5723c, 0x8ee60480, 0x8ee70484, 0xad0b0008, 0xa504000e, 0xad0a0018, +0x52940, 0xa01821, 0x1021, 0xe33821, 0xe3202b, 0xc23021, +0xc43021, 0xad060000, 0xad070004, 0x8ee2723c, 0x4d1025, 0xad02001c, +0x8ee204b4, 0xad020010, 0xaf890120, 0x92e24e10, 0x14400060, 0x24100001, +0x2543ffee, 0x2c630002, 0x39420011, 0x2c420001, 0x621825, 0x10600024, +0x0, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, +0x1455000f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062000b, 0x0, +0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, +0x1054002b, 0x0, 0x8003f1e, 0x0, 0x8ee24e20, 0x24420001, +0x50540003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, +0x210c0, 0x24425028, 0x2e22021, 0x24020001, 0x8003f3e, 0xac950000, +0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007, +0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, +0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, +0x10540007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, +0x8003f2a, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, +0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400012, 0xac800000, +0x8003f3f, 0x0, 0x8ee24e20, 0x24420001, 0x50540003, 0x1021, +0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, +0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x1600000d, +0x0, 0x8f820120, 0x3c040001, 0x24844ca8, 0xafa00014, 0xafa20010, +0x8d86001c, 0x8f870124, 0x3c050008, 0xc002403, 0x34a50001, 0x8004047, +0x0, 0x8ee2723c, 0x24420001, 0x304203ff, 0x11a00006, 0xaee2723c, +0x8ee201c8, 0x2442ffff, 0xaee201c8, 0x8003f5b, 0x8ee201c8, 0x8ee201c4, +0x2442ffff, 0xaee201c4, 0x8ee201c4, 0x8ee201cc, 0x2442ffff, 0xaee201cc, +0x8004047, 0x8ee201cc, 0x8f420240, 0x104000e5, 0x0, 0x8ee20e0c, +0x24420001, 0x8004047, 0xaee20e0c, 0x9582001e, 0xad82001c, 0x8f420240, +0x10400072, 0x0, 0x8ee20e0c, 0x24420001, 0xaee20e0c, 0x8f430240, +0x43102b, 0x144000d5, 0x0, 0x8f830120, 0x27623800, 0x24660020, +0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, +0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x8021, 0x24420001, +0xaee201a0, 0x8003fca, 0x8ee201a0, 0x8ee2723c, 0xac62001c, 0x8ee40498, +0x8ee5049c, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, +0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, +0x92e24e10, 0x14400034, 0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, +0x2e22021, 0x8c820000, 0x1455001f, 0x0, 0x8ee34e20, 0x8ee24e24, +0x1062001b, 0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, +0x8ee34e20, 0x24420001, 0x10540007, 0x0, 0x8ee24e24, 0x24420001, +0x10620005, 0x0, 0x8003fb6, 0x0, 0x14600005, 0x0, +0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, +0x50400011, 0xac800000, 0x8003fca, 0x0, 0x8ee24e20, 0x24420001, +0x50540003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, +0x210c0, 0x24425028, 0x2e22021, 0x24020001, 0xac950000, 0xac820004, +0x5600000b, 0x24100001, 0x8ee2723c, 0x3c040001, 0x24844c18, 0xafa00014, +0xafa20010, 0x8ee6723c, 0x8f470280, 0x3c050009, 0xc002403, 0x34a5f008, +0x56000001, 0xaee00e0c, 0x8ee20184, 0x24420001, 0xaee20184, 0x8004040, +0x8ee20184, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, +0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124, 0x14c20007, +0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8004034, 0x8ee201a0, 0x8ee2723c, 0xac62001c, 0x8ee40498, 0x8ee5049c, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400034, 0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x1455001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, -0x10530007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, -0x8003f12, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, +0x10540007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, +0x8004020, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400011, 0xac800000, -0x8003f26, 0x0, 0x8ee24e20, 0x24420001, 0x50530003, 0x1021, +0x8004034, 0x0, 0x8ee24e20, 0x24420001, 0x50540003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, -0x2e22021, 0x24020001, 0xac950000, 0xac820004, 0x5600000b, 0x24100001, -0x8ee2723c, 0x3c040001, 0x24844a08, 0xafa00014, 0xafa20010, 0x8ee6723c, -0x8f470280, 0x3c050009, 0xc0023a7, 0x34a5f008, 0x56000001, 0xaee00e0c, -0x8ee20184, 0x24420001, 0xaee20184, 0x8003f99, 0x8ee20184, 0x8f830120, -0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, -0x14c20007, 0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, -0x8003f8d, 0x8ee201a0, 0x8ee2723c, 0xac62001c, 0x8ee40498, 0x8ee5049c, -0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, 0xac620018, -0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, -0x14400034, 0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, -0x8c820000, 0x1455001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, -0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, -0x24420001, 0x10530007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, -0x0, 0x8003f79, 0x0, 0x14600005, 0x0, 0x8f820128, -0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400011, -0xac800000, 0x8003f8d, 0x0, 0x8ee24e20, 0x24420001, 0x50530003, -0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, -0x24425028, 0x2e22021, 0x24020001, 0xac950000, 0xac820004, 0x1600000b, -0x0, 0x8ee2723c, 0x3c040001, 0x24844a08, 0xafa00014, 0xafa20010, -0x8ee6723c, 0x8f470280, 0x3c050009, 0xc0023a7, 0x34a5f008, 0x8ee20170, -0x24420001, 0xaee20170, 0x8003fa0, 0x8ee20170, 0x24020001, 0xaee24e14, -0x8f830128, 0x8f820124, 0x1462fd61, 0x0, 0x8fbf0030, 0x8fb5002c, -0x8fb40028, 0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008, -0x27bd0038, 0x0, 0x0, 0x0, 0x27bdffe8, 0x27840208, -0x27450200, 0x24060008, 0xafbf0014, 0xc00243e, 0xafb00010, 0x24040001, -0x24100001, 0x2402241f, 0xaf900210, 0xaf900200, 0xaf800204, 0xaf820214, -0x8f460248, 0x24030004, 0x3c020040, 0x3c010001, 0xac234de8, 0x3c010001, -0xac234dec, 0x3c010001, 0xac204e8c, 0x3c010001, 0xac224de4, 0x3c010001, -0xac234dec, 0xc004e2c, 0x24050004, 0xc0046b4, 0x0, 0x8ee20000, -0x3c03feff, 0x3463fffd, 0x431024, 0xaee20000, 0x3c023c00, 0xaf82021c, -0x3c010001, 0x370821, 0xac30839c, 0x8fbf0014, 0x8fb00010, 0x3e00008, -0x27bd0018, 0x27bdffe0, 0x3c050008, 0x34a50400, 0xafbf0018, 0xafa00010, -0xafa00014, 0x8f860200, 0x3c040001, 0x24844b50, 0xc0023a7, 0x3821, -0x8ee20270, 0x24420001, 0xaee20270, 0x8ee20270, 0x8f830200, 0x3c023f00, -0x621824, 0x8fbf0018, 0x3c020400, 0x3e00008, 0x27bd0020, 0x27bdffd8, -0xafbf0020, 0xafb1001c, 0xafb00018, 0x8f900220, 0x8ee20204, 0x3821, -0x24420001, 0xaee20204, 0x8ee20204, 0x3c020300, 0x2021024, 0x10400027, -0x3c110400, 0xc0041e7, 0x0, 0x3c020100, 0x2021024, 0x10400007, -0x0, 0x8ee20208, 0x24420001, 0xaee20208, 0x8ee20208, 0x8004012, -0x3c03fdff, 0x8ee2020c, 0x24420001, 0xaee2020c, 0x8ee2020c, 0x3c03fdff, -0x3463ffff, 0x3c0808ff, 0x3508ffff, 0x8ee20000, 0x3c040001, 0x24844b5c, -0x3c050008, 0x2003021, 0x431024, 0xaee20000, 0x8f820220, 0x3821, -0x3c030300, 0x481024, 0x431025, 0xaf820220, 0xafa00010, 0xc0023a7, -0xafa00014, 0x80041e2, 0x0, 0x2111024, 0x1040001f, 0x3c024000, -0x8f830224, 0x24021402, 0x1462000b, 0x3c03fdff, 0x3c040001, 0x24844b68, -0x3c050008, 0xafa00010, 0xafa00014, 0x8f860224, 0x34a5ffff, 0xc0023a7, -0x3821, 0x3c03fdff, 0x8ee20000, 0x3463ffff, 0x2002021, 0x431024, -0xc004b88, 0xaee20000, 0x8ee20210, 0x24420001, 0xaee20210, 0x8ee20210, -0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x80041e1, 0x511025, -0x2021024, 0x10400142, 0x0, 0x8ee2021c, 0x24420001, 0xaee2021c, -0x8ee2021c, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420004, -0xaf820220, 0x8f830054, 0x8f820054, 0x800405a, 0x24630002, 0x8f820054, -0x621023, 0x2c420003, 0x1440fffc, 0x0, 0x8f8600e0, 0x8f8400e4, +0x2e22021, 0x24020001, 0xac950000, 0xac820004, 0x1600000b, 0x0, +0x8ee2723c, 0x3c040001, 0x24844c18, 0xafa00014, 0xafa20010, 0x8ee6723c, +0x8f470280, 0x3c050009, 0xc002403, 0x34a5f008, 0x8ee20170, 0x24420001, +0xaee20170, 0x8004047, 0x8ee20170, 0x24020001, 0xaee24e14, 0x8f830128, +0x8f820124, 0x1462fd58, 0x0, 0x8fbf0030, 0x8fb5002c, 0x8fb40028, +0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0038, +0x27bdffe8, 0x27840208, 0x27450200, 0x24060008, 0xafbf0014, 0xc00249a, +0xafb00010, 0x24040001, 0x24100001, 0x2402241f, 0xaf900210, 0xaf900200, +0xaf800204, 0xaf820214, 0x8f460248, 0x24030004, 0x3c020040, 0x3c010001, +0xac234ff8, 0x3c010001, 0xac234ffc, 0x3c010001, 0xac20509c, 0x3c010001, +0xac224ff4, 0x3c010001, 0xac234ffc, 0xc004eac, 0x24050004, 0xc004734, +0x0, 0x8ee20000, 0x3c03feff, 0x3463fffd, 0x431024, 0xaee20000, +0x3c023c00, 0xaf82021c, 0x3c010001, 0x370821, 0xac30839c, 0x8fbf0014, +0x8fb00010, 0x3e00008, 0x27bd0018, 0x27bdffe0, 0x3c050008, 0x34a50400, +0xafbf0018, 0xafa00010, 0xafa00014, 0x8f860200, 0x3c040001, 0x24844d60, +0xc002403, 0x3821, 0x8ee20270, 0x24420001, 0xaee20270, 0x8ee20270, +0x8f830200, 0x3c023f00, 0x621824, 0x8fbf0018, 0x3c020400, 0x3e00008, +0x27bd0020, 0x27bdffd8, 0xafbf0020, 0xafb1001c, 0xafb00018, 0x8f900220, +0x8ee20204, 0x3821, 0x24420001, 0xaee20204, 0x8ee20204, 0x3c020300, +0x2021024, 0x10400027, 0x3c110400, 0xc00428b, 0x0, 0x3c020100, +0x2021024, 0x10400007, 0x0, 0x8ee20208, 0x24420001, 0xaee20208, +0x8ee20208, 0x80040b6, 0x3c03fdff, 0x8ee2020c, 0x24420001, 0xaee2020c, +0x8ee2020c, 0x3c03fdff, 0x3463ffff, 0x3c0808ff, 0x3508ffff, 0x8ee20000, +0x3c040001, 0x24844d6c, 0x3c050008, 0x2003021, 0x431024, 0xaee20000, +0x8f820220, 0x3821, 0x3c030300, 0x481024, 0x431025, 0xaf820220, +0xafa00010, 0xc002403, 0xafa00014, 0x8004286, 0x0, 0x2111024, +0x1040001f, 0x3c024000, 0x8f830224, 0x24021402, 0x1462000b, 0x3c03fdff, +0x3c040001, 0x24844d78, 0x3c050008, 0xafa00010, 0xafa00014, 0x8f860224, +0x34a5ffff, 0xc002403, 0x3821, 0x3c03fdff, 0x8ee20000, 0x3463ffff, +0x2002021, 0x431024, 0xc004c08, 0xaee20000, 0x8ee20210, 0x24420001, +0xaee20210, 0x8ee20210, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, +0x8004285, 0x511025, 0x2021024, 0x10400142, 0x0, 0x8ee2021c, +0x24420001, 0xaee2021c, 0x8ee2021c, 0x8f820220, 0x3c0308ff, 0x3463ffff, +0x431024, 0x34420004, 0xaf820220, 0x8f830054, 0x8f820054, 0x80040fe, +0x24630002, 0x8f820054, 0x621023, 0x2c420003, 0x1440fffc, 0x0, +0x8f8600e0, 0x8f8400e4, 0x30c20007, 0x10400012, 0x0, 0x8f8300e4, +0x2402fff8, 0xc21024, 0x1043000d, 0x0, 0x8f820054, 0x8f8300e0, +0x14c30009, 0x24440050, 0x8f820054, 0x821023, 0x2c420051, 0x10400004, +0x0, 0x8f8200e0, 0x10c2fff9, 0x0, 0x8f820220, 0x3c0308ff, +0x3463fffd, 0x431024, 0xaf820220, 0x8f8600e0, 0x30c20007, 0x10400003, +0x2402fff8, 0xc23024, 0xaf8600e0, 0x8f8300c4, 0x3c02001f, 0x3442ffff, +0x24680008, 0x48102b, 0x10400003, 0x3c02fff5, 0x34421000, 0x1024021, +0x8f8b00c8, 0x8f850120, 0x8f840124, 0x8004135, 0x6021, 0x27623800, +0x82102b, 0x50400001, 0x27643000, 0x10a40010, 0x318200ff, 0x8c820018, +0x38430007, 0x2c630001, 0x3842000b, 0x2c420001, 0x621825, 0x5060fff3, +0x24840020, 0x8ee20230, 0x240c0001, 0x24420001, 0xaee20230, 0x8ee20230, +0x8c8b0008, 0x318200ff, 0x14400065, 0x0, 0x3c020001, 0x571021, +0x904283b0, 0x14400060, 0x0, 0x8f8400e4, 0xc41023, 0x218c3, +0x4620001, 0x24630200, 0x8f8900c4, 0x10600005, 0x24020001, 0x10620009, +0x0, 0x8004177, 0x0, 0x8ee20220, 0x1205821, 0x24420001, +0xaee20220, 0x80041ac, 0x8ee20220, 0x8ee20224, 0x3c05000a, 0x24420001, +0xaee20224, 0x8c8b0000, 0x34a5f000, 0x8ee20224, 0x12b1823, 0xa3102b, +0x54400001, 0x651821, 0x2c62233f, 0x14400040, 0x0, 0x8f8200e8, +0x24420008, 0xaf8200e8, 0x8f8200e8, 0x8f8200e4, 0x1205821, 0x24420008, +0xaf8200e4, 0x80041ac, 0x8f8200e4, 0x8ee20228, 0x3c03000a, 0x24420001, +0xaee20228, 0x8c840000, 0x3463f000, 0x8ee20228, 0x883823, 0x67102b, +0x54400001, 0xe33821, 0x3c020003, 0x34420d40, 0x47102b, 0x10400003, +0x0, 0x80041ac, 0x805821, 0x8f8200e4, 0x24440008, 0xaf8400e4, +0x8f8400e4, 0x10860018, 0x3c05000a, 0x34a5f000, 0x3c0a0003, 0x354a0d40, +0x8ee2007c, 0x24420001, 0xaee2007c, 0x8c830000, 0x8ee2007c, 0x683823, +0xa7102b, 0x54400001, 0xe53821, 0x147102b, 0x54400007, 0x605821, +0x8f8200e4, 0x24440008, 0xaf8400e4, 0x8f8400e4, 0x1486ffef, 0x0, +0x14860005, 0x0, 0x1205821, 0xaf8600e4, 0x80041ac, 0xaf8600e8, +0xaf8400e4, 0xaf8400e8, 0x8f8200c8, 0x3c03000a, 0x3463f000, 0x483823, +0x67102b, 0x54400001, 0xe33821, 0x3c020003, 0x34420d3f, 0x47102b, +0x54400007, 0x6021, 0x1683823, 0x67102b, 0x54400003, 0xe33821, +0x80041bf, 0x3c020003, 0x3c020003, 0x34420d3f, 0x47102b, 0x14400016, +0x318200ff, 0x14400006, 0x0, 0x3c020001, 0x571021, 0x904283b0, +0x1040000f, 0x0, 0x8ee2022c, 0x3c04fdff, 0x8ee30000, 0x3484ffff, +0x24420001, 0xaee2022c, 0x8ee2022c, 0x24020001, 0x641824, 0x3c010001, +0x370821, 0xa02283a8, 0x800421c, 0xaee30000, 0xaf8b00c8, 0x8f8300c8, +0x8f8200c4, 0x3c04000a, 0x3484f000, 0x623823, 0x87102b, 0x54400001, +0xe43821, 0x3c020003, 0x34420d40, 0x47102b, 0x2ce30001, 0x431025, +0x10400008, 0x0, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, +0x3c034000, 0x431025, 0xaf820220, 0x8f8600e0, 0x8f8400e4, 0x10c4002a, +0x0, 0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x24c2fff8, +0xaf8200e0, 0x3c020001, 0x8c427140, 0x3c030008, 0x8f8600e0, 0x431024, +0x1040001d, 0x0, 0x10c4001b, 0x240dfff8, 0x3c0a000a, 0x354af000, +0x3c0c0080, 0x24850008, 0x27622800, 0x50a20001, 0x27651800, 0x8c880004, +0x8c820000, 0x8ca90000, 0x3103ffff, 0x431021, 0x4d1024, 0x24430010, +0x6b102b, 0x54400001, 0x6a1821, 0x12b102b, 0x54400001, 0x12a4821, +0x10690002, 0x10c1025, 0xac820004, 0xa02021, 0x14c4ffeb, 0x24850008, +0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420002, 0xaf820220, +0x8f830054, 0x8f820054, 0x8004227, 0x24630001, 0x8f820054, 0x621023, +0x2c420002, 0x1440fffc, 0x0, 0x8f820220, 0x3c0308ff, 0x3463fffb, +0x431024, 0xaf820220, 0x6010055, 0x0, 0x8ee20218, 0x24420001, +0xaee20218, 0x8ee20218, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, +0x34420004, 0xaf820220, 0x8f830054, 0x8f820054, 0x8004241, 0x24630002, +0x8f820054, 0x621023, 0x2c420003, 0x1440fffc, 0x0, 0x8f8600e0, 0x30c20007, 0x10400012, 0x0, 0x8f8300e4, 0x2402fff8, 0xc21024, -0x1043000d, 0x0, 0x8f820054, 0x8f8300e0, 0x14c30009, 0x24440050, -0x8f820054, 0x821023, 0x2c420051, 0x10400004, 0x0, 0x8f8200e0, +0x1043000d, 0x0, 0x8f820054, 0x8f8300e0, 0x14c30009, 0x24440032, +0x8f820054, 0x821023, 0x2c420033, 0x10400004, 0x0, 0x8f8200e0, 0x10c2fff9, 0x0, 0x8f820220, 0x3c0308ff, 0x3463fffd, 0x431024, 0xaf820220, 0x8f8600e0, 0x30c20007, 0x10400003, 0x2402fff8, 0xc23024, -0xaf8600e0, 0x8f8300c4, 0x3c02001f, 0x3442ffff, 0x24680008, 0x48102b, -0x10400003, 0x3c02fff5, 0x34421000, 0x1024021, 0x8f8b00c8, 0x8f850120, -0x8f840124, 0x8004091, 0x6021, 0x27623800, 0x82102b, 0x50400001, -0x27643000, 0x10a40010, 0x318200ff, 0x8c820018, 0x38430007, 0x2c630001, -0x3842000b, 0x2c420001, 0x621825, 0x5060fff3, 0x24840020, 0x8ee20230, -0x240c0001, 0x24420001, 0xaee20230, 0x8ee20230, 0x8c8b0008, 0x318200ff, -0x14400065, 0x0, 0x3c020001, 0x571021, 0x904283b0, 0x14400060, -0x0, 0x8f8400e4, 0xc41023, 0x218c3, 0x4620001, 0x24630200, -0x8f8900c4, 0x10600005, 0x24020001, 0x10620009, 0x0, 0x80040d3, -0x0, 0x8ee20220, 0x1205821, 0x24420001, 0xaee20220, 0x8004108, -0x8ee20220, 0x8ee20224, 0x3c05000a, 0x24420001, 0xaee20224, 0x8c8b0000, -0x34a5f000, 0x8ee20224, 0x12b1823, 0xa3102b, 0x54400001, 0x651821, -0x2c62233f, 0x14400040, 0x0, 0x8f8200e8, 0x24420008, 0xaf8200e8, -0x8f8200e8, 0x8f8200e4, 0x1205821, 0x24420008, 0xaf8200e4, 0x8004108, -0x8f8200e4, 0x8ee20228, 0x3c03000a, 0x24420001, 0xaee20228, 0x8c840000, -0x3463f000, 0x8ee20228, 0x883823, 0x67102b, 0x54400001, 0xe33821, -0x3c020003, 0x34420d40, 0x47102b, 0x10400003, 0x0, 0x8004108, -0x805821, 0x8f8200e4, 0x24440008, 0xaf8400e4, 0x8f8400e4, 0x10860018, -0x3c05000a, 0x34a5f000, 0x3c0a0003, 0x354a0d40, 0x8ee2007c, 0x24420001, -0xaee2007c, 0x8c830000, 0x8ee2007c, 0x683823, 0xa7102b, 0x54400001, -0xe53821, 0x147102b, 0x54400007, 0x605821, 0x8f8200e4, 0x24440008, -0xaf8400e4, 0x8f8400e4, 0x1486ffef, 0x0, 0x14860005, 0x0, -0x1205821, 0xaf8600e4, 0x8004108, 0xaf8600e8, 0xaf8400e4, 0xaf8400e8, -0x8f8200c8, 0x3c03000a, 0x3463f000, 0x483823, 0x67102b, 0x54400001, -0xe33821, 0x3c020003, 0x34420d3f, 0x47102b, 0x54400007, 0x6021, -0x1683823, 0x67102b, 0x54400003, 0xe33821, 0x800411b, 0x3c020003, -0x3c020003, 0x34420d3f, 0x47102b, 0x14400016, 0x318200ff, 0x14400006, -0x0, 0x3c020001, 0x571021, 0x904283b0, 0x1040000f, 0x0, -0x8ee2022c, 0x3c04fdff, 0x8ee30000, 0x3484ffff, 0x24420001, 0xaee2022c, -0x8ee2022c, 0x24020001, 0x641824, 0x3c010001, 0x370821, 0xa02283a8, -0x8004178, 0xaee30000, 0xaf8b00c8, 0x8f8300c8, 0x8f8200c4, 0x3c04000a, -0x3484f000, 0x623823, 0x87102b, 0x54400001, 0xe43821, 0x3c020003, -0x34420d40, 0x47102b, 0x2ce30001, 0x431025, 0x10400008, 0x0, -0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x3c034000, 0x431025, -0xaf820220, 0x8f8600e0, 0x8f8400e4, 0x10c4002a, 0x0, 0x8ee2007c, -0x24420001, 0xaee2007c, 0x8ee2007c, 0x24c2fff8, 0xaf8200e0, 0x3c020001, -0x8c426f30, 0x3c030008, 0x8f8600e0, 0x431024, 0x1040001d, 0x0, -0x10c4001b, 0x240dfff8, 0x3c0a000a, 0x354af000, 0x3c0c0080, 0x24850008, -0x27622800, 0x50a20001, 0x27651800, 0x8c880004, 0x8c820000, 0x8ca90000, -0x3103ffff, 0x431021, 0x4d1024, 0x24430010, 0x6b102b, 0x54400001, -0x6a1821, 0x12b102b, 0x54400001, 0x12a4821, 0x10690002, 0x10c1025, -0xac820004, 0xa02021, 0x14c4ffeb, 0x24850008, 0x8f820220, 0x3c0308ff, -0x3463ffff, 0x431024, 0x34420002, 0xaf820220, 0x8f830054, 0x8f820054, -0x8004183, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, -0x0, 0x8f820220, 0x3c0308ff, 0x3463fffb, 0x431024, 0xaf820220, -0x6010055, 0x0, 0x8ee20218, 0x24420001, 0xaee20218, 0x8ee20218, -0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420004, 0xaf820220, -0x8f830054, 0x8f820054, 0x800419d, 0x24630002, 0x8f820054, 0x621023, -0x2c420003, 0x1440fffc, 0x0, 0x8f8600e0, 0x30c20007, 0x10400012, -0x0, 0x8f8300e4, 0x2402fff8, 0xc21024, 0x1043000d, 0x0, -0x8f820054, 0x8f8300e0, 0x14c30009, 0x24440032, 0x8f820054, 0x821023, -0x2c420033, 0x10400004, 0x0, 0x8f8200e0, 0x10c2fff9, 0x0, -0x8f820220, 0x3c0308ff, 0x3463fffd, 0x431024, 0xaf820220, 0x8f8600e0, -0x30c20007, 0x10400003, 0x2402fff8, 0xc23024, 0xaf8600e0, 0x240301f5, -0x8f8200e8, 0x673823, 0x718c0, 0x431021, 0xaf8200e8, 0x8f8200e8, -0xaf8200e4, 0x8ee2007c, 0x3c0408ff, 0x3484ffff, 0x471021, 0xaee2007c, -0x8f820220, 0x3c038000, 0x34630002, 0x441024, 0x431025, 0xaf820220, -0x8f830054, 0x8f820054, 0x80041d9, 0x24630001, 0x8f820054, 0x621023, -0x2c420002, 0x1440fffc, 0x0, 0x8f820220, 0x3c0308ff, 0x3463fffb, -0x431024, 0xaf820220, 0x8fbf0020, 0x8fb1001c, 0x8fb00018, 0x3e00008, -0x27bd0028, 0x3c020001, 0x8c424dfc, 0x27bdffd8, 0x10400012, 0xafbf0020, -0x3c040001, 0x24844b74, 0x3c050008, 0x24020001, 0x3c010001, 0x370821, -0xac22839c, 0xafa00010, 0xafa00014, 0x8f860220, 0x34a50498, 0x3c010001, -0xac204dfc, 0x3c010001, 0xac224df0, 0xc0023a7, 0x3821, 0x8f420268, -0x3c037fff, 0x3463ffff, 0x431024, 0xaf420268, 0x8ee204c0, 0x8ee404c4, -0x2403fffe, 0x431024, 0x30840002, 0x10800118, 0xaee204c0, 0x8ee204c4, -0x2403fffd, 0x431024, 0xaee204c4, 0x8f820044, 0x3c030600, 0x34632000, -0x34420020, 0xaf820044, 0xafa30018, 0x8ee205f8, 0x8f430228, 0x24420001, -0x304a00ff, 0x514300f8, 0xafa00010, 0x8ee205f8, 0x210c0, 0x571021, -0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f830054, 0x8f820054, -0x24690032, 0x1221023, 0x2c420033, 0x10400067, 0x5821, 0x24180008, -0x240f000d, 0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120, 0x27623800, -0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128, 0x15020007, -0x1021, 0x8ee201a0, 0x2821, 0x24420001, 0xaee201a0, 0x8004286, -0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, -0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, -0x8ee205f8, 0xa4f8000e, 0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, -0x2e21021, 0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, -0x14400033, 0x24050001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, -0x8c820000, 0x144d001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, -0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, -0x24420001, 0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, -0x0, 0x8004273, 0x0, 0x14600005, 0x0, 0x8f820128, -0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, -0xac800000, 0x8004286, 0x0, 0x8ee24e20, 0x24420001, 0x504c0003, -0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, -0x24425028, 0x2e22021, 0xac8d0000, 0xac8e0004, 0x54a00006, 0x240b0001, -0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa0, 0x0, 0x316300ff, -0x24020001, 0x54620076, 0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054, -0x24690032, 0x1221023, 0x2c420033, 0x1040005e, 0x5821, 0x240d0008, -0x240c0011, 0x24080012, 0x24070040, 0x240a0001, 0x8f830120, 0x27623800, -0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, -0x0, 0x8ee201a0, 0x2821, 0x24420001, 0xaee201a0, 0x80042ef, -0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494, 0x2462001c, -0xac620008, 0xa46d000e, 0xac6c0018, 0xac640000, 0xac650004, 0x8ee204b4, -0xac620010, 0xaf860120, 0x92e24e10, 0x14400033, 0x24050001, 0x8ee24e20, -0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x1448001f, 0x0, -0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001, -0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10470007, 0x0, -0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x80042dc, 0x0, -0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, -0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x80042ef, 0x0, -0x8ee24e20, 0x24420001, 0x50470003, 0x1021, 0x8ee24e20, 0x24420001, -0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0xac880000, -0xac8a0004, 0x54a00006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, -0x1440ffa9, 0x0, 0x316300ff, 0x24020001, 0x54620003, 0xafa00010, -0x800431c, 0x0, 0x3c040001, 0x24844b80, 0xafa00014, 0x8f860120, -0x8f870124, 0x3c050009, 0xc0023a7, 0x34a5f011, 0x800431c, 0x0, -0x3c040001, 0x24844b8c, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, -0xc0023a7, 0x34a5f010, 0x800431c, 0x0, 0x3c040001, 0x24844b98, -0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f00f, -0x8ee201a8, 0x24420001, 0xaee201a8, 0x8ee201a8, 0x8ee20158, 0x24420001, -0xaee20158, 0x8ee20158, 0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3c020001, -0x8c424dfc, 0x27bdffe0, 0x1440000d, 0xafbf0018, 0x3c040001, 0x24844ba4, -0x3c050008, 0xafa00010, 0xafa00014, 0x8f860220, 0x34a50499, 0x24020001, -0x3c010001, 0xac224dfc, 0xc0023a7, 0x3821, 0x8ee204c0, 0x3c030001, -0x771821, 0x946383a2, 0x34420001, 0x10600007, 0xaee204c0, 0x8f820220, -0x3c0308ff, 0x3463ffff, 0x431024, 0x34420008, 0xaf820220, 0x24040001, -0xc004f33, 0x24050004, 0xaf420268, 0x8fbf0018, 0x3e00008, 0x27bd0020, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x3c120001, 0x26520f00, 0x3c140001, 0x8e944d70, -0x3c100001, 0x26100e20, 0x3c15c000, 0x36b50060, 0x8e8a0000, 0x8eb30000, -0x26a400b, 0x248000a, 0x200f821, 0x0, 0xd, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0xaf8600e0, 0x240301f5, 0x8f8200e8, 0x673823, 0x718c0, 0x431021, +0xaf8200e8, 0x8f8200e8, 0xaf8200e4, 0x8ee2007c, 0x3c0408ff, 0x3484ffff, +0x471021, 0xaee2007c, 0x8f820220, 0x3c038000, 0x34630002, 0x441024, +0x431025, 0xaf820220, 0x8f830054, 0x8f820054, 0x800427d, 0x24630001, +0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820220, +0x3c0308ff, 0x3463fffb, 0x431024, 0xaf820220, 0x8fbf0020, 0x8fb1001c, +0x8fb00018, 0x3e00008, 0x27bd0028, 0x3c020001, 0x8c42500c, 0x27bdffd8, +0x10400012, 0xafbf0020, 0x3c040001, 0x24844d84, 0x3c050008, 0x24020001, +0x3c010001, 0x370821, 0xac22839c, 0xafa00010, 0xafa00014, 0x8f860220, +0x34a50498, 0x3c010001, 0xac20500c, 0x3c010001, 0xac225000, 0xc002403, +0x3821, 0x8f420268, 0x3c037fff, 0x3463ffff, 0x431024, 0xaf420268, +0x8ee204c0, 0x8ee404c4, 0x2403fffe, 0x431024, 0x30840002, 0x1080011e, +0xaee204c0, 0x8ee204c4, 0x2403fffd, 0x431024, 0xaee204c4, 0x8f820044, +0x3c030600, 0x34632000, 0x34420020, 0xaf820044, 0xafa30018, 0x8ee205f8, +0x8f430228, 0x24420001, 0x304a00ff, 0x514300fe, 0xafa00010, 0x8ee205f8, +0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, +0x8f830054, 0x8f820054, 0x24690032, 0x1221023, 0x2c420033, 0x1040006a, +0x5821, 0x24180008, 0x240f000d, 0x240d0007, 0x240c0040, 0x240e0001, +0x8f870120, 0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, +0x8f820128, 0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, +0x8ee201a0, 0x2821, 0x24420001, 0xaee201a0, 0x800432d, 0x8ee201a0, +0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, +0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee205f8, +0xa4f8000e, 0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 0x2e21021, +0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 0x14400033, +0x24050001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, +0x144d001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, +0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, +0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, +0x800431a, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, +0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, +0x800432d, 0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 0x1021, +0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, +0x2e22021, 0xac8d0000, 0xac8e0004, 0x54a00006, 0x240b0001, 0x8f820054, +0x1221023, 0x2c420033, 0x1440ff9d, 0x0, 0x316300ff, 0x24020001, +0x54620079, 0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054, 0x24690032, +0x1221023, 0x2c420033, 0x10400061, 0x5821, 0x240d0008, 0x240c0011, +0x24080012, 0x24070040, 0x240a0001, 0x8f830120, 0x27623800, 0x24660020, +0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, +0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x2821, 0x24420001, +0xaee201a0, 0x8004399, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, +0x8ee50494, 0x2462001c, 0xac620008, 0xa46d000e, 0xac6c0018, 0xac640000, +0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400033, +0x24050001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, +0x1448001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, +0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, +0x10470007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, +0x8004386, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, +0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, +0x8004399, 0x0, 0x8ee24e20, 0x24420001, 0x50470003, 0x1021, +0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, +0x2e22021, 0xac880000, 0xac8a0004, 0x54a00006, 0x240b0001, 0x8f820054, +0x1221023, 0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, +0x54620003, 0xafa00010, 0x80043c6, 0x0, 0x3c040001, 0x24844d90, +0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011, +0x80043c6, 0x0, 0x3c040001, 0x24844d9c, 0xafa00014, 0x8f860120, +0x8f870124, 0x3c050009, 0xc002403, 0x34a5f010, 0x80043c6, 0x0, +0x3c040001, 0x24844da8, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, +0xc002403, 0x34a5f00f, 0x8ee201a8, 0x24420001, 0xaee201a8, 0x8ee201a8, +0x8ee20158, 0x24420001, 0xaee20158, 0x8ee20158, 0x8fbf0020, 0x3e00008, +0x27bd0028, 0x3c020001, 0x8c42500c, 0x27bdffe0, 0x1440000d, 0xafbf0018, +0x3c040001, 0x24844db4, 0x3c050008, 0xafa00010, 0xafa00014, 0x8f860220, +0x34a50499, 0x24020001, 0x3c010001, 0xac22500c, 0xc002403, 0x3821, +0x8ee204c0, 0x3c030001, 0x771821, 0x946383a2, 0x34420001, 0x10600007, +0xaee204c0, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420008, +0xaf820220, 0x24040001, 0xc004fb3, 0x24050004, 0xaf420268, 0x8fbf0018, +0x3e00008, 0x27bd0020, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x3c120001, 0x26521100, +0x3c140001, 0x8e944f80, 0x3c100001, 0x26101020, 0x3c15c000, 0x36b50060, +0x8e8a0000, 0x8eb30000, 0x26a400b, 0x248000a, 0x200f821, 0x0, +0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x80014c4, 0x0, 0x80014c6, 0x3c0a0001, 0x80014c6, 0x3c0a0002, -0x80014c6, 0x0, 0x800244a, 0x0, 0x80014c6, 0x3c0a0003, -0x80014c6, 0x3c0a0004, 0x8002ef8, 0x0, 0x80014c6, 0x3c0a0005, -0x8003c3d, 0x0, 0x8003bbe, 0x0, 0x80014c6, 0x3c0a0006, -0x80014c6, 0x3c0a0007, 0x80014c6, 0x0, 0x80014c6, 0x0, -0x80014c6, 0x0, 0x80029f8, 0x0, 0x80014c6, 0x3c0a000b, -0x80014c6, 0x3c0a000c, 0x80014c6, 0x3c0a000d, 0x800231c, 0x0, -0x80022d9, 0x0, 0x80014c6, 0x3c0a000e, 0x8001b08, 0x0, -0x8002448, 0x0, 0x80014c6, 0x3c0a000f, 0x8003ff3, 0x0, -0x8003fdd, 0x0, 0x80014c6, 0x3c0a0010, 0x80014da, 0x0, -0x80014c6, 0x3c0a0011, 0x80014c6, 0x3c0a0012, 0x80014c6, 0x3c0a0013, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x80014d6, 0x0, 0x80014d8, 0x3c0a0001, +0x80014d8, 0x3c0a0002, 0x80014d8, 0x0, 0x80024a6, 0x0, +0x80014d8, 0x3c0a0003, 0x80014d8, 0x3c0a0004, 0x8002f7c, 0x0, +0x80014d8, 0x3c0a0005, 0x8003cd8, 0x0, 0x8003c56, 0x0, +0x80014d8, 0x3c0a0006, 0x80014d8, 0x3c0a0007, 0x80014d8, 0x0, +0x80014d8, 0x0, 0x80014d8, 0x0, 0x8002a75, 0x0, +0x80014d8, 0x3c0a000b, 0x80014d8, 0x3c0a000c, 0x80014d8, 0x3c0a000d, +0x8002378, 0x0, 0x8002335, 0x0, 0x80014d8, 0x3c0a000e, +0x8001b38, 0x0, 0x80024a4, 0x0, 0x80014d8, 0x3c0a000f, +0x8004097, 0x0, 0x8004081, 0x0, 0x80014d8, 0x3c0a0010, +0x80014ee, 0x0, 0x80014d8, 0x3c0a0011, 0x80014d8, 0x3c0a0012, +0x80014d8, 0x3c0a0013, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, @@ -2243,541 +2264,542 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x3c030001, 0x34633800, 0x24050080, 0x2404001f, -0x2406ffff, 0x24020001, 0xaf80021c, 0xaf820200, 0xaf820220, 0x3631021, -0xaf8200c0, 0x3631021, 0xaf8200c4, 0x3631021, 0xaf8200c8, 0x27623800, -0xaf8200d0, 0x27623800, 0xaf8200d4, 0x27623800, 0xaf8200d8, 0x27621800, -0xaf8200e0, 0x27621800, 0xaf8200e4, 0x27621800, 0xaf8200e8, 0x27621000, -0xaf8200f0, 0x27621000, 0xaf8200f4, 0x27621000, 0xaf8200f8, 0xaca00000, -0x2484ffff, 0x1486fffd, 0x24a50004, 0x8f830040, 0x3c02f000, 0x621824, -0x3c025000, 0x1062000c, 0x43102b, 0x14400006, 0x3c026000, 0x3c024000, -0x10620008, 0x24020800, 0x8004479, 0x0, 0x10620004, 0x24020800, -0x8004479, 0x0, 0x24020700, 0x3c010001, 0xac224e00, 0x3e00008, -0x0, 0x27bdffd0, 0xafbf0028, 0x3c010001, 0xc004b65, 0xac204de8, -0x24040001, 0x2821, 0x27a60020, 0x34028000, 0xc004782, 0xa7a20020, -0x8f830054, 0x8f820054, 0x800448b, 0x24630064, 0x8f820054, 0x621023, -0x2c420065, 0x1440fffc, 0x24040001, 0x24050001, 0xc004740, 0x27a60020, -0x8f830054, 0x8f820054, 0x8004497, 0x24630064, 0x8f820054, 0x621023, -0x2c420065, 0x1440fffc, 0x24040001, 0x24050001, 0xc004740, 0x27a60020, -0x8f830054, 0x8f820054, 0x80044a3, 0x24630064, 0x8f820054, 0x621023, -0x2c420065, 0x1440fffc, 0x24040001, 0x24050002, 0xc004740, 0x27a60018, -0x8f830054, 0x8f820054, 0x80044af, 0x24630064, 0x8f820054, 0x621023, -0x2c420065, 0x1440fffc, 0x24040001, 0x24050003, 0xc004740, 0x27a6001a, -0x97a20020, 0x10400022, 0x24030001, 0x3c020001, 0x8c424de8, 0x97a30018, -0x34420001, 0x3c010001, 0xac224de8, 0x24020015, 0x14620008, 0x3402f423, -0x97a3001a, 0x14620005, 0x24020003, 0x3c010001, 0xac224e9c, 0x80044e2, -0x3c08fff0, 0x97a30018, 0x24027810, 0x1462000a, 0x24020002, 0x97a3001a, -0x24020001, 0x14620006, 0x24020002, 0x24020004, 0x3c010001, 0xac224e9c, -0x80044e2, 0x3c08fff0, 0x3c010001, 0xac224e9c, 0x80044e2, 0x3c08fff0, -0x3c020001, 0x8c424de8, 0x3c010001, 0xac234e9c, 0x34420004, 0x3c010001, -0xac224de8, 0x3c08fff0, 0x3508bdc0, 0x8f830054, 0x97a60018, 0x3c070001, -0x8ce74e9c, 0x3c040001, 0x24844c10, 0x24020001, 0x3c010001, 0xac224df0, -0xafa60010, 0x3c060001, 0x8cc64de8, 0x97a2001a, 0x3c05000d, 0x34a50100, -0x3c010001, 0xac204dec, 0x681821, 0x3c010001, 0xac234e94, 0xc0023a7, -0xafa20014, 0x8fbf0028, 0x3e00008, 0x27bd0030, 0x27bdffe8, 0x24070004, -0x3c040001, 0x8c844dec, 0x3021, 0x24020001, 0x1482000a, 0xafbf0010, -0x3c020001, 0x8c426f3c, 0x3c050004, 0x30428000, 0x1040000c, 0x34a593e0, -0x3c05000f, 0x8004515, 0x34a54240, 0x3c020001, 0x8c426f3c, 0x3c05000f, -0x30428000, 0x10400003, 0x34a54240, 0x3c05001e, 0x34a58480, 0x3c020001, -0x8c424e94, 0x8f830054, 0x451021, 0x431023, 0x45102b, 0x1440002e, -0x0, 0x3c020001, 0x8c424df4, 0x1440002a, 0x2cc20001, 0x7182b, -0x431024, 0x1040001d, 0x0, 0x3c090001, 0x8d294de8, 0x240b0001, -0x3c054000, 0x3c080001, 0x25086f3c, 0x250afffc, 0x42042, 0x14800002, -0x24e7ffff, 0x24040008, 0x891024, 0x5040000b, 0x2cc20001, 0x148b0004, -0x0, 0x8d020000, 0x800453a, 0x451024, 0x8d420000, 0x451024, -0x54400001, 0x24060001, 0x2cc20001, 0x7182b, 0x431024, 0x5440ffed, -0x42042, 0x3c010001, 0x10c00024, 0xac244dec, 0x8f830054, 0x24020001, -0x3c010001, 0xac224df0, 0x3c010001, 0xac234e94, 0x3c020001, 0x8c424df0, -0x10400006, 0x24020001, 0x3c010001, 0xac204df0, 0x3c010001, 0x370821, -0xac22839c, 0x3c030001, 0x771821, 0x8c63839c, 0x24020008, 0x10620005, -0x24020001, 0xc00456a, 0x0, 0x8004567, 0x0, 0x3c030001, -0x8c634dec, 0x10620007, 0x2402000e, 0x3c030001, 0x8c636eb0, 0x10620003, -0x0, 0xc004b88, 0x8f840220, 0x8fbf0010, 0x3e00008, 0x27bd0018, -0x27bdffe0, 0x3c02fdff, 0xafbf0018, 0x8ee30000, 0x3c050001, 0x8ca54dec, -0x3c040001, 0x8c844e04, 0x3442ffff, 0x621824, 0x14a40008, 0xaee30000, -0x3c030001, 0x771821, 0x8c63839c, 0x3c020001, 0x8c424e08, 0x10620008, -0x0, 0x3c020001, 0x571021, 0x8c42839c, 0x3c010001, 0xac254e04, -0x3c010001, 0xac224e08, 0x3c030001, 0x8c634dec, 0x24020002, 0x10620126, -0x2c620003, 0x10400005, 0x24020001, 0x10620008, 0x0, 0x80046ae, -0x0, 0x24020004, 0x1062007c, 0x24020001, 0x80046af, 0x0, -0x3c020001, 0x571021, 0x8c42839c, 0x2443ffff, 0x2c620008, 0x10400117, -0x31080, 0x3c010001, 0x220821, 0x8c224c28, 0x400008, 0x0, -0xc0046b4, 0x0, 0x3c020001, 0x8c424df8, 0x3c010001, 0xac204d80, -0x104000c5, 0x24020002, 0x3c010001, 0x370821, 0xac22839c, 0x3c010001, -0x80046b1, 0xac204df8, 0xc0047c3, 0x0, 0x3c030001, 0x8c634e10, -0x24020011, 0x146200fd, 0x24020003, 0x8004631, 0x0, 0x3c050001, -0x8ca54dec, 0x3c060001, 0x8cc66f3c, 0xc004e2c, 0x24040001, 0x24020005, -0x3c010001, 0xac204df8, 0x3c010001, 0x370821, 0x80046b1, 0xac22839c, -0x3c040001, 0x24844c1c, 0x3c05000f, 0x34a50100, 0x3021, 0x3821, -0xafa00010, 0xc0023a7, 0xafa00014, 0x80046b1, 0x0, 0x8f820220, -0x3c03f700, 0x431025, 0x8004658, 0xaf820220, 0x8f820220, 0x3c030004, -0x431024, 0x14400095, 0x24020007, 0x8f830054, 0x3c020001, 0x8c424e90, -0x2463d8f0, 0x431023, 0x2c422710, 0x144000d1, 0x24020001, 0x80046af, -0x0, 0x3c050001, 0x8ca54dec, 0xc004f33, 0x24040001, 0xc004ff8, -0x24040001, 0x3c030001, 0x8c636f34, 0x46100c3, 0x24020001, 0x3c020008, -0x621024, 0x10400006, 0x0, 0x8f820214, 0x3c03ffff, 0x431024, -0x80045fa, 0x3442251f, 0x8f820214, 0x3c03ffff, 0x431024, 0x3442241f, -0xaf820214, 0x8ee20000, 0x3c030200, 0x431025, 0xaee20000, 0x8f820220, -0x2403fffb, 0x431024, 0xaf820220, 0x8f820220, 0x34420002, 0xaf820220, -0x24020008, 0x3c010001, 0x370821, 0xc004323, 0xac22839c, 0x80046b1, -0x0, 0x3c020001, 0x571021, 0x8c42839c, 0x2443ffff, 0x2c620008, -0x1040009e, 0x31080, 0x3c010001, 0x220821, 0x8c224c48, 0x400008, -0x0, 0xc0041e7, 0x0, 0x3c010001, 0xac204df0, 0xaf800204, -0x3c010001, 0xc0046b4, 0xac206f00, 0x8f820044, 0x34428080, 0xaf820044, -0x8f830054, 0x3c010001, 0xac204d80, 0x800465a, 0x24020002, 0x8f830054, -0x3c020001, 0x8c424e90, 0x2463d8f0, 0x431023, 0x2c422710, 0x14400081, -0x24020003, 0x3c010001, 0x370821, 0x80046b1, 0xac22839c, 0x3c020001, -0x8c426f38, 0x30424000, 0x10400005, 0x0, 0x8f820044, 0x3c03ffff, -0x8004640, 0x34637fff, 0x8f820044, 0x2403ff7f, 0x431024, 0xaf820044, -0x8f830054, 0x800465a, 0x24020004, 0x8f830054, 0x3c020001, 0x8c424e90, -0x2463d8f0, 0x431023, 0x2c422710, 0x14400065, 0x24020005, 0x3c010001, -0x370821, 0x80046b1, 0xac22839c, 0x8f820220, 0x3c03f700, 0x431025, -0xaf820220, 0xaf800204, 0x3c010001, 0xac206f00, 0x8f830054, 0x24020006, -0x3c010001, 0x370821, 0xac22839c, 0x3c010001, 0x80046b1, 0xac234e90, -0x3c05fffe, 0x34a57960, 0x3c040001, 0x8f820054, 0x3c030001, 0x8c634e90, -0x3484869f, 0x451021, 0x621823, 0x83202b, 0x10800046, 0x0, -0x24020007, 0x3c010001, 0x370821, 0x80046b1, 0xac22839c, 0x8f820220, -0x3c04f700, 0x441025, 0xaf820220, 0x8f820220, 0x3c030300, 0x431024, -0x14400005, 0x1821, 0x8f820220, 0x24030001, 0x441025, 0xaf820220, -0x10600030, 0x24020001, 0x8f820214, 0x3c03ffff, 0x3c040001, 0x8c844e88, -0x431024, 0x3442251f, 0xaf820214, 0x24020008, 0x3c010001, 0x370821, -0xac22839c, 0x10800007, 0x24020001, 0x3c010001, 0xac226eb0, 0xc004b88, -0x8f840220, 0x80046b1, 0x0, 0x8f820220, 0x3c030008, 0x431024, -0x1440001a, 0x2402000e, 0x3c010001, 0xac226eb0, 0x8ee20000, 0x24040001, -0x3c030200, 0x431025, 0xc004ff8, 0xaee20000, 0x8f820220, 0x2403fffb, -0x431024, 0xaf820220, 0x8f820220, 0x34420002, 0xc004323, 0xaf820220, -0x3c050001, 0x8ca54dec, 0xc004f33, 0x24040001, 0x80046b1, 0x0, -0x24020001, 0x3c010001, 0xac224df0, 0x8fbf0018, 0x3e00008, 0x27bd0020, -0x8f820200, 0x8f820220, 0x8f820220, 0x34420004, 0xaf820220, 0x8f820200, -0x3c060001, 0x8cc64dec, 0x34420004, 0xaf820200, 0x24020002, 0x10c20048, -0x2cc20003, 0x10400005, 0x24020001, 0x10c20008, 0x0, 0x8004708, -0x0, 0x24020004, 0x10c20013, 0x24020001, 0x8004708, 0x0, -0x3c030001, 0x8c634dd8, 0x3c020001, 0x8c424de4, 0x3c040001, 0x8c844e00, -0x3c050001, 0x8ca54ddc, 0xaf860200, 0xaf860220, 0x34630022, 0x441025, -0x451025, 0x34420002, 0x8004707, 0xaf830200, 0xaf820200, 0xaf820220, -0x8f820044, 0x3c030001, 0x8c634e88, 0x34428080, 0xaf820044, 0x10600005, -0x3c033f00, 0x3c020001, 0x8c424dd0, 0x80046fb, 0x346300e0, 0x8f8400f0, -0x276217f8, 0x14820002, 0x24850008, 0x27651000, 0x8f8200f4, 0x10a20007, -0x3c038000, 0x34630040, 0x3c020001, 0x24424d90, 0xac820000, 0xac830004, -0xaf8500f0, 0x3c020001, 0x8c424dd0, 0x3c033f00, 0x346300e2, 0x431025, -0xaf820200, 0x3c030001, 0x8c634dd4, 0x3c04f700, 0x3c020001, 0x8c424de4, -0x3c050001, 0x8ca54e00, 0x641825, 0x431025, 0x451025, 0xaf820220, -0x3e00008, 0x0, 0x8f820220, 0x3c030001, 0x8c634dec, 0x34420004, -0xaf820220, 0x24020001, 0x1062000f, 0x0, 0x8f830054, 0x8f820054, -0x24630002, 0x621023, 0x2c420003, 0x10400011, 0x0, 0x8f820054, -0x621023, 0x2c420003, 0x1040000c, 0x0, 0x8004719, 0x0, -0x8f830054, 0x8f820054, 0x8004725, 0x24630007, 0x8f820054, 0x621023, -0x2c420008, 0x1440fffc, 0x0, 0x8f8400e0, 0x30820007, 0x1040000d, -0x0, 0x8f820054, 0x8f8300e0, 0x14830009, 0x24450032, 0x8f820054, -0xa21023, 0x2c420033, 0x10400004, 0x0, 0x8f8200e0, 0x1082fff9, -0x0, 0x8f820220, 0x2403fffd, 0x431024, 0xaf820220, 0x3e00008, -0x0, 0x0, 0x27bdffd8, 0xafb20018, 0x809021, 0xafb3001c, -0xa09821, 0xafb10014, 0xc08821, 0xafb00010, 0x8021, 0xafbf0020, -0xa6200000, 0xc004b3f, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0xc004b3f, -0x24040001, 0xc004b3f, 0x2021, 0x24100010, 0x2501024, 0x10400002, -0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x2501024, -0x24100010, 0x2701024, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, -0x108042, 0x1600fffa, 0x2701024, 0xc004b65, 0x34108000, 0xc004b65, -0x0, 0xc004b1f, 0x0, 0x50400005, 0x108042, 0x96220000, -0x501025, 0xa6220000, 0x108042, 0x1600fff7, 0x0, 0xc004b65, -0x0, 0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, -0x3e00008, 0x27bd0028, 0x27bdffd8, 0xafb10014, 0x808821, 0xafb20018, -0xa09021, 0xafb3001c, 0xc09821, 0xafb00010, 0x8021, 0xafbf0020, -0xc004b3f, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, -0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, -0xc004b3f, 0x24040001, 0x24100010, 0x2301024, 0x10400002, 0x2021, -0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x2301024, 0x24100010, -0x2501024, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, -0x1600fffa, 0x2501024, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, -0x34108000, 0x96620000, 0x501024, 0x10400002, 0x2021, 0x24040001, -0xc004b3f, 0x108042, 0x1600fff8, 0x0, 0xc004b65, 0x0, -0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, -0x27bd0028, 0x3c030001, 0x8c634e10, 0x3c020001, 0x8c424e54, 0x27bdffd8, -0xafbf0020, 0xafb1001c, 0x10620003, 0xafb00018, 0x3c010001, 0xac234e54, -0x2463ffff, 0x2c620013, 0x10400349, 0x31080, 0x3c010001, 0x220821, -0x8c224c70, 0x400008, 0x0, 0xc004b65, 0x8021, 0x34028000, -0xa7a20010, 0x27b10010, 0xc004b3f, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, -0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, -0x32020001, 0x24100010, 0xc004b3f, 0x2021, 0x108042, 0x1600fffc, -0x0, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 0x34108000, -0x96220000, 0x501024, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, -0x108042, 0x1600fff8, 0x0, 0xc004b65, 0x0, 0x8004b18, -0x24020002, 0x27b10010, 0xa7a00010, 0x8021, 0xc004b3f, 0x24040001, -0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004b3f, 0x2021, -0xc004b3f, 0x24040001, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, -0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, -0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0xc004b3f, 0x2021, -0x108042, 0x1600fffc, 0x0, 0xc004b65, 0x34108000, 0xc004b65, -0x0, 0xc004b1f, 0x0, 0x50400005, 0x108042, 0x96220000, -0x501025, 0xa6220000, 0x108042, 0x1600fff7, 0x0, 0xc004b65, -0x0, 0x97a20010, 0x30428000, 0x144002dc, 0x24020003, 0x8004b18, -0x0, 0x24021200, 0xa7a20010, 0x27b10010, 0x8021, 0xc004b3f, -0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004b3f, -0x2021, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 0xc004b3f, -0x24040001, 0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, -0xc004b3f, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0xc004b3f, -0x2021, 0x108042, 0x1600fffc, 0x0, 0xc004b3f, 0x24040001, -0xc004b3f, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fff8, 0x0, -0xc004b65, 0x0, 0x8f830054, 0x8004b0a, 0x24020004, 0x8f830054, -0x3c020001, 0x8c424e98, 0x2463ff9c, 0x431023, 0x2c420064, 0x1440029e, -0x24020002, 0x3c030001, 0x8c634e9c, 0x10620297, 0x2c620003, 0x14400296, -0x24020011, 0x24020003, 0x10620005, 0x24020004, 0x10620291, 0x2402000f, -0x8004b18, 0x24020011, 0x8004b18, 0x24020005, 0x24020014, 0xa7a20010, -0x27b10010, 0x8021, 0xc004b3f, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, -0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, -0x32020001, 0x24100010, 0x32020012, 0x10400002, 0x2021, 0x24040001, -0xc004b3f, 0x108042, 0x1600fffa, 0x32020012, 0xc004b3f, 0x24040001, -0xc004b3f, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fff8, 0x0, -0xc004b65, 0x0, 0x8f830054, 0x8004b0a, 0x24020006, 0x8f830054, -0x3c020001, 0x8c424e98, 0x2463ff9c, 0x431023, 0x2c420064, 0x14400250, -0x24020007, 0x8004b18, 0x0, 0x24020006, 0xa7a20010, 0x27b10010, -0x8021, 0xc004b3f, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0xc004b3f, -0x2021, 0xc004b3f, 0x24040001, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x32020001, -0x24100010, 0x32020013, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, -0x108042, 0x1600fffa, 0x32020013, 0xc004b3f, 0x24040001, 0xc004b3f, +0x0, 0x0, 0x0, 0x0, 0x3c030001, 0x34633800, +0x24050080, 0x2404001f, 0x2406ffff, 0x24020001, 0xaf80021c, 0xaf820200, +0xaf820220, 0x3631021, 0xaf8200c0, 0x3631021, 0xaf8200c4, 0x3631021, +0xaf8200c8, 0x27623800, 0xaf8200d0, 0x27623800, 0xaf8200d4, 0x27623800, +0xaf8200d8, 0x27621800, 0xaf8200e0, 0x27621800, 0xaf8200e4, 0x27621800, +0xaf8200e8, 0x27621000, 0xaf8200f0, 0x27621000, 0xaf8200f4, 0x27621000, +0xaf8200f8, 0xaca00000, 0x2484ffff, 0x1486fffd, 0x24a50004, 0x8f830040, +0x3c02f000, 0x621824, 0x3c025000, 0x1062000c, 0x43102b, 0x14400006, +0x3c026000, 0x3c024000, 0x10620008, 0x24020800, 0x80044f9, 0x0, +0x10620004, 0x24020800, 0x80044f9, 0x0, 0x24020700, 0x3c010001, +0xac225010, 0x3e00008, 0x0, 0x27bdffd0, 0xafbf0028, 0x3c010001, +0xc004be5, 0xac204ff8, 0x24040001, 0x2821, 0x27a60020, 0x34028000, +0xc004802, 0xa7a20020, 0x8f830054, 0x8f820054, 0x800450b, 0x24630064, +0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050001, +0xc0047c0, 0x27a60020, 0x8f830054, 0x8f820054, 0x8004517, 0x24630064, +0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050001, +0xc0047c0, 0x27a60020, 0x8f830054, 0x8f820054, 0x8004523, 0x24630064, +0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050002, +0xc0047c0, 0x27a60018, 0x8f830054, 0x8f820054, 0x800452f, 0x24630064, +0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050003, +0xc0047c0, 0x27a6001a, 0x97a20020, 0x10400022, 0x24030001, 0x3c020001, +0x8c424ff8, 0x97a30018, 0x34420001, 0x3c010001, 0xac224ff8, 0x24020015, +0x14620008, 0x3402f423, 0x97a3001a, 0x14620005, 0x24020003, 0x3c010001, +0xac2250ac, 0x8004562, 0x3c08fff0, 0x97a30018, 0x24027810, 0x1462000a, +0x24020002, 0x97a3001a, 0x24020001, 0x14620006, 0x24020002, 0x24020004, +0x3c010001, 0xac2250ac, 0x8004562, 0x3c08fff0, 0x3c010001, 0xac2250ac, +0x8004562, 0x3c08fff0, 0x3c020001, 0x8c424ff8, 0x3c010001, 0xac2350ac, +0x34420004, 0x3c010001, 0xac224ff8, 0x3c08fff0, 0x3508bdc0, 0x8f830054, +0x97a60018, 0x3c070001, 0x8ce750ac, 0x3c040001, 0x24844e20, 0x24020001, +0x3c010001, 0xac225000, 0xafa60010, 0x3c060001, 0x8cc64ff8, 0x97a2001a, +0x3c05000d, 0x34a50100, 0x3c010001, 0xac204ffc, 0x681821, 0x3c010001, +0xac2350a4, 0xc002403, 0xafa20014, 0x8fbf0028, 0x3e00008, 0x27bd0030, +0x27bdffe8, 0x24070004, 0x3c040001, 0x8c844ffc, 0x3021, 0x24020001, +0x1482000a, 0xafbf0010, 0x3c020001, 0x8c42714c, 0x3c050004, 0x30428000, +0x1040000c, 0x34a593e0, 0x3c05000f, 0x8004595, 0x34a54240, 0x3c020001, +0x8c42714c, 0x3c05000f, 0x30428000, 0x10400003, 0x34a54240, 0x3c05001e, +0x34a58480, 0x3c020001, 0x8c4250a4, 0x8f830054, 0x451021, 0x431023, +0x45102b, 0x1440002e, 0x0, 0x3c020001, 0x8c425004, 0x1440002a, +0x2cc20001, 0x7182b, 0x431024, 0x1040001d, 0x0, 0x3c090001, +0x8d294ff8, 0x240b0001, 0x3c054000, 0x3c080001, 0x2508714c, 0x250afffc, +0x42042, 0x14800002, 0x24e7ffff, 0x24040008, 0x891024, 0x5040000b, +0x2cc20001, 0x148b0004, 0x0, 0x8d020000, 0x80045ba, 0x451024, +0x8d420000, 0x451024, 0x54400001, 0x24060001, 0x2cc20001, 0x7182b, +0x431024, 0x5440ffed, 0x42042, 0x3c010001, 0x10c00024, 0xac244ffc, +0x8f830054, 0x24020001, 0x3c010001, 0xac225000, 0x3c010001, 0xac2350a4, +0x3c020001, 0x8c425000, 0x10400006, 0x24020001, 0x3c010001, 0xac205000, +0x3c010001, 0x370821, 0xac22839c, 0x3c030001, 0x771821, 0x8c63839c, +0x24020008, 0x10620005, 0x24020001, 0xc0045ea, 0x0, 0x80045e7, +0x0, 0x3c030001, 0x8c634ffc, 0x10620007, 0x2402000e, 0x3c030001, +0x8c6370c0, 0x10620003, 0x0, 0xc004c08, 0x8f840220, 0x8fbf0010, +0x3e00008, 0x27bd0018, 0x27bdffe0, 0x3c02fdff, 0xafbf0018, 0x8ee30000, +0x3c050001, 0x8ca54ffc, 0x3c040001, 0x8c845014, 0x3442ffff, 0x621824, +0x14a40008, 0xaee30000, 0x3c030001, 0x771821, 0x8c63839c, 0x3c020001, +0x8c425018, 0x10620008, 0x0, 0x3c020001, 0x571021, 0x8c42839c, +0x3c010001, 0xac255014, 0x3c010001, 0xac225018, 0x3c030001, 0x8c634ffc, +0x24020002, 0x10620126, 0x2c620003, 0x10400005, 0x24020001, 0x10620008, +0x0, 0x800472e, 0x0, 0x24020004, 0x1062007c, 0x24020001, +0x800472f, 0x0, 0x3c020001, 0x571021, 0x8c42839c, 0x2443ffff, +0x2c620008, 0x10400117, 0x31080, 0x3c010001, 0x220821, 0x8c224e38, +0x400008, 0x0, 0xc004734, 0x0, 0x3c020001, 0x8c425008, +0x3c010001, 0xac204f90, 0x104000c5, 0x24020002, 0x3c010001, 0x370821, +0xac22839c, 0x3c010001, 0x8004731, 0xac205008, 0xc004843, 0x0, +0x3c030001, 0x8c635020, 0x24020011, 0x146200fd, 0x24020003, 0x80046b1, +0x0, 0x3c050001, 0x8ca54ffc, 0x3c060001, 0x8cc6714c, 0xc004eac, +0x24040001, 0x24020005, 0x3c010001, 0xac205008, 0x3c010001, 0x370821, +0x8004731, 0xac22839c, 0x3c040001, 0x24844e2c, 0x3c05000f, 0x34a50100, +0x3021, 0x3821, 0xafa00010, 0xc002403, 0xafa00014, 0x8004731, +0x0, 0x8f820220, 0x3c03f700, 0x431025, 0x80046d8, 0xaf820220, +0x8f820220, 0x3c030004, 0x431024, 0x14400095, 0x24020007, 0x8f830054, +0x3c020001, 0x8c4250a0, 0x2463d8f0, 0x431023, 0x2c422710, 0x144000d1, +0x24020001, 0x800472f, 0x0, 0x3c050001, 0x8ca54ffc, 0xc004fb3, +0x24040001, 0xc005078, 0x24040001, 0x3c030001, 0x8c637144, 0x46100c3, +0x24020001, 0x3c020008, 0x621024, 0x10400006, 0x0, 0x8f820214, +0x3c03ffff, 0x431024, 0x800467a, 0x3442251f, 0x8f820214, 0x3c03ffff, +0x431024, 0x3442241f, 0xaf820214, 0x8ee20000, 0x3c030200, 0x431025, +0xaee20000, 0x8f820220, 0x2403fffb, 0x431024, 0xaf820220, 0x8f820220, +0x34420002, 0xaf820220, 0x24020008, 0x3c010001, 0x370821, 0xc0043cd, +0xac22839c, 0x8004731, 0x0, 0x3c020001, 0x571021, 0x8c42839c, +0x2443ffff, 0x2c620008, 0x1040009e, 0x31080, 0x3c010001, 0x220821, +0x8c224e58, 0x400008, 0x0, 0xc00428b, 0x0, 0x3c010001, +0xac205000, 0xaf800204, 0x3c010001, 0xc004734, 0xac207110, 0x8f820044, +0x34428080, 0xaf820044, 0x8f830054, 0x3c010001, 0xac204f90, 0x80046da, +0x24020002, 0x8f830054, 0x3c020001, 0x8c4250a0, 0x2463d8f0, 0x431023, +0x2c422710, 0x14400081, 0x24020003, 0x3c010001, 0x370821, 0x8004731, +0xac22839c, 0x3c020001, 0x8c427148, 0x30424000, 0x10400005, 0x0, +0x8f820044, 0x3c03ffff, 0x80046c0, 0x34637fff, 0x8f820044, 0x2403ff7f, +0x431024, 0xaf820044, 0x8f830054, 0x80046da, 0x24020004, 0x8f830054, +0x3c020001, 0x8c4250a0, 0x2463d8f0, 0x431023, 0x2c422710, 0x14400065, +0x24020005, 0x3c010001, 0x370821, 0x8004731, 0xac22839c, 0x8f820220, +0x3c03f700, 0x431025, 0xaf820220, 0xaf800204, 0x3c010001, 0xac207110, +0x8f830054, 0x24020006, 0x3c010001, 0x370821, 0xac22839c, 0x3c010001, +0x8004731, 0xac2350a0, 0x3c05fffe, 0x34a57960, 0x3c040001, 0x8f820054, +0x3c030001, 0x8c6350a0, 0x3484869f, 0x451021, 0x621823, 0x83202b, +0x10800046, 0x0, 0x24020007, 0x3c010001, 0x370821, 0x8004731, +0xac22839c, 0x8f820220, 0x3c04f700, 0x441025, 0xaf820220, 0x8f820220, +0x3c030300, 0x431024, 0x14400005, 0x1821, 0x8f820220, 0x24030001, +0x441025, 0xaf820220, 0x10600030, 0x24020001, 0x8f820214, 0x3c03ffff, +0x3c040001, 0x8c845098, 0x431024, 0x3442251f, 0xaf820214, 0x24020008, +0x3c010001, 0x370821, 0xac22839c, 0x10800007, 0x24020001, 0x3c010001, +0xac2270c0, 0xc004c08, 0x8f840220, 0x8004731, 0x0, 0x8f820220, +0x3c030008, 0x431024, 0x1440001a, 0x2402000e, 0x3c010001, 0xac2270c0, +0x8ee20000, 0x24040001, 0x3c030200, 0x431025, 0xc005078, 0xaee20000, +0x8f820220, 0x2403fffb, 0x431024, 0xaf820220, 0x8f820220, 0x34420002, +0xc0043cd, 0xaf820220, 0x3c050001, 0x8ca54ffc, 0xc004fb3, 0x24040001, +0x8004731, 0x0, 0x24020001, 0x3c010001, 0xac225000, 0x8fbf0018, +0x3e00008, 0x27bd0020, 0x8f820200, 0x8f820220, 0x8f820220, 0x34420004, +0xaf820220, 0x8f820200, 0x3c060001, 0x8cc64ffc, 0x34420004, 0xaf820200, +0x24020002, 0x10c20048, 0x2cc20003, 0x10400005, 0x24020001, 0x10c20008, +0x0, 0x8004788, 0x0, 0x24020004, 0x10c20013, 0x24020001, +0x8004788, 0x0, 0x3c030001, 0x8c634fe8, 0x3c020001, 0x8c424ff4, +0x3c040001, 0x8c845010, 0x3c050001, 0x8ca54fec, 0xaf860200, 0xaf860220, +0x34630022, 0x441025, 0x451025, 0x34420002, 0x8004787, 0xaf830200, +0xaf820200, 0xaf820220, 0x8f820044, 0x3c030001, 0x8c635098, 0x34428080, +0xaf820044, 0x10600005, 0x3c033f00, 0x3c020001, 0x8c424fe0, 0x800477b, +0x346300e0, 0x8f8400f0, 0x276217f8, 0x14820002, 0x24850008, 0x27651000, +0x8f8200f4, 0x10a20007, 0x3c038000, 0x34630040, 0x3c020001, 0x24424fa0, +0xac820000, 0xac830004, 0xaf8500f0, 0x3c020001, 0x8c424fe0, 0x3c033f00, +0x346300e2, 0x431025, 0xaf820200, 0x3c030001, 0x8c634fe4, 0x3c04f700, +0x3c020001, 0x8c424ff4, 0x3c050001, 0x8ca55010, 0x641825, 0x431025, +0x451025, 0xaf820220, 0x3e00008, 0x0, 0x8f820220, 0x3c030001, +0x8c634ffc, 0x34420004, 0xaf820220, 0x24020001, 0x1062000f, 0x0, +0x8f830054, 0x8f820054, 0x24630002, 0x621023, 0x2c420003, 0x10400011, +0x0, 0x8f820054, 0x621023, 0x2c420003, 0x1040000c, 0x0, +0x8004799, 0x0, 0x8f830054, 0x8f820054, 0x80047a5, 0x24630007, +0x8f820054, 0x621023, 0x2c420008, 0x1440fffc, 0x0, 0x8f8400e0, +0x30820007, 0x1040000d, 0x0, 0x8f820054, 0x8f8300e0, 0x14830009, +0x24450032, 0x8f820054, 0xa21023, 0x2c420033, 0x10400004, 0x0, +0x8f8200e0, 0x1082fff9, 0x0, 0x8f820220, 0x2403fffd, 0x431024, +0xaf820220, 0x3e00008, 0x0, 0x0, 0x27bdffd8, 0xafb20018, +0x809021, 0xafb3001c, 0xa09821, 0xafb10014, 0xc08821, 0xafb00010, +0x8021, 0xafbf0020, 0xa6200000, 0xc004bbf, 0x24040001, 0x26100001, +0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, 0x2021, 0xc004bbf, +0x24040001, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0x24100010, +0x2501024, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, +0x1600fffa, 0x2501024, 0x24100010, 0x2701024, 0x10400002, 0x2021, +0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x2701024, 0xc004be5, +0x34108000, 0xc004be5, 0x0, 0xc004b9f, 0x0, 0x50400005, +0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, 0x1600fff7, +0x0, 0xc004be5, 0x0, 0x8fbf0020, 0x8fb3001c, 0x8fb20018, +0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0028, 0x27bdffd8, 0xafb10014, +0x808821, 0xafb20018, 0xa09021, 0xafb3001c, 0xc09821, 0xafb00010, +0x8021, 0xafbf0020, 0xc004bbf, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, +0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0x24100010, 0x2301024, +0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, +0x2301024, 0x24100010, 0x2501024, 0x10400002, 0x2021, 0x24040001, +0xc004bbf, 0x108042, 0x1600fffa, 0x2501024, 0xc004bbf, 0x24040001, +0xc004bbf, 0x2021, 0x34108000, 0x96620000, 0x501024, 0x10400002, +0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fff8, 0x0, +0xc004be5, 0x0, 0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, +0x8fb00010, 0x3e00008, 0x27bd0028, 0x3c030001, 0x8c635020, 0x3c020001, +0x8c425064, 0x27bdffd8, 0xafbf0020, 0xafb1001c, 0x10620003, 0xafb00018, +0x3c010001, 0xac235064, 0x2463ffff, 0x2c620013, 0x10400349, 0x31080, +0x3c010001, 0x220821, 0x8c224e80, 0x400008, 0x0, 0xc004be5, +0x8021, 0x34028000, 0xa7a20010, 0x27b10010, 0xc004bbf, 0x24040001, +0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, 0x2021, +0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, +0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, +0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0xc004bbf, 0x2021, +0x108042, 0x1600fffc, 0x0, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, 0x2021, -0x24040001, 0xc004b3f, 0x108042, 0x1600fff8, 0x0, 0xc004b65, -0x0, 0x8f830054, 0x8004b0a, 0x24020008, 0x8f830054, 0x3c020001, -0x8c424e98, 0x2463ff9c, 0x431023, 0x2c420064, 0x1440020f, 0x24020009, -0x8004b18, 0x0, 0x27b10010, 0xa7a00010, 0x8021, 0xc004b3f, -0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004b3f, -0x2021, 0xc004b3f, 0x24040001, 0xc004b3f, 0x24040001, 0xc004b3f, -0x2021, 0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, -0xc004b3f, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, -0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, -0x32020018, 0xc004b65, 0x34108000, 0xc004b65, 0x0, 0xc004b1f, -0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, -0x108042, 0x1600fff7, 0x0, 0xc004b65, 0x8021, 0x97a20010, -0x27b10010, 0x34420001, 0xa7a20010, 0xc004b3f, 0x24040001, 0x26100001, -0x2e020020, 0x1440fffb, 0x0, 0xc004b3f, 0x2021, 0xc004b3f, -0x24040001, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0x24100010, -0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, -0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021, -0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x32020018, 0xc004b3f, -0x24040001, 0xc004b3f, 0x2021, 0x34108000, 0x96220000, 0x501024, -0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fff8, -0x0, 0xc004b65, 0x0, 0x8f830054, 0x8004b0a, 0x2402000a, -0x8f830054, 0x3c020001, 0x8c424e98, 0x2463ff9c, 0x431023, 0x2c420064, -0x1440019b, 0x2402000b, 0x8004b18, 0x0, 0x27b10010, 0xa7a00010, -0x8021, 0xc004b3f, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0xc004b3f, -0x24040001, 0xc004b3f, 0x2021, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x32020001, -0x24100010, 0x32020017, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, -0x108042, 0x1600fffa, 0x32020017, 0xc004b65, 0x34108000, 0xc004b65, -0x0, 0xc004b1f, 0x0, 0x50400005, 0x108042, 0x96220000, -0x501025, 0xa6220000, 0x108042, 0x1600fff7, 0x0, 0xc004b65, -0x8021, 0x97a20010, 0x27b10010, 0x34420700, 0xa7a20010, 0xc004b3f, -0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004b3f, -0x2021, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 0xc004b3f, +0x24040001, 0xc004bbf, 0x108042, 0x1600fff8, 0x0, 0xc004be5, +0x0, 0x8004b98, 0x24020002, 0x27b10010, 0xa7a00010, 0x8021, +0xc004bbf, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, +0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0xc004bbf, 0x24040001, +0xc004bbf, 0x2021, 0x24100010, 0x32020001, 0x10400002, 0x2021, +0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, +0xc004bbf, 0x2021, 0x108042, 0x1600fffc, 0x0, 0xc004be5, +0x34108000, 0xc004be5, 0x0, 0xc004b9f, 0x0, 0x50400005, +0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, 0x1600fff7, +0x0, 0xc004be5, 0x0, 0x97a20010, 0x30428000, 0x144002dc, +0x24020003, 0x8004b98, 0x0, 0x24021200, 0xa7a20010, 0x27b10010, +0x8021, 0xc004bbf, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, +0x0, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0xc004bbf, +0x2021, 0xc004bbf, 0x24040001, 0x24100010, 0x32020001, 0x10400002, +0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020001, +0x24100010, 0xc004bbf, 0x2021, 0x108042, 0x1600fffc, 0x0, +0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0x34108000, 0x96220000, +0x501024, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, +0x1600fff8, 0x0, 0xc004be5, 0x0, 0x8f830054, 0x8004b8a, +0x24020004, 0x8f830054, 0x3c020001, 0x8c4250a8, 0x2463ff9c, 0x431023, +0x2c420064, 0x1440029e, 0x24020002, 0x3c030001, 0x8c6350ac, 0x10620297, +0x2c620003, 0x14400296, 0x24020011, 0x24020003, 0x10620005, 0x24020004, +0x10620291, 0x2402000f, 0x8004b98, 0x24020011, 0x8004b98, 0x24020005, +0x24020014, 0xa7a20010, 0x27b10010, 0x8021, 0xc004bbf, 0x24040001, +0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, 0x2021, +0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, +0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, +0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020012, 0x10400002, +0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020012, +0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0x34108000, 0x96220000, +0x501024, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, +0x1600fff8, 0x0, 0xc004be5, 0x0, 0x8f830054, 0x8004b8a, +0x24020006, 0x8f830054, 0x3c020001, 0x8c4250a8, 0x2463ff9c, 0x431023, +0x2c420064, 0x14400250, 0x24020007, 0x8004b98, 0x0, 0x24020006, +0xa7a20010, 0x27b10010, 0x8021, 0xc004bbf, 0x24040001, 0x26100001, +0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, 0x2021, 0xc004bbf, +0x24040001, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0x24100010, +0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, +0x1600fffa, 0x32020001, 0x24100010, 0x32020013, 0x10400002, 0x2021, +0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020013, 0xc004bbf, +0x24040001, 0xc004bbf, 0x2021, 0x34108000, 0x96220000, 0x501024, +0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fff8, +0x0, 0xc004be5, 0x0, 0x8f830054, 0x8004b8a, 0x24020008, +0x8f830054, 0x3c020001, 0x8c4250a8, 0x2463ff9c, 0x431023, 0x2c420064, +0x1440020f, 0x24020009, 0x8004b98, 0x0, 0x27b10010, 0xa7a00010, +0x8021, 0xc004bbf, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, +0x0, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0xc004bbf, +0x24040001, 0xc004bbf, 0x2021, 0x24100010, 0x32020001, 0x10400002, +0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020001, +0x24100010, 0x32020018, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, +0x108042, 0x1600fffa, 0x32020018, 0xc004be5, 0x34108000, 0xc004be5, +0x0, 0xc004b9f, 0x0, 0x50400005, 0x108042, 0x96220000, +0x501025, 0xa6220000, 0x108042, 0x1600fff7, 0x0, 0xc004be5, +0x8021, 0x97a20010, 0x27b10010, 0x34420001, 0xa7a20010, 0xc004bbf, +0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, +0x2021, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, -0xc004b3f, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020017, -0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, -0x32020017, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 0x34108000, -0x96220000, 0x501024, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, -0x108042, 0x1600fff8, 0x0, 0xc004b65, 0x0, 0x8f830054, -0x8004b0a, 0x2402000c, 0x8f830054, 0x3c020001, 0x8c424e98, 0x2463ff9c, -0x431023, 0x2c420064, 0x14400127, 0x24020012, 0x8004b18, 0x0, -0x27b10010, 0xa7a00010, 0x8021, 0xc004b3f, 0x24040001, 0x26100001, -0x2e020020, 0x1440fffb, 0x0, 0xc004b3f, 0x2021, 0xc004b3f, -0x24040001, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 0x24100010, -0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, -0x1600fffa, 0x32020001, 0x24100010, 0x32020014, 0x10400002, 0x2021, -0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x32020014, 0xc004b65, -0x34108000, 0xc004b65, 0x0, 0xc004b1f, 0x0, 0x50400005, +0xc004bbf, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, +0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, +0x32020018, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0x34108000, +0x96220000, 0x501024, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, +0x108042, 0x1600fff8, 0x0, 0xc004be5, 0x0, 0x8f830054, +0x8004b8a, 0x2402000a, 0x8f830054, 0x3c020001, 0x8c4250a8, 0x2463ff9c, +0x431023, 0x2c420064, 0x1440019b, 0x2402000b, 0x8004b98, 0x0, +0x27b10010, 0xa7a00010, 0x8021, 0xc004bbf, 0x24040001, 0x26100001, +0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, 0x2021, 0xc004bbf, +0x24040001, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0x24100010, +0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, +0x1600fffa, 0x32020001, 0x24100010, 0x32020017, 0x10400002, 0x2021, +0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020017, 0xc004be5, +0x34108000, 0xc004be5, 0x0, 0xc004b9f, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, 0x1600fff7, -0x0, 0xc004b65, 0x8021, 0x97a20010, 0x27b10010, 0x34420010, -0xa7a20010, 0xc004b3f, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0xc004b3f, -0x2021, 0xc004b3f, 0x24040001, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x32020001, -0x24100010, 0x32020014, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, -0x108042, 0x1600fffa, 0x32020014, 0xc004b3f, 0x24040001, 0xc004b3f, +0x0, 0xc004be5, 0x8021, 0x97a20010, 0x27b10010, 0x34420700, +0xa7a20010, 0xc004bbf, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, +0x0, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0xc004bbf, +0x2021, 0xc004bbf, 0x24040001, 0x24100010, 0x32020001, 0x10400002, +0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020001, +0x24100010, 0x32020017, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, +0x108042, 0x1600fffa, 0x32020017, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, 0x2021, -0x24040001, 0xc004b3f, 0x108042, 0x1600fff8, 0x0, 0xc004b65, -0x0, 0x8f830054, 0x8004b0a, 0x24020013, 0x8f830054, 0x3c020001, -0x8c424e98, 0x2463ff9c, 0x431023, 0x2c420064, 0x144000b3, 0x2402000d, -0x8004b18, 0x0, 0x27b10010, 0xa7a00010, 0x8021, 0xc004b3f, -0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004b3f, -0x2021, 0xc004b3f, 0x24040001, 0xc004b3f, 0x24040001, 0xc004b3f, +0x24040001, 0xc004bbf, 0x108042, 0x1600fff8, 0x0, 0xc004be5, +0x0, 0x8f830054, 0x8004b8a, 0x2402000c, 0x8f830054, 0x3c020001, +0x8c4250a8, 0x2463ff9c, 0x431023, 0x2c420064, 0x14400127, 0x24020012, +0x8004b98, 0x0, 0x27b10010, 0xa7a00010, 0x8021, 0xc004bbf, +0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, +0x2021, 0xc004bbf, 0x24040001, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, -0xc004b3f, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, -0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, -0x32020018, 0xc004b65, 0x34108000, 0xc004b65, 0x0, 0xc004b1f, +0xc004bbf, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020014, +0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, +0x32020014, 0xc004be5, 0x34108000, 0xc004be5, 0x0, 0xc004b9f, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, -0x108042, 0x1600fff7, 0x0, 0xc004b65, 0x8021, 0x97a20010, -0x27b10010, 0x3042fffe, 0xa7a20010, 0xc004b3f, 0x24040001, 0x26100001, -0x2e020020, 0x1440fffb, 0x0, 0xc004b3f, 0x2021, 0xc004b3f, -0x24040001, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0x24100010, -0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, -0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021, -0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x32020018, 0xc004b3f, -0x24040001, 0xc004b3f, 0x2021, 0x34108000, 0x96220000, 0x501024, -0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fff8, -0x0, 0xc004b65, 0x0, 0x8f830054, 0x8004b0a, 0x2402000e, -0x24020840, 0xa7a20010, 0x27b10010, 0x8021, 0xc004b3f, 0x24040001, -0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004b3f, 0x2021, -0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, -0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, -0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020013, 0x10400002, -0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x32020013, -0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 0x34108000, 0x96220000, -0x501024, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, -0x1600fff8, 0x0, 0xc004b65, 0x0, 0x8f830054, 0x24020010, -0x3c010001, 0xac224e10, 0x3c010001, 0x8004b1a, 0xac234e98, 0x8f830054, -0x3c020001, 0x8c424e98, 0x2463ff9c, 0x431023, 0x2c420064, 0x14400004, -0x0, 0x24020011, 0x3c010001, 0xac224e10, 0x8fbf0020, 0x8fb1001c, -0x8fb00018, 0x3e00008, 0x27bd0028, 0x8f850044, 0x8f820044, 0x3c030001, -0x431025, 0x3c030008, 0xaf820044, 0x8f840054, 0x8f820054, 0xa32824, -0x8004b2b, 0x24840001, 0x8f820054, 0x821023, 0x2c420002, 0x1440fffc, -0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, -0x8f830054, 0x8f820054, 0x8004b39, 0x24630001, 0x8f820054, 0x621023, -0x2c420002, 0x1440fffc, 0x0, 0x3e00008, 0xa01021, 0x8f830044, -0x3c02fff0, 0x3442ffff, 0x42480, 0x621824, 0x3c020002, 0x822025, -0x641825, 0xaf830044, 0x8f820044, 0x3c030001, 0x431025, 0xaf820044, -0x8f830054, 0x8f820054, 0x8004b51, 0x24630001, 0x8f820054, 0x621023, +0x108042, 0x1600fff7, 0x0, 0xc004be5, 0x8021, 0x97a20010, +0x27b10010, 0x34420010, 0xa7a20010, 0xc004bbf, 0x24040001, 0x26100001, +0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, 0x2021, 0xc004bbf, +0x24040001, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0x24100010, +0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, +0x1600fffa, 0x32020001, 0x24100010, 0x32020014, 0x10400002, 0x2021, +0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020014, 0xc004bbf, +0x24040001, 0xc004bbf, 0x2021, 0x34108000, 0x96220000, 0x501024, +0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fff8, +0x0, 0xc004be5, 0x0, 0x8f830054, 0x8004b8a, 0x24020013, +0x8f830054, 0x3c020001, 0x8c4250a8, 0x2463ff9c, 0x431023, 0x2c420064, +0x144000b3, 0x2402000d, 0x8004b98, 0x0, 0x27b10010, 0xa7a00010, +0x8021, 0xc004bbf, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, +0x0, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0xc004bbf, +0x24040001, 0xc004bbf, 0x2021, 0x24100010, 0x32020001, 0x10400002, +0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020001, +0x24100010, 0x32020018, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, +0x108042, 0x1600fffa, 0x32020018, 0xc004be5, 0x34108000, 0xc004be5, +0x0, 0xc004b9f, 0x0, 0x50400005, 0x108042, 0x96220000, +0x501025, 0xa6220000, 0x108042, 0x1600fff7, 0x0, 0xc004be5, +0x8021, 0x97a20010, 0x27b10010, 0x3042fffe, 0xa7a20010, 0xc004bbf, +0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, +0x2021, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0xc004bbf, +0x24040001, 0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, +0xc004bbf, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, +0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, +0x32020018, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0x34108000, +0x96220000, 0x501024, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, +0x108042, 0x1600fff8, 0x0, 0xc004be5, 0x0, 0x8f830054, +0x8004b8a, 0x2402000e, 0x24020840, 0xa7a20010, 0x27b10010, 0x8021, +0xc004bbf, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, +0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, +0xc004bbf, 0x24040001, 0x24100010, 0x32020001, 0x10400002, 0x2021, +0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, +0x32020013, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, +0x1600fffa, 0x32020013, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, +0x34108000, 0x96220000, 0x501024, 0x10400002, 0x2021, 0x24040001, +0xc004bbf, 0x108042, 0x1600fff8, 0x0, 0xc004be5, 0x0, +0x8f830054, 0x24020010, 0x3c010001, 0xac225020, 0x3c010001, 0x8004b9a, +0xac2350a8, 0x8f830054, 0x3c020001, 0x8c4250a8, 0x2463ff9c, 0x431023, +0x2c420064, 0x14400004, 0x0, 0x24020011, 0x3c010001, 0xac225020, +0x8fbf0020, 0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0028, 0x8f850044, +0x8f820044, 0x3c030001, 0x431025, 0x3c030008, 0xaf820044, 0x8f840054, +0x8f820054, 0xa32824, 0x8004bab, 0x24840001, 0x8f820054, 0x821023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, -0x431024, 0xaf820044, 0x8f830054, 0x8f820054, 0x8004b5f, 0x24630001, +0x431024, 0xaf820044, 0x8f830054, 0x8f820054, 0x8004bb9, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x3e00008, -0x0, 0x8f820044, 0x3c03fff0, 0x3463ffff, 0x431024, 0xaf820044, -0x8f820044, 0x3c030001, 0x431025, 0xaf820044, 0x8f830054, 0x8f820054, -0x8004b73, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, -0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, -0x8f830054, 0x8f820054, 0x8004b81, 0x24630001, 0x8f820054, 0x621023, -0x2c420002, 0x1440fffc, 0x0, 0x3e00008, 0x0, 0x0, -0x27bdffe8, 0xafbf0010, 0x3c030001, 0x771821, 0x8c63839c, 0x24020008, -0x1462021c, 0x803021, 0x3c020001, 0x8c424e88, 0x14400033, 0x0, -0x8f850224, 0x38a30020, 0x2c630001, 0x38a20010, 0x2c420001, 0x621825, -0x1460000d, 0x38a30030, 0x2c630001, 0x38a20400, 0x2c420001, 0x621825, -0x14600007, 0x38a30402, 0x2c630001, 0x38a20404, 0x2c420001, 0x621825, -0x10600005, 0x0, 0xc0041e7, 0x0, 0x8004bc1, 0x2402000e, -0xc004323, 0x0, 0x3c050001, 0x8ca54dec, 0xc004f33, 0x24040001, -0x3c030001, 0x8c634dec, 0x24020004, 0x14620005, 0x2403fffb, 0x3c020001, -0x8c424de8, 0x8004bbd, 0x2403fff7, 0x3c020001, 0x8c424de8, 0x431024, -0x3c010001, 0xac224de8, 0x2402000e, 0x3c010001, 0xc0041e7, 0xac226eb0, -0x8004dab, 0x0, 0x8f820220, 0x3c030400, 0x431024, 0x10400027, -0x2403ffbf, 0x8f850224, 0x3c020001, 0x8c426ebc, 0xa32024, 0x431024, -0x1482000c, 0x0, 0x3c020001, 0x8c426ec0, 0x24420001, 0x3c010001, -0xac226ec0, 0x2c420002, 0x14400008, 0x24020001, 0x3c010001, 0x8004be1, -0xac226ee0, 0x3c010001, 0xac206ec0, 0x3c010001, 0xac206ee0, 0x3c020001, -0x8c426ee0, 0x10400006, 0x30a20040, 0x10400004, 0x24020001, 0x3c010001, -0x8004bec, 0xac226ee4, 0x3c010001, 0xac206ee4, 0x3c010001, 0xac256ebc, -0x3c010001, 0x8004bfc, 0xac206ef0, 0x24020001, 0x3c010001, 0xac226ef0, -0x3c010001, 0xac206ee0, 0x3c010001, 0xac206ec0, 0x3c010001, 0xac206ee4, -0x3c010001, 0xac206ebc, 0x3c030001, 0x8c636eb0, 0x3c020001, 0x8c426eb4, -0x10620003, 0x3c020200, 0x3c010001, 0xac236eb4, 0xc21024, 0x10400007, -0x2463ffff, 0x8f820220, 0x24030001, 0x3c010001, 0xac234df0, 0x8004da9, -0x3c03f700, 0x2c62000e, 0x10400198, 0x31080, 0x3c010001, 0x220821, -0x8c224cc0, 0x400008, 0x0, 0x8ee20000, 0x3c03fdff, 0x3463ffff, -0x431024, 0xaee20000, 0x3c010001, 0xac206ee0, 0x3c010001, 0xac206ec0, -0x3c010001, 0xac206ef0, 0x3c010001, 0xac206ebc, 0x3c010001, 0xac206ee4, -0x3c010001, 0xac206ed8, 0x3c010001, 0xac206ed0, 0xc00470a, 0xaf800224, -0x24020002, 0x3c010001, 0xac226eb0, 0xc0041e7, 0x0, 0xaf800204, -0x8f820200, 0x2403fffd, 0x431024, 0xaf820200, 0x3c010001, 0xac206f00, -0x8f830054, 0x3c020001, 0x8c426ed8, 0x24040001, 0x3c010001, 0xac246eec, -0x24420001, 0x3c010001, 0xac226ed8, 0x2c420004, 0x3c010001, 0xac236ed4, -0x14400006, 0x24020003, 0x3c010001, 0xac244df0, 0x3c010001, 0x8004da7, -0xac206ed8, 0x3c010001, 0x8004da7, 0xac226eb0, 0x8f830054, 0x3c020001, -0x8c426ed4, 0x2463d8f0, 0x431023, 0x2c422710, 0x14400154, 0x24020004, -0x3c010001, 0x8004da7, 0xac226eb0, 0x3c040001, 0x8c844e8c, 0x3c010001, -0xc004dae, 0xac206ec8, 0x3c020001, 0x8c426efc, 0xaf820204, 0x8f820204, -0x30420030, 0x1440013c, 0x24020002, 0x3c030001, 0x8c636efc, 0x24020005, -0x3c010001, 0xac226eb0, 0x3c010001, 0x8004da7, 0xac236f00, 0x3c020001, -0x8c426ee0, 0x10400139, 0x0, 0x3c020001, 0x8c426ebc, 0x10400135, -0x0, 0x3c010001, 0xac226ee8, 0x24020003, 0x3c010001, 0xac226ec0, -0x8004d3a, 0x24020006, 0x3c010001, 0xac206ec8, 0x8f820204, 0x34420040, -0xaf820204, 0x3c020001, 0x8c426f00, 0x24030007, 0x3c010001, 0xac236eb0, -0x34420040, 0x3c010001, 0xac226f00, 0x3c020001, 0x8c426ee0, 0x10400005, -0x0, 0x3c020001, 0x8c426ebc, 0x10400110, 0x24020002, 0x3c050001, -0x24a56ec0, 0x8ca20000, 0x2c424e21, 0x1040010a, 0x24020002, 0x3c020001, -0x8c426ee4, 0x1040010f, 0x2404ffbf, 0x3c020001, 0x8c426ebc, 0x3c030001, -0x8c636ee8, 0x441024, 0x641824, 0x14430007, 0x24020001, 0x24020003, -0xaca20000, 0x24020008, 0x3c010001, 0x8004da7, 0xac226eb0, 0x3c010001, -0x8004da7, 0xac226eb0, 0x3c020001, 0x8c426eec, 0x1040000c, 0x24020001, -0x3c040001, 0xc004dbb, 0x8c846ebc, 0x3c020001, 0x8c426f08, 0x14400005, -0x24020001, 0x3c020001, 0x8c426f04, 0x10400006, 0x24020001, 0x3c010001, -0xac224df0, 0x3c010001, 0x8004da7, 0xac206ed8, 0x8f820204, 0x34420040, -0xaf820204, 0x3c020001, 0x8c426f00, 0x3c030001, 0x8c636ed0, 0x34420040, -0x3c010001, 0xac226f00, 0x3c020001, 0x8c426ebc, 0x2c630001, 0x318c0, -0x3c010001, 0xac236ed0, 0x30420008, 0x3c010001, 0xac226ecc, 0x8f830054, -0x24020009, 0x3c010001, 0xac226eb0, 0x3c010001, 0x8004da7, 0xac236ed4, -0x8f830054, 0x3c020001, 0x8c426ed4, 0x2463d8f0, 0x431023, 0x2c422710, -0x144000b6, 0x0, 0x3c020001, 0x8c426ee0, 0x10400005, 0x0, -0x3c020001, 0x8c426ebc, 0x104000b7, 0x24020002, 0x3c030001, 0x24636ec0, -0x8c620000, 0x2c424e21, 0x104000b1, 0x24020002, 0x3c020001, 0x8c426eec, -0x1040000e, 0x0, 0x3c020001, 0x8c426ebc, 0x3c010001, 0xac206eec, -0x30420080, 0x1040002f, 0x2402000c, 0x8f820204, 0x30420080, 0x1440000c, -0x24020003, 0x8004d27, 0x2402000c, 0x3c020001, 0x8c426ebc, 0x30420080, -0x14400005, 0x24020003, 0x8f820204, 0x30420080, 0x1040001f, 0x24020003, -0xac620000, 0x2402000a, 0x3c010001, 0xac226eb0, 0x3c040001, 0x24846ef8, -0x8c820000, 0x3c030001, 0x8c636ed0, 0x431025, 0xaf820204, 0x8c830000, -0x3c040001, 0x8c846ed0, 0x2402000b, 0x3c010001, 0xac226eb0, 0x641825, -0x3c010001, 0xac236f00, 0x3c050001, 0x24a56ec0, 0x8ca20000, 0x2c424e21, -0x1040007d, 0x24020002, 0x3c020001, 0x8c426ef0, 0x10400005, 0x0, -0x2402000c, 0x3c010001, 0x8004da7, 0xac226eb0, 0x3c020001, 0x8c426ee0, -0x1040007a, 0x0, 0x3c040001, 0x8c846ebc, 0x1080006c, 0x30820008, -0x3c030001, 0x8c636ecc, 0x10620072, 0x24020003, 0x3c010001, 0xac246ee8, -0xaca20000, 0x24020006, 0x3c010001, 0x8004da7, 0xac226eb0, 0x8f8400f0, -0x276217f8, 0x14820002, 0x24850008, 0x27651000, 0x8f8200f4, 0x10a20007, -0x3c038000, 0x34630040, 0x3c020001, 0x24424d90, 0xac820000, 0xac830004, -0xaf8500f0, 0x8f820200, 0x34420002, 0xaf820200, 0x8f830054, 0x2402000d, -0x3c010001, 0xac226eb0, 0x3c010001, 0xac236ed4, 0x8f830054, 0x3c020001, -0x8c426ed4, 0x2463d8f0, 0x431023, 0x2c422710, 0x1440003a, 0x0, -0x3c020001, 0x8c426ef0, 0x10400029, 0x2402000e, 0x3c030001, 0x8c636f04, -0x3c010001, 0x14600015, 0xac226eb0, 0xc004323, 0x0, 0x3c050001, -0x8ca54dec, 0xc004f33, 0x24040001, 0x3c030001, 0x8c634dec, 0x24020004, -0x14620005, 0x2403fffb, 0x3c020001, 0x8c424de8, 0x8004d76, 0x2403fff7, -0x3c020001, 0x8c424de8, 0x431024, 0x3c010001, 0xac224de8, 0x8ee20000, -0x3c030200, 0x431025, 0xaee20000, 0x8f820224, 0x3c010001, 0xac226f0c, -0x8f820220, 0x2403fffb, 0x431024, 0xaf820220, 0x8f820220, 0x34420002, -0x8004da7, 0xaf820220, 0x3c020001, 0x8c426ee0, 0x10400005, 0x0, -0x3c020001, 0x8c426ebc, 0x1040000f, 0x24020002, 0x3c020001, 0x8c426ec0, -0x2c424e21, 0x1040000a, 0x24020002, 0x3c020001, 0x8c426ee0, 0x1040000f, -0x0, 0x3c020001, 0x8c426ebc, 0x1440000b, 0x0, 0x24020002, -0x3c010001, 0x8004da7, 0xac226eb0, 0x3c020001, 0x8c426ee0, 0x10400003, -0x0, 0xc0041e7, 0x0, 0x8f820220, 0x3c03f700, 0x431025, -0xaf820220, 0x8fbf0010, 0x3e00008, 0x27bd0018, 0x3c030001, 0x24636f08, -0x8c620000, 0x10400005, 0x34422000, 0x3c010001, 0xac226efc, 0x8004db9, -0xac600000, 0x3c010001, 0xac246efc, 0x3e00008, 0x0, 0x27bdffe0, -0x30820030, 0xafbf0018, 0x3c010001, 0xac226f04, 0x14400067, 0x3c02ffff, -0x34421f0e, 0x821024, 0x14400061, 0x24020030, 0x30822000, 0x1040005d, -0x30838000, 0x31a02, 0x30820001, 0x21200, 0x3c040001, 0x8c844e8c, -0x621825, 0x331c2, 0x3c030001, 0x24634e6c, 0x30828000, 0x21202, -0x30840001, 0x42200, 0x441025, 0x239c2, 0x61080, 0x431021, -0x471021, 0x90430000, 0x24020001, 0x10620025, 0x0, 0x10600007, -0x24020002, 0x10620013, 0x24020003, 0x1062002c, 0x3c05000f, 0x8004e1d, -0x0, 0x8f820200, 0x2403feff, 0x431024, 0xaf820200, 0x8f820220, -0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220, 0x3c010001, 0xac206f44, -0x3c010001, 0x8004e28, 0xac206f4c, 0x8f820200, 0x34420100, 0xaf820200, -0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220, 0x24020100, -0x3c010001, 0xac226f44, 0x3c010001, 0x8004e28, 0xac206f4c, 0x8f820200, -0x2403feff, 0x431024, 0xaf820200, 0x8f820220, 0x3c030001, 0x431025, -0xaf820220, 0x3c010001, 0xac206f44, 0x3c010001, 0x8004e28, 0xac236f4c, -0x8f820200, 0x34420100, 0xaf820200, 0x8f820220, 0x3c030001, 0x431025, -0xaf820220, 0x24020100, 0x3c010001, 0xac226f44, 0x3c010001, 0x8004e28, -0xac236f4c, 0x34a5ffff, 0x3c040001, 0x24844cf8, 0xafa30010, 0xc0023a7, -0xafa00014, 0x8004e28, 0x0, 0x24020030, 0x3c010001, 0xac226f08, -0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0, 0x27bdffc8, 0xafb10024, -0x808821, 0xafb3002c, 0xa09821, 0xafb00020, 0xc08021, 0x3c040001, -0x24844d10, 0x3c050009, 0x3c020001, 0x8c424dec, 0x34a59001, 0x2203021, -0x2603821, 0xafbf0030, 0xafb20028, 0xa7a0001a, 0xafb00014, 0xc0023a7, -0xafa20010, 0x24020002, 0x126200e9, 0x2e620003, 0x10400005, 0x24020001, -0x1262000a, 0x3c02fffb, 0x8004f2c, 0x0, 0x24020004, 0x1262006d, -0x24020008, 0x1262006c, 0x3c02ffec, 0x8004f2c, 0x0, 0x3442ffff, -0x2028024, 0x119140, 0x3c010001, 0x320821, 0xac306f1c, 0x3c024000, -0x2021024, 0x10400046, 0x1023c2, 0x30840030, 0x101382, 0x3042000c, -0x3c030001, 0x24634e14, 0x431021, 0x823821, 0x3c020020, 0x2021024, -0x10400006, 0x24020100, 0x3c010001, 0x320821, 0xac226f20, 0x8004e6f, -0x3c020080, 0x3c010001, 0x320821, 0xac206f20, 0x3c020080, 0x2021024, -0x10400006, 0x111940, 0x3c020001, 0x3c010001, 0x230821, 0x8004e7b, -0xac226f28, 0x111140, 0x3c010001, 0x220821, 0xac206f28, 0x94e30000, -0x32024000, 0x10400003, 0xa7a30018, 0x34624000, 0xa7a20018, 0x24040001, -0x94e20002, 0x24050004, 0x24e60002, 0x34420001, 0xc004782, 0xa4e20002, -0x24040001, 0x2821, 0xc004782, 0x27a60018, 0x3c020001, 0x8c424dec, -0x24110001, 0x3c010001, 0xac314df8, 0x14530004, 0x32028000, 0xc0041e7, -0x0, 0x32028000, 0x10400095, 0x0, 0xc0041e7, 0x0, -0x24020002, 0x3c010001, 0xac314df0, 0x3c010001, 0x8004f2c, 0xac224dec, -0x24040001, 0x24050004, 0x27b0001a, 0xc004782, 0x2003021, 0x24040001, -0x2821, 0xc004782, 0x2003021, 0x3c020001, 0x521021, 0x8c426f14, -0x3c040001, 0x8c844dec, 0x3c03bfff, 0x3463ffff, 0x3c010001, 0xac334df8, -0x431024, 0x3c010001, 0x320821, 0x10930074, 0xac226f14, 0x8004f2c, -0x0, 0x3c02ffec, 0x3442ffff, 0x2028024, 0x3c020008, 0x2028025, -0x111140, 0x3c010001, 0x220821, 0xac306f18, 0x3c022000, 0x2021024, -0x10400005, 0x24020001, 0x3c010001, 0xac224e88, 0x8004ecd, 0x3c024000, -0x3c010001, 0xac204e88, 0x3c024000, 0x2021024, 0x1440001c, 0x0, -0x3c020001, 0x8c424e88, 0x10400007, 0x24022020, 0x3c010001, 0xac224e8c, -0x24020001, 0x3c010001, 0x370821, 0xac22839c, 0x3c04bfff, 0x111940, -0x3c020001, 0x431021, 0x8c426f10, 0x3c050001, 0x8ca54dec, 0x3484ffff, -0x441024, 0x3c010001, 0x230821, 0xac226f10, 0x24020001, 0x10a20044, -0x0, 0x8004f2a, 0x0, 0x3c020001, 0x8c424e88, 0x1040001c, -0x24022000, 0x3c010001, 0xac224e8c, 0x3c0300a0, 0x2031024, 0x14430005, -0x111140, 0x3402a000, 0x3c010001, 0x8004f25, 0xac224e8c, 0x3c030001, -0x621821, 0x8c636f18, 0x3c020020, 0x621024, 0x10400004, 0x24022001, -0x3c010001, 0x8004f25, 0xac224e8c, 0x3c020080, 0x621024, 0x1040001f, -0x3402a001, 0x3c010001, 0x8004f25, 0xac224e8c, 0x3c020020, 0x2021024, -0x10400007, 0x111940, 0x24020100, 0x3c010001, 0x230821, 0xac226f24, -0x8004f19, 0x3c020080, 0x111140, 0x3c010001, 0x220821, 0xac206f24, +0xa01021, 0x8f830044, 0x3c02fff0, 0x3442ffff, 0x42480, 0x621824, +0x3c020002, 0x822025, 0x641825, 0xaf830044, 0x8f820044, 0x3c030001, +0x431025, 0xaf820044, 0x8f830054, 0x8f820054, 0x8004bd1, 0x24630001, +0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820044, +0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, 0x8f830054, 0x8f820054, +0x8004bdf, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, +0x0, 0x3e00008, 0x0, 0x8f820044, 0x3c03fff0, 0x3463ffff, +0x431024, 0xaf820044, 0x8f820044, 0x3c030001, 0x431025, 0xaf820044, +0x8f830054, 0x8f820054, 0x8004bf3, 0x24630001, 0x8f820054, 0x621023, +0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, +0x431024, 0xaf820044, 0x8f830054, 0x8f820054, 0x8004c01, 0x24630001, +0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x3e00008, +0x0, 0x0, 0x27bdffe8, 0xafbf0010, 0x3c030001, 0x771821, +0x8c63839c, 0x24020008, 0x1462021c, 0x803021, 0x3c020001, 0x8c425098, +0x14400033, 0x0, 0x8f850224, 0x38a30020, 0x2c630001, 0x38a20010, +0x2c420001, 0x621825, 0x1460000d, 0x38a30030, 0x2c630001, 0x38a20400, +0x2c420001, 0x621825, 0x14600007, 0x38a30402, 0x2c630001, 0x38a20404, +0x2c420001, 0x621825, 0x10600005, 0x0, 0xc00428b, 0x0, +0x8004c41, 0x2402000e, 0xc0043cd, 0x0, 0x3c050001, 0x8ca54ffc, +0xc004fb3, 0x24040001, 0x3c030001, 0x8c634ffc, 0x24020004, 0x14620005, +0x2403fffb, 0x3c020001, 0x8c424ff8, 0x8004c3d, 0x2403fff7, 0x3c020001, +0x8c424ff8, 0x431024, 0x3c010001, 0xac224ff8, 0x2402000e, 0x3c010001, +0xc00428b, 0xac2270c0, 0x8004e2b, 0x0, 0x8f820220, 0x3c030400, +0x431024, 0x10400027, 0x2403ffbf, 0x8f850224, 0x3c020001, 0x8c4270cc, +0xa32024, 0x431024, 0x1482000c, 0x0, 0x3c020001, 0x8c4270d0, +0x24420001, 0x3c010001, 0xac2270d0, 0x2c420002, 0x14400008, 0x24020001, +0x3c010001, 0x8004c61, 0xac2270f0, 0x3c010001, 0xac2070d0, 0x3c010001, +0xac2070f0, 0x3c020001, 0x8c4270f0, 0x10400006, 0x30a20040, 0x10400004, +0x24020001, 0x3c010001, 0x8004c6c, 0xac2270f4, 0x3c010001, 0xac2070f4, +0x3c010001, 0xac2570cc, 0x3c010001, 0x8004c7c, 0xac207100, 0x24020001, +0x3c010001, 0xac227100, 0x3c010001, 0xac2070f0, 0x3c010001, 0xac2070d0, +0x3c010001, 0xac2070f4, 0x3c010001, 0xac2070cc, 0x3c030001, 0x8c6370c0, +0x3c020001, 0x8c4270c4, 0x10620003, 0x3c020200, 0x3c010001, 0xac2370c4, +0xc21024, 0x10400007, 0x2463ffff, 0x8f820220, 0x24030001, 0x3c010001, +0xac235000, 0x8004e29, 0x3c03f700, 0x2c62000e, 0x10400198, 0x31080, +0x3c010001, 0x220821, 0x8c224ed0, 0x400008, 0x0, 0x8ee20000, +0x3c03fdff, 0x3463ffff, 0x431024, 0xaee20000, 0x3c010001, 0xac2070f0, +0x3c010001, 0xac2070d0, 0x3c010001, 0xac207100, 0x3c010001, 0xac2070cc, +0x3c010001, 0xac2070f4, 0x3c010001, 0xac2070e8, 0x3c010001, 0xac2070e0, +0xc00478a, 0xaf800224, 0x24020002, 0x3c010001, 0xac2270c0, 0xc00428b, +0x0, 0xaf800204, 0x8f820200, 0x2403fffd, 0x431024, 0xaf820200, +0x3c010001, 0xac207110, 0x8f830054, 0x3c020001, 0x8c4270e8, 0x24040001, +0x3c010001, 0xac2470fc, 0x24420001, 0x3c010001, 0xac2270e8, 0x2c420004, +0x3c010001, 0xac2370e4, 0x14400006, 0x24020003, 0x3c010001, 0xac245000, +0x3c010001, 0x8004e27, 0xac2070e8, 0x3c010001, 0x8004e27, 0xac2270c0, +0x8f830054, 0x3c020001, 0x8c4270e4, 0x2463d8f0, 0x431023, 0x2c422710, +0x14400154, 0x24020004, 0x3c010001, 0x8004e27, 0xac2270c0, 0x3c040001, +0x8c84509c, 0x3c010001, 0xc004e2e, 0xac2070d8, 0x3c020001, 0x8c42710c, +0xaf820204, 0x8f820204, 0x30420030, 0x1440013c, 0x24020002, 0x3c030001, +0x8c63710c, 0x24020005, 0x3c010001, 0xac2270c0, 0x3c010001, 0x8004e27, +0xac237110, 0x3c020001, 0x8c4270f0, 0x10400139, 0x0, 0x3c020001, +0x8c4270cc, 0x10400135, 0x0, 0x3c010001, 0xac2270f8, 0x24020003, +0x3c010001, 0xac2270d0, 0x8004dba, 0x24020006, 0x3c010001, 0xac2070d8, +0x8f820204, 0x34420040, 0xaf820204, 0x3c020001, 0x8c427110, 0x24030007, +0x3c010001, 0xac2370c0, 0x34420040, 0x3c010001, 0xac227110, 0x3c020001, +0x8c4270f0, 0x10400005, 0x0, 0x3c020001, 0x8c4270cc, 0x10400110, +0x24020002, 0x3c050001, 0x24a570d0, 0x8ca20000, 0x2c424e21, 0x1040010a, +0x24020002, 0x3c020001, 0x8c4270f4, 0x1040010f, 0x2404ffbf, 0x3c020001, +0x8c4270cc, 0x3c030001, 0x8c6370f8, 0x441024, 0x641824, 0x14430007, +0x24020001, 0x24020003, 0xaca20000, 0x24020008, 0x3c010001, 0x8004e27, +0xac2270c0, 0x3c010001, 0x8004e27, 0xac2270c0, 0x3c020001, 0x8c4270fc, +0x1040000c, 0x24020001, 0x3c040001, 0xc004e3b, 0x8c8470cc, 0x3c020001, +0x8c427118, 0x14400005, 0x24020001, 0x3c020001, 0x8c427114, 0x10400006, +0x24020001, 0x3c010001, 0xac225000, 0x3c010001, 0x8004e27, 0xac2070e8, +0x8f820204, 0x34420040, 0xaf820204, 0x3c020001, 0x8c427110, 0x3c030001, +0x8c6370e0, 0x34420040, 0x3c010001, 0xac227110, 0x3c020001, 0x8c4270cc, +0x2c630001, 0x318c0, 0x3c010001, 0xac2370e0, 0x30420008, 0x3c010001, +0xac2270dc, 0x8f830054, 0x24020009, 0x3c010001, 0xac2270c0, 0x3c010001, +0x8004e27, 0xac2370e4, 0x8f830054, 0x3c020001, 0x8c4270e4, 0x2463d8f0, +0x431023, 0x2c422710, 0x144000b6, 0x0, 0x3c020001, 0x8c4270f0, +0x10400005, 0x0, 0x3c020001, 0x8c4270cc, 0x104000b7, 0x24020002, +0x3c030001, 0x246370d0, 0x8c620000, 0x2c424e21, 0x104000b1, 0x24020002, +0x3c020001, 0x8c4270fc, 0x1040000e, 0x0, 0x3c020001, 0x8c4270cc, +0x3c010001, 0xac2070fc, 0x30420080, 0x1040002f, 0x2402000c, 0x8f820204, +0x30420080, 0x1440000c, 0x24020003, 0x8004da7, 0x2402000c, 0x3c020001, +0x8c4270cc, 0x30420080, 0x14400005, 0x24020003, 0x8f820204, 0x30420080, +0x1040001f, 0x24020003, 0xac620000, 0x2402000a, 0x3c010001, 0xac2270c0, +0x3c040001, 0x24847108, 0x8c820000, 0x3c030001, 0x8c6370e0, 0x431025, +0xaf820204, 0x8c830000, 0x3c040001, 0x8c8470e0, 0x2402000b, 0x3c010001, +0xac2270c0, 0x641825, 0x3c010001, 0xac237110, 0x3c050001, 0x24a570d0, +0x8ca20000, 0x2c424e21, 0x1040007d, 0x24020002, 0x3c020001, 0x8c427100, +0x10400005, 0x0, 0x2402000c, 0x3c010001, 0x8004e27, 0xac2270c0, +0x3c020001, 0x8c4270f0, 0x1040007a, 0x0, 0x3c040001, 0x8c8470cc, +0x1080006c, 0x30820008, 0x3c030001, 0x8c6370dc, 0x10620072, 0x24020003, +0x3c010001, 0xac2470f8, 0xaca20000, 0x24020006, 0x3c010001, 0x8004e27, +0xac2270c0, 0x8f8400f0, 0x276217f8, 0x14820002, 0x24850008, 0x27651000, +0x8f8200f4, 0x10a20007, 0x3c038000, 0x34630040, 0x3c020001, 0x24424fa0, +0xac820000, 0xac830004, 0xaf8500f0, 0x8f820200, 0x34420002, 0xaf820200, +0x8f830054, 0x2402000d, 0x3c010001, 0xac2270c0, 0x3c010001, 0xac2370e4, +0x8f830054, 0x3c020001, 0x8c4270e4, 0x2463d8f0, 0x431023, 0x2c422710, +0x1440003a, 0x0, 0x3c020001, 0x8c427100, 0x10400029, 0x2402000e, +0x3c030001, 0x8c637114, 0x3c010001, 0x14600015, 0xac2270c0, 0xc0043cd, +0x0, 0x3c050001, 0x8ca54ffc, 0xc004fb3, 0x24040001, 0x3c030001, +0x8c634ffc, 0x24020004, 0x14620005, 0x2403fffb, 0x3c020001, 0x8c424ff8, +0x8004df6, 0x2403fff7, 0x3c020001, 0x8c424ff8, 0x431024, 0x3c010001, +0xac224ff8, 0x8ee20000, 0x3c030200, 0x431025, 0xaee20000, 0x8f820224, +0x3c010001, 0xac22711c, 0x8f820220, 0x2403fffb, 0x431024, 0xaf820220, +0x8f820220, 0x34420002, 0x8004e27, 0xaf820220, 0x3c020001, 0x8c4270f0, +0x10400005, 0x0, 0x3c020001, 0x8c4270cc, 0x1040000f, 0x24020002, +0x3c020001, 0x8c4270d0, 0x2c424e21, 0x1040000a, 0x24020002, 0x3c020001, +0x8c4270f0, 0x1040000f, 0x0, 0x3c020001, 0x8c4270cc, 0x1440000b, +0x0, 0x24020002, 0x3c010001, 0x8004e27, 0xac2270c0, 0x3c020001, +0x8c4270f0, 0x10400003, 0x0, 0xc00428b, 0x0, 0x8f820220, +0x3c03f700, 0x431025, 0xaf820220, 0x8fbf0010, 0x3e00008, 0x27bd0018, +0x3c030001, 0x24637118, 0x8c620000, 0x10400005, 0x34422000, 0x3c010001, +0xac22710c, 0x8004e39, 0xac600000, 0x3c010001, 0xac24710c, 0x3e00008, +0x0, 0x27bdffe0, 0x30820030, 0xafbf0018, 0x3c010001, 0xac227114, +0x14400067, 0x3c02ffff, 0x34421f0e, 0x821024, 0x14400061, 0x24020030, +0x30822000, 0x1040005d, 0x30838000, 0x31a02, 0x30820001, 0x21200, +0x3c040001, 0x8c84509c, 0x621825, 0x331c2, 0x3c030001, 0x2463507c, +0x30828000, 0x21202, 0x30840001, 0x42200, 0x441025, 0x239c2, +0x61080, 0x431021, 0x471021, 0x90430000, 0x24020001, 0x10620025, +0x0, 0x10600007, 0x24020002, 0x10620013, 0x24020003, 0x1062002c, +0x3c05000f, 0x8004e9d, 0x0, 0x8f820200, 0x2403feff, 0x431024, +0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220, +0x3c010001, 0xac207154, 0x3c010001, 0x8004ea8, 0xac20715c, 0x8f820200, +0x34420100, 0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, +0xaf820220, 0x24020100, 0x3c010001, 0xac227154, 0x3c010001, 0x8004ea8, +0xac20715c, 0x8f820200, 0x2403feff, 0x431024, 0xaf820200, 0x8f820220, +0x3c030001, 0x431025, 0xaf820220, 0x3c010001, 0xac207154, 0x3c010001, +0x8004ea8, 0xac23715c, 0x8f820200, 0x34420100, 0xaf820200, 0x8f820220, +0x3c030001, 0x431025, 0xaf820220, 0x24020100, 0x3c010001, 0xac227154, +0x3c010001, 0x8004ea8, 0xac23715c, 0x34a5ffff, 0x3c040001, 0x24844f08, +0xafa30010, 0xc002403, 0xafa00014, 0x8004ea8, 0x0, 0x24020030, +0x3c010001, 0xac227118, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0, +0x27bdffc8, 0xafb10024, 0x808821, 0xafb3002c, 0xa09821, 0xafb00020, +0xc08021, 0x3c040001, 0x24844f20, 0x3c050009, 0x3c020001, 0x8c424ffc, +0x34a59001, 0x2203021, 0x2603821, 0xafbf0030, 0xafb20028, 0xa7a0001a, +0xafb00014, 0xc002403, 0xafa20010, 0x24020002, 0x126200e9, 0x2e620003, +0x10400005, 0x24020001, 0x1262000a, 0x3c02fffb, 0x8004fac, 0x0, +0x24020004, 0x1262006d, 0x24020008, 0x1262006c, 0x3c02ffec, 0x8004fac, +0x0, 0x3442ffff, 0x2028024, 0x119140, 0x3c010001, 0x320821, +0xac30712c, 0x3c024000, 0x2021024, 0x10400046, 0x1023c2, 0x30840030, +0x101382, 0x3042000c, 0x3c030001, 0x24635024, 0x431021, 0x823821, +0x3c020020, 0x2021024, 0x10400006, 0x24020100, 0x3c010001, 0x320821, +0xac227130, 0x8004eef, 0x3c020080, 0x3c010001, 0x320821, 0xac207130, 0x3c020080, 0x2021024, 0x10400006, 0x111940, 0x3c020001, 0x3c010001, -0x230821, 0x8004f25, 0xac226f2c, 0x111140, 0x3c010001, 0x220821, -0xac206f2c, 0x3c030001, 0x8c634dec, 0x24020001, 0x10620003, 0x0, -0xc0041e7, 0x0, 0x8fbf0030, 0x8fb3002c, 0x8fb20028, 0x8fb10024, -0x8fb00020, 0x3e00008, 0x27bd0038, 0x27bdffd0, 0xafb40028, 0x80a021, -0xafb20020, 0x9021, 0xafb30024, 0x9821, 0xafb1001c, 0x8821, -0x24020002, 0xafbf002c, 0xafb00018, 0xa7a00012, 0x10a20068, 0xa7a00010, -0x2ca20003, 0x10400005, 0x24020001, 0x10a2000a, 0x148140, 0x8004ff0, -0x2201021, 0x24020004, 0x10a2005e, 0x24020008, 0x10a2005d, 0x142140, -0x8004ff0, 0x2201021, 0x3c030001, 0x701821, 0x8c636f1c, 0x3c024000, -0x621024, 0x14400009, 0x24040001, 0x3c027fff, 0x3442ffff, 0x628824, -0x3c010001, 0x300821, 0xac316f14, 0x8004ff0, 0x2201021, 0x24050001, -0xc004740, 0x27a60010, 0x24040001, 0x24050001, 0xc004740, 0x27a60010, -0x97a20010, 0x30420004, 0x10400034, 0x3c114000, 0x3c030001, 0x8c634e9c, -0x24020003, 0x10620008, 0x2c620004, 0x14400029, 0x3c028000, 0x24020004, -0x10620014, 0x24040001, 0x8004f99, 0x3c028000, 0x24040001, 0x24050011, -0x27b00012, 0xc004740, 0x2003021, 0x24040001, 0x24050011, 0xc004740, -0x2003021, 0x97a30012, 0x30624000, 0x10400002, 0x3c130010, 0x3c130008, -0x3c120001, 0x8004f96, 0x30628000, 0x24050014, 0x27b00012, 0xc004740, -0x2003021, 0x24040001, 0x24050014, 0xc004740, 0x2003021, 0x97a30012, -0x30621000, 0x10400002, 0x3c130010, 0x3c130008, 0x3c120001, 0x30620800, -0x54400001, 0x3c120002, 0x3c028000, 0x2221025, 0x2531825, 0x8004fa3, -0x438825, 0x3c110001, 0x2308821, 0x8e316f1c, 0x3c027fff, 0x3442ffff, -0x2228824, 0x141140, 0x3c010001, 0x220821, 0xac316f14, 0x8004ff0, -0x2201021, 0x142140, 0x3c030001, 0x641821, 0x8c636f18, 0x3c024000, -0x621024, 0x14400008, 0x3c027fff, 0x3442ffff, 0x628824, 0x3c010001, -0x240821, 0xac316f10, 0x8004ff0, 0x2201021, 0x3c020001, 0x8c424dfc, -0x1040002d, 0x3c11c00c, 0x3c020001, 0x8c424e88, 0x3c03e00c, 0x3c010001, -0x240821, 0x8c246f24, 0x2102b, 0x21023, 0x431024, 0x10800004, -0x518825, 0x3c020020, 0x8004fcd, 0x2228825, 0x3c02ffdf, 0x3442ffff, -0x2228824, 0x141140, 0x3c010001, 0x220821, 0x8c226f2c, 0x10400003, -0x3c020080, 0x8004fd8, 0x2228825, 0x3c02ff7f, 0x3442ffff, 0x2228824, -0x3c020001, 0x8c424e60, 0x10400002, 0x3c020800, 0x2228825, 0x3c020001, -0x8c424e64, 0x10400002, 0x3c020400, 0x2228825, 0x3c020001, 0x8c424e68, -0x10400006, 0x3c020100, 0x8004feb, 0x2228825, 0x3c027fff, 0x3442ffff, -0x628824, 0x141140, 0x3c010001, 0x220821, 0xac316f10, 0x2201021, -0x8fbf002c, 0x8fb40028, 0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018, -0x3e00008, 0x27bd0030, 0x27bdffd8, 0xafb40020, 0x80a021, 0xafbf0024, -0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010, 0x8f900200, 0x3c030001, -0x8c634dec, 0x8f930220, 0x24020002, 0x106200b1, 0x2c620003, 0x10400005, -0x24020001, 0x1062000a, 0x141940, 0x80050b7, 0x0, 0x24020004, -0x1062005a, 0x24020008, 0x10620059, 0x149140, 0x80050b7, 0x0, -0x3c040001, 0x832021, 0x8c846f1c, 0x3c110001, 0x2238821, 0x8e316f14, -0x3c024000, 0x821024, 0x1040003e, 0x3c020008, 0x2221024, 0x10400020, -0x36100002, 0x3c020001, 0x431021, 0x8c426f20, 0x10400005, 0x36100020, -0x36100100, 0x3c020020, 0x800502f, 0x2228825, 0x2402feff, 0x2028024, +0x230821, 0x8004efb, 0xac227138, 0x111140, 0x3c010001, 0x220821, +0xac207138, 0x94e30000, 0x32024000, 0x10400003, 0xa7a30018, 0x34624000, +0xa7a20018, 0x24040001, 0x94e20002, 0x24050004, 0x24e60002, 0x34420001, +0xc004802, 0xa4e20002, 0x24040001, 0x2821, 0xc004802, 0x27a60018, +0x3c020001, 0x8c424ffc, 0x24110001, 0x3c010001, 0xac315008, 0x14530004, +0x32028000, 0xc00428b, 0x0, 0x32028000, 0x10400095, 0x0, +0xc00428b, 0x0, 0x24020002, 0x3c010001, 0xac315000, 0x3c010001, +0x8004fac, 0xac224ffc, 0x24040001, 0x24050004, 0x27b0001a, 0xc004802, +0x2003021, 0x24040001, 0x2821, 0xc004802, 0x2003021, 0x3c020001, +0x521021, 0x8c427124, 0x3c040001, 0x8c844ffc, 0x3c03bfff, 0x3463ffff, +0x3c010001, 0xac335008, 0x431024, 0x3c010001, 0x320821, 0x10930074, +0xac227124, 0x8004fac, 0x0, 0x3c02ffec, 0x3442ffff, 0x2028024, +0x3c020008, 0x2028025, 0x111140, 0x3c010001, 0x220821, 0xac307128, +0x3c022000, 0x2021024, 0x10400005, 0x24020001, 0x3c010001, 0xac225098, +0x8004f4d, 0x3c024000, 0x3c010001, 0xac205098, 0x3c024000, 0x2021024, +0x1440001c, 0x0, 0x3c020001, 0x8c425098, 0x10400007, 0x24022020, +0x3c010001, 0xac22509c, 0x24020001, 0x3c010001, 0x370821, 0xac22839c, +0x3c04bfff, 0x111940, 0x3c020001, 0x431021, 0x8c427120, 0x3c050001, +0x8ca54ffc, 0x3484ffff, 0x441024, 0x3c010001, 0x230821, 0xac227120, +0x24020001, 0x10a20044, 0x0, 0x8004faa, 0x0, 0x3c020001, +0x8c425098, 0x1040001c, 0x24022000, 0x3c010001, 0xac22509c, 0x3c0300a0, +0x2031024, 0x14430005, 0x111140, 0x3402a000, 0x3c010001, 0x8004fa5, +0xac22509c, 0x3c030001, 0x621821, 0x8c637128, 0x3c020020, 0x621024, +0x10400004, 0x24022001, 0x3c010001, 0x8004fa5, 0xac22509c, 0x3c020080, +0x621024, 0x1040001f, 0x3402a001, 0x3c010001, 0x8004fa5, 0xac22509c, +0x3c020020, 0x2021024, 0x10400007, 0x111940, 0x24020100, 0x3c010001, +0x230821, 0xac227134, 0x8004f99, 0x3c020080, 0x111140, 0x3c010001, +0x220821, 0xac207134, 0x3c020080, 0x2021024, 0x10400006, 0x111940, +0x3c020001, 0x3c010001, 0x230821, 0x8004fa5, 0xac22713c, 0x111140, +0x3c010001, 0x220821, 0xac20713c, 0x3c030001, 0x8c634ffc, 0x24020001, +0x10620003, 0x0, 0xc00428b, 0x0, 0x8fbf0030, 0x8fb3002c, +0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008, 0x27bd0038, 0x27bdffd0, +0xafb40028, 0x80a021, 0xafb20020, 0x9021, 0xafb30024, 0x9821, +0xafb1001c, 0x8821, 0x24020002, 0xafbf002c, 0xafb00018, 0xa7a00012, +0x10a20068, 0xa7a00010, 0x2ca20003, 0x10400005, 0x24020001, 0x10a2000a, +0x148140, 0x8005070, 0x2201021, 0x24020004, 0x10a2005e, 0x24020008, +0x10a2005d, 0x142140, 0x8005070, 0x2201021, 0x3c030001, 0x701821, +0x8c63712c, 0x3c024000, 0x621024, 0x14400009, 0x24040001, 0x3c027fff, +0x3442ffff, 0x628824, 0x3c010001, 0x300821, 0xac317124, 0x8005070, +0x2201021, 0x24050001, 0xc0047c0, 0x27a60010, 0x24040001, 0x24050001, +0xc0047c0, 0x27a60010, 0x97a20010, 0x30420004, 0x10400034, 0x3c114000, +0x3c030001, 0x8c6350ac, 0x24020003, 0x10620008, 0x2c620004, 0x14400029, +0x3c028000, 0x24020004, 0x10620014, 0x24040001, 0x8005019, 0x3c028000, +0x24040001, 0x24050011, 0x27b00012, 0xc0047c0, 0x2003021, 0x24040001, +0x24050011, 0xc0047c0, 0x2003021, 0x97a30012, 0x30624000, 0x10400002, +0x3c130010, 0x3c130008, 0x3c120001, 0x8005016, 0x30628000, 0x24050014, +0x27b00012, 0xc0047c0, 0x2003021, 0x24040001, 0x24050014, 0xc0047c0, +0x2003021, 0x97a30012, 0x30621000, 0x10400002, 0x3c130010, 0x3c130008, +0x3c120001, 0x30620800, 0x54400001, 0x3c120002, 0x3c028000, 0x2221025, +0x2531825, 0x8005023, 0x438825, 0x3c110001, 0x2308821, 0x8e31712c, +0x3c027fff, 0x3442ffff, 0x2228824, 0x141140, 0x3c010001, 0x220821, +0xac317124, 0x8005070, 0x2201021, 0x142140, 0x3c030001, 0x641821, +0x8c637128, 0x3c024000, 0x621024, 0x14400008, 0x3c027fff, 0x3442ffff, +0x628824, 0x3c010001, 0x240821, 0xac317120, 0x8005070, 0x2201021, +0x3c020001, 0x8c42500c, 0x1040002d, 0x3c11c00c, 0x3c020001, 0x8c425098, +0x3c03e00c, 0x3c010001, 0x240821, 0x8c247134, 0x2102b, 0x21023, +0x431024, 0x10800004, 0x518825, 0x3c020020, 0x800504d, 0x2228825, 0x3c02ffdf, 0x3442ffff, 0x2228824, 0x141140, 0x3c010001, 0x220821, -0x8c226f28, 0x10400005, 0x3c020001, 0x2629825, 0x3c020080, 0x800504e, -0x2228825, 0x3c02fffe, 0x3442ffff, 0x2629824, 0x3c02ff7f, 0x3442ffff, -0x800504e, 0x2228824, 0x2402fedf, 0x2028024, 0x3c02fffe, 0x3442ffff, -0x2629824, 0x3c02ff5f, 0x3442ffff, 0x2228824, 0x3c010001, 0x230821, -0xac206f20, 0x3c010001, 0x230821, 0xac206f28, 0xc00470a, 0x0, -0xaf900200, 0xaf930220, 0x8f820220, 0x2403fffb, 0x431024, 0xaf820220, -0x8f820220, 0x34420002, 0xaf820220, 0x8005065, 0x141140, 0x8f820200, -0x2403fffd, 0x431024, 0xc00470a, 0xaf820200, 0x3c02bfff, 0x3442ffff, -0xc0041e7, 0x2228824, 0x141140, 0x3c010001, 0x220821, 0x80050b7, -0xac316f14, 0x149140, 0x3c040001, 0x922021, 0x8c846f18, 0x3c110001, -0x2328821, 0x8e316f10, 0x3c024000, 0x821024, 0x14400011, 0x0, -0x3c020001, 0x8c424e88, 0x14400006, 0x3c02bfff, 0x8f820200, 0x34420002, -0xc00470a, 0xaf820200, 0x3c02bfff, 0x3442ffff, 0xc0041e7, 0x2228824, -0x3c010001, 0x320821, 0x80050b7, 0xac316f10, 0x3c020001, 0x8c424e88, -0x1440002d, 0x141140, 0x3c020020, 0x821024, 0x10400007, 0x36100020, -0x24020100, 0x3c010001, 0x320821, 0xac226f24, 0x8005097, 0x36100100, -0x3c010001, 0x320821, 0xac206f24, 0x2402feff, 0x2028024, 0x3c020080, -0x821024, 0x10400007, 0x141940, 0x3c020001, 0x3c010001, 0x230821, -0xac226f2c, 0x80050a8, 0x2629825, 0x141140, 0x3c010001, 0x220821, -0xac206f2c, 0x3c02fffe, 0x3442ffff, 0x2629824, 0xc00470a, 0x0, -0xaf900200, 0xaf930220, 0x8f820220, 0x2403fffb, 0x431024, 0xaf820220, -0x8f820220, 0x34420002, 0xaf820220, 0x141140, 0x3c010001, 0x220821, -0xac316f10, 0x8fbf0024, 0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, -0x8fb00010, 0x3e00008, 0x27bd0028, 0x0, 0x0 }; -u32 tigonFwData[(MAX_DATA_LEN/4) + 1] = { +0x8c22713c, 0x10400003, 0x3c020080, 0x8005058, 0x2228825, 0x3c02ff7f, +0x3442ffff, 0x2228824, 0x3c020001, 0x8c425070, 0x10400002, 0x3c020800, +0x2228825, 0x3c020001, 0x8c425074, 0x10400002, 0x3c020400, 0x2228825, +0x3c020001, 0x8c425078, 0x10400006, 0x3c020100, 0x800506b, 0x2228825, +0x3c027fff, 0x3442ffff, 0x628824, 0x141140, 0x3c010001, 0x220821, +0xac317120, 0x2201021, 0x8fbf002c, 0x8fb40028, 0x8fb30024, 0x8fb20020, +0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0030, 0x27bdffd8, 0xafb40020, +0x80a021, 0xafbf0024, 0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010, +0x8f900200, 0x3c030001, 0x8c634ffc, 0x8f930220, 0x24020002, 0x106200b1, +0x2c620003, 0x10400005, 0x24020001, 0x1062000a, 0x141940, 0x8005137, +0x0, 0x24020004, 0x1062005a, 0x24020008, 0x10620059, 0x149140, +0x8005137, 0x0, 0x3c040001, 0x832021, 0x8c84712c, 0x3c110001, +0x2238821, 0x8e317124, 0x3c024000, 0x821024, 0x1040003e, 0x3c020008, +0x2221024, 0x10400020, 0x36100002, 0x3c020001, 0x431021, 0x8c427130, +0x10400005, 0x36100020, 0x36100100, 0x3c020020, 0x80050af, 0x2228825, +0x2402feff, 0x2028024, 0x3c02ffdf, 0x3442ffff, 0x2228824, 0x141140, +0x3c010001, 0x220821, 0x8c227138, 0x10400005, 0x3c020001, 0x2629825, +0x3c020080, 0x80050ce, 0x2228825, 0x3c02fffe, 0x3442ffff, 0x2629824, +0x3c02ff7f, 0x3442ffff, 0x80050ce, 0x2228824, 0x2402fedf, 0x2028024, +0x3c02fffe, 0x3442ffff, 0x2629824, 0x3c02ff5f, 0x3442ffff, 0x2228824, +0x3c010001, 0x230821, 0xac207130, 0x3c010001, 0x230821, 0xac207138, +0xc00478a, 0x0, 0xaf900200, 0xaf930220, 0x8f820220, 0x2403fffb, +0x431024, 0xaf820220, 0x8f820220, 0x34420002, 0xaf820220, 0x80050e5, +0x141140, 0x8f820200, 0x2403fffd, 0x431024, 0xc00478a, 0xaf820200, +0x3c02bfff, 0x3442ffff, 0xc00428b, 0x2228824, 0x141140, 0x3c010001, +0x220821, 0x8005137, 0xac317124, 0x149140, 0x3c040001, 0x922021, +0x8c847128, 0x3c110001, 0x2328821, 0x8e317120, 0x3c024000, 0x821024, +0x14400011, 0x0, 0x3c020001, 0x8c425098, 0x14400006, 0x3c02bfff, +0x8f820200, 0x34420002, 0xc00478a, 0xaf820200, 0x3c02bfff, 0x3442ffff, +0xc00428b, 0x2228824, 0x3c010001, 0x320821, 0x8005137, 0xac317120, +0x3c020001, 0x8c425098, 0x1440002d, 0x141140, 0x3c020020, 0x821024, +0x10400007, 0x36100020, 0x24020100, 0x3c010001, 0x320821, 0xac227134, +0x8005117, 0x36100100, 0x3c010001, 0x320821, 0xac207134, 0x2402feff, +0x2028024, 0x3c020080, 0x821024, 0x10400007, 0x141940, 0x3c020001, +0x3c010001, 0x230821, 0xac22713c, 0x8005128, 0x2629825, 0x141140, +0x3c010001, 0x220821, 0xac20713c, 0x3c02fffe, 0x3442ffff, 0x2629824, +0xc00478a, 0x0, 0xaf900200, 0xaf930220, 0x8f820220, 0x2403fffb, +0x431024, 0xaf820220, 0x8f820220, 0x34420002, 0xaf820220, 0x141140, +0x3c010001, 0x220821, 0xac317120, 0x8fbf0024, 0x8fb40020, 0x8fb3001c, +0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0028, 0x0, +0x0 }; +u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __init = { 0x416c7465, 0x6f6e2041, 0x63654e49, 0x43205600, 0x416c7465, 0x6f6e2041, 0x63654e49, 0x43205600, 0x42424242, 0x0, 0x0, 0x0, 0x135430, 0x13e7fc, 0x0, 0x0, 0x0, 0x0, @@ -2792,7 +2814,7 @@ u32 tigonFwData[(MAX_DATA_LEN/4) + 1] = { 0x12000060, 0x12000180, 0x120001e0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30001, 0x1, 0x30201, 0x0, 0x0 }; -u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] = { +u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __init = { 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, 0x6f6e2f66, 0x776d6169, 0x6e2e632c, 0x7620312e, 0x312e322e, 0x31312031, 0x3939382f, 0x30342f32, @@ -2813,114 +2835,114 @@ u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] = { 0x0, 0x6576526e, 0x6746756c, 0x6c000000, 0x0, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, 0x6f6e2f63, 0x6f6d6d61, -0x6e642e63, 0x2c762031, 0x2e312e32, 0x2e382031, 0x3939382f, 0x30342f32, -0x37203232, 0x3a31333a, 0x33392073, 0x6875616e, 0x67204578, 0x70202400, -0x4e4f636f, 0x6d616e64, 0x0, 0x68737465, 0x5f455252, 0x0, -0x412d4572, 0x72427563, 0x0, 0x4552524f, 0x522d4164, 0x64000000, -0x656e714d, 0x45765046, 0x61696c00, 0x656e714d, 0x45764661, 0x696c0000, -0x6661696c, 0x456e454d, 0x0, 0x442d4572, 0x724c6173, 0x74000000, -0x442d4572, 0x72320000, 0x6d437374, 0x4d644552, 0x52000000, 0x70726f6d, -0x4d644552, 0x52000000, 0x46696c74, 0x4d644552, 0x52000000, 0x636d645f, -0x45525200, 0x3f456e71, 0x45767400, 0x3f6e6f51, 0x64457650, 0x0, -0x6576526e, 0x6746756c, 0x6c000000, 0x0, 0x6da4, 0x7e7c, -0x6d3c, 0x85c8, 0x815c, 0x8614, 0x8614, 0x6e58, -0x7578, 0x7dcc, 0x7f68, 0x7f34, 0x8614, 0x7d30, -0x7f8c, 0x6d68, 0x808c, 0x0, 0x24486561, 0x6465723a, -0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, -0x2f66772f, 0x636f6d6d, 0x6f6e2f64, 0x6d612e63, 0x2c762031, 0x2e312e32, -0x2e332031, 0x3939382f, 0x30342f32, 0x37203232, 0x3a31333a, 0x34312073, -0x6875616e, 0x67204578, 0x70202400, 0x646d6172, 0x6441544e, 0x0, -0x646d6177, 0x7241544e, 0x0, 0x0, 0x0, 0x0, -0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, -0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, 0x6f6e2f74, 0x72616365, -0x2e632c76, 0x20312e31, 0x2e322e32, 0x20313939, 0x382f3034, 0x2f323720, -0x32323a31, 0x333a3530, 0x20736875, 0x616e6720, 0x45787020, 0x24000000, -0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, -0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, 0x6f6e2f64, 0x6174612e, -0x632c7620, 0x312e312e, 0x322e3220, 0x31393938, 0x2f30342f, 0x32372032, -0x323a3133, 0x3a343020, 0x73687561, 0x6e672045, 0x78702024, 0x0, -0x46575f56, 0x45525349, 0x4f4e3a20, 0x23312046, 0x7269204f, 0x63742031, -0x36203130, 0x3a31333a, 0x30352050, 0x44542031, 0x39393800, 0x46575f43, -0x4f4d5049, 0x4c455f54, 0x494d453a, 0x2031303a, 0x31333a30, 0x35000000, -0x46575f43, 0x4f4d5049, 0x4c455f42, 0x593a2064, 0x65767263, 0x73000000, -0x46575f43, 0x4f4d5049, 0x4c455f48, 0x4f53543a, 0x20636f6d, 0x70757465, -0x0, 0x46575f43, 0x4f4d5049, 0x4c455f44, 0x4f4d4149, 0x4e3a2065, -0x6e672e61, 0x6374656f, 0x6e2e636f, 0x6d000000, 0x46575f43, 0x4f4d5049, -0x4c45523a, 0x20676363, 0x20766572, 0x73696f6e, 0x20322e37, 0x2e320000, +0x6e642e63, 0x2c762031, 0x2e312e31, 0x362e3120, 0x31393938, 0x2f31312f, +0x31392030, 0x323a3339, 0x3a323520, 0x73687561, 0x6e672045, 0x78702024, +0x0, 0x3f4d626f, 0x78457674, 0x0, 0x4e4f636f, 0x6d616e64, +0x0, 0x68737465, 0x5f455252, 0x0, 0x412d4572, 0x72427563, +0x0, 0x4552524f, 0x522d4164, 0x64000000, 0x656e714d, 0x45765046, +0x61696c00, 0x656e714d, 0x45764661, 0x696c0000, 0x6661696c, 0x456e454d, +0x0, 0x442d4572, 0x724c6173, 0x74000000, 0x442d4572, 0x72320000, +0x6d437374, 0x4d644552, 0x52000000, 0x70726f6d, 0x4d644552, 0x52000000, +0x46696c74, 0x4d644552, 0x52000000, 0x636d645f, 0x45525200, 0x3f456e71, +0x45767400, 0x3f6e6f51, 0x64457650, 0x0, 0x6576526e, 0x6746756c, +0x6c000000, 0x0, 0x6e90, 0x7fac, 0x6e28, 0x871c, +0x8298, 0x8768, 0x8768, 0x6f44, 0x7684, 0x7efc, +0x8098, 0x8064, 0x8768, 0x7e60, 0x80bc, 0x6e54, +0x81bc, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, +0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, +0x6f6e2f64, 0x6d612e63, 0x2c762031, 0x2e312e32, 0x2e332031, 0x3939382f, +0x30342f32, 0x37203232, 0x3a31333a, 0x34312073, 0x6875616e, 0x67204578, +0x70202400, 0x646d6172, 0x6441544e, 0x0, 0x646d6177, 0x7241544e, 0x0, 0x0, 0x0, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, -0x2f66772f, 0x636f6d6d, 0x6f6e2f6d, 0x656d2e63, 0x2c762031, 0x2e312e32, -0x2e322031, 0x3939382f, 0x30342f32, 0x37203232, 0x3a31333a, 0x34342073, -0x6875616e, 0x67204578, 0x70202400, 0x0, 0x24486561, 0x6465723a, -0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, -0x2f66772f, 0x636f6d6d, 0x6f6e2f73, 0x656e642e, 0x632c7620, 0x312e312e, -0x322e3820, 0x31393938, 0x2f30342f, 0x32372032, 0x323a3133, 0x3a343820, -0x73687561, 0x6e672045, 0x78702024, 0x0, 0x736e6464, 0x654e6f51, -0x20000000, 0x6e6f454e, 0x515f5458, 0x0, 0x736e6464, 0x744e6f51, -0x20000000, 0x3f6e6f51, 0x64547845, 0x0, 0x756e6b72, 0x64747970, -0x65000000, 0x0, 0xba70, 0xba70, 0xbb18, 0xac2c, -0xae2c, 0xbb18, 0xbb18, 0xbb18, 0xbb18, 0xbb18, -0xbb18, 0xbb18, 0xbb18, 0xbb18, 0xbb18, 0xbb18, -0xbb18, 0xbb18, 0xbb18, 0xae14, 0x24486561, 0x6465723a, -0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, -0x2f66772f, 0x636f6d6d, 0x6f6e2f72, 0x6563762e, 0x632c7620, 0x312e312e, -0x322e3139, 0x20313939, 0x382f3037, 0x2f323420, 0x32313a33, 0x303a3035, -0x20736875, 0x616e6720, 0x45787020, 0x24000000, 0x706b5278, 0x45525200, -0x66726d32, 0x4c617267, 0x65000000, 0x72784e6f, 0x52784264, 0x0, -0x72785144, 0x6d614446, 0x0, 0x72785144, 0x6d614246, 0x0, -0x3f6e6f51, 0x64527845, 0x0, 0x706b5278, 0x45525273, 0x0, -0x66726d32, 0x4c726753, 0x0, 0x72784e6f, 0x42645300, 0x3f724264, -0x446d6146, 0x0, 0x3f724a42, 0x64446d46, 0x0, 0x0, -0xf3c0, 0xf3c0, 0xf3c0, 0xf3c0, 0xf3c0, 0xf3c0, -0xf3c0, 0xf3c0, 0xf3c0, 0xf3c0, 0xf3c0, 0xf3c0, -0xf3c0, 0xf3c0, 0xf3c0, 0xf3b8, 0xf3b8, 0xf3b8, -0x572d444d, 0x41456e46, 0x0, 0x0, 0xfafc, 0xfe80, -0xfb18, 0xfe80, 0xfe80, 0xfe80, 0xfe80, 0xfe80, -0xfe80, 0xf44c, 0xfe80, 0xfe80, 0xfe80, 0xfe80, -0xfe80, 0xfe78, 0xfe78, 0xfe78, 0x24486561, 0x6465723a, -0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, -0x2f66772f, 0x636f6d6d, 0x6f6e2f6d, 0x61632e63, 0x2c762031, 0x2e312e32, -0x2e313220, 0x31393938, 0x2f30342f, 0x32372032, 0x323a3133, 0x3a343220, -0x73687561, 0x6e672045, 0x78702024, 0x0, 0x6d616374, 0x7841544e, -0x0, 0x4e745379, 0x6e264c6b, 0x0, 0x72656d61, 0x73737274, -0x0, 0x6c696e6b, 0x444f574e, 0x0, 0x656e714d, 0x45765046, -0x61696c00, 0x656e714d, 0x45764661, 0x696c0000, 0x6661696c, 0x456e454d, -0x0, 0x6c696e6b, 0x55500000, 0x0, 0x24486561, 0x6465723a, +0x2f66772f, 0x636f6d6d, 0x6f6e2f74, 0x72616365, 0x2e632c76, 0x20312e31, +0x2e322e32, 0x20313939, 0x382f3034, 0x2f323720, 0x32323a31, 0x333a3530, +0x20736875, 0x616e6720, 0x45787020, 0x24000000, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, -0x2f66772f, 0x636f6d6d, 0x6f6e2f63, 0x6b73756d, 0x2e632c76, 0x20312e31, -0x2e322e32, 0x20313939, 0x382f3034, 0x2f323720, 0x32323a31, 0x333a3339, -0x20736875, 0x616e6720, 0x45787020, 0x24000000, 0x50726f62, 0x65506879, -0x0, 0x6c6e6b41, 0x53535254, 0x0, 0x11680, 0x116b8, -0x116dc, 0x11710, 0x1173c, 0x11750, 0x1178c, 0x11ac4, -0x11864, 0x118a4, 0x118d4, 0x11914, 0x11944, 0x11980, -0x119c4, 0x11ac4, 0x0, 0x0, 0x11f5c, 0x1202c, -0x12104, 0x121d4, 0x12230, 0x1230c, 0x12334, 0x12410, -0x12438, 0x125e0, 0x12608, 0x127b0, 0x129a8, 0x12c3c, -0x12b50, 0x12c3c, 0x12c68, 0x127d8, 0x12980, 0x0, -0x13054, 0x130b4, 0x13130, 0x1315c, 0x131ac, 0x131e8, -0x1321c, 0x132a8, 0x13360, 0x13430, 0x13470, 0x134f4, -0x13550, 0x13684, 0x646f4261, 0x73655067, 0x0, 0x0, -0x0, 0x0, 0x73746d61, 0x634c4e4b, 0x0, 0x0, -0x0 }; +0x2f66772f, 0x636f6d6d, 0x6f6e2f64, 0x6174612e, 0x632c7620, 0x312e312e, +0x322e3220, 0x31393938, 0x2f30342f, 0x32372032, 0x323a3133, 0x3a343020, +0x73687561, 0x6e672045, 0x78702024, 0x0, 0x46575f56, 0x45525349, +0x4f4e3a20, 0x2331204d, 0x6f6e2044, 0x65632037, 0x2031343a, 0x35363a33, +0x30205053, 0x54203139, 0x39380000, 0x46575f43, 0x4f4d5049, 0x4c455f54, +0x494d453a, 0x2031343a, 0x35363a33, 0x30000000, 0x46575f43, 0x4f4d5049, +0x4c455f42, 0x593a2064, 0x65767263, 0x73000000, 0x46575f43, 0x4f4d5049, +0x4c455f48, 0x4f53543a, 0x20636f6d, 0x70757465, 0x0, 0x46575f43, +0x4f4d5049, 0x4c455f44, 0x4f4d4149, 0x4e3a2065, 0x6e672e61, 0x6374656f, +0x6e2e636f, 0x6d000000, 0x46575f43, 0x4f4d5049, 0x4c45523a, 0x20676363, +0x20766572, 0x73696f6e, 0x20322e37, 0x2e320000, 0x0, 0x0, +0x0, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, +0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, +0x6f6e2f6d, 0x656d2e63, 0x2c762031, 0x2e312e32, 0x2e322031, 0x3939382f, +0x30342f32, 0x37203232, 0x3a31333a, 0x34342073, 0x6875616e, 0x67204578, +0x70202400, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, +0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, +0x6f6e2f73, 0x656e642e, 0x632c7620, 0x312e312e, 0x322e3820, 0x31393938, +0x2f30342f, 0x32372032, 0x323a3133, 0x3a343820, 0x73687561, 0x6e672045, +0x78702024, 0x0, 0x736e6464, 0x654e6f51, 0x20000000, 0x6e6f454e, +0x515f5458, 0x0, 0x736e6464, 0x744e6f51, 0x20000000, 0x3f6e6f51, +0x64547845, 0x0, 0x756e6b72, 0x64747970, 0x65000000, 0x0, +0xbc88, 0xbc88, 0xbd30, 0xae2c, 0xb038, 0xbd30, +0xbd30, 0xbd30, 0xbd30, 0xbd30, 0xbd30, 0xbd30, +0xbd30, 0xbd30, 0xbd30, 0xbd30, 0xbd30, 0xbd30, +0xbd30, 0xb020, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, +0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, +0x6f6e2f72, 0x6563762e, 0x632c7620, 0x312e312e, 0x322e3139, 0x20313939, +0x382f3037, 0x2f323420, 0x32313a33, 0x303a3035, 0x20736875, 0x616e6720, +0x45787020, 0x24000000, 0x706b5278, 0x45525200, 0x66726d32, 0x4c617267, +0x65000000, 0x72784e6f, 0x52784264, 0x0, 0x72785144, 0x6d614446, +0x0, 0x72785144, 0x6d614246, 0x0, 0x3f6e6f51, 0x64527845, +0x0, 0x706b5278, 0x45525273, 0x0, 0x66726d32, 0x4c726753, +0x0, 0x72784e6f, 0x42645300, 0x3f724264, 0x446d6146, 0x0, +0x3f724a42, 0x64446d46, 0x0, 0x0, 0xf638, 0xf638, +0xf638, 0xf638, 0xf638, 0xf638, 0xf638, 0xf638, +0xf638, 0xf638, 0xf638, 0xf638, 0xf638, 0xf638, +0xf638, 0xf630, 0xf630, 0xf630, 0x572d444d, 0x41456e46, +0x0, 0x0, 0xfd80, 0x1011c, 0xfd9c, 0x1011c, +0x1011c, 0x1011c, 0x1011c, 0x1011c, 0x1011c, 0xf6c4, +0x1011c, 0x1011c, 0x1011c, 0x1011c, 0x1011c, 0x10114, +0x10114, 0x10114, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, +0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, +0x6f6e2f6d, 0x61632e63, 0x2c762031, 0x2e312e32, 0x2e313220, 0x31393938, +0x2f30342f, 0x32372032, 0x323a3133, 0x3a343220, 0x73687561, 0x6e672045, +0x78702024, 0x0, 0x6d616374, 0x7841544e, 0x0, 0x4e745379, +0x6e264c6b, 0x0, 0x72656d61, 0x73737274, 0x0, 0x6c696e6b, +0x444f574e, 0x0, 0x656e714d, 0x45765046, 0x61696c00, 0x656e714d, +0x45764661, 0x696c0000, 0x6661696c, 0x456e454d, 0x0, 0x6c696e6b, +0x55500000, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, +0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, +0x6f6e2f63, 0x6b73756d, 0x2e632c76, 0x20312e31, 0x2e322e32, 0x20313939, +0x382f3034, 0x2f323720, 0x32323a31, 0x333a3339, 0x20736875, 0x616e6720, +0x45787020, 0x24000000, 0x50726f62, 0x65506879, 0x0, 0x6c6e6b41, +0x53535254, 0x0, 0x11880, 0x118b8, 0x118dc, 0x11910, +0x1193c, 0x11950, 0x1198c, 0x11cc4, 0x11a64, 0x11aa4, +0x11ad4, 0x11b14, 0x11b44, 0x11b80, 0x11bc4, 0x11cc4, +0x0, 0x0, 0x1215c, 0x1222c, 0x12304, 0x123d4, +0x12430, 0x1250c, 0x12534, 0x12610, 0x12638, 0x127e0, +0x12808, 0x129b0, 0x12ba8, 0x12e3c, 0x12d50, 0x12e3c, +0x12e68, 0x129d8, 0x12b80, 0x0, 0x13254, 0x132b4, +0x13330, 0x1335c, 0x133ac, 0x133e8, 0x1341c, 0x134a8, +0x13560, 0x13630, 0x13670, 0x136f4, 0x13750, 0x13884, +0x646f4261, 0x73655067, 0x0, 0x0, 0x0, 0x0, +0x73746d61, 0x634c4e4b, 0x0, 0x0, 0x0 }; /* Generated by genfw.c */ int tigon2FwReleaseMajor = 0xc; int tigon2FwReleaseMinor = 0x1; -int tigon2FwReleaseFix = 0x4; +int tigon2FwReleaseFix = 0x6; u32 tigon2FwStartAddr = 0x4000; u32 tigon2FwTextAddr = 0x4000; -int tigon2FwTextLen = 0xe480; -u32 tigon2FwDataAddr = 0x131d0; +int tigon2FwTextLen = 0xe5b0; +u32 tigon2FwDataAddr = 0x13330; int tigon2FwDataLen = 0x170; -u32 tigon2FwRodataAddr = 0x12480; -int tigon2FwRodataLen = 0xd30; -u32 tigon2FwBssAddr = 0x133f0; +u32 tigon2FwRodataAddr = 0x125b0; +int tigon2FwRodataLen = 0xd60; +u32 tigon2FwBssAddr = 0x13550; int tigon2FwBssLen = 0x20c0; -u32 tigon2FwSbssAddr = 0x13340; +u32 tigon2FwSbssAddr = 0x134a0; int tigon2FwSbssLen = 0xa8; -u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { +u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __init = { 0x0, 0x10000003, 0x0, 0xd, 0xd, 0x3c1d0001, -0x8fbd3220, 0x3a0f021, 0x3c100000, 0x26104000, 0xc0010c0, 0x0, -0xd, 0x3c1d0001, 0x8fbd3224, 0x3a0f021, 0x3c100000, 0x26104000, +0x8fbd3380, 0x3a0f021, 0x3c100000, 0x26104000, 0xc0010c0, 0x0, +0xd, 0x3c1d0001, 0x8fbd3384, 0x3a0f021, 0x3c100000, 0x26104000, 0xc0016fe, 0x0, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, @@ -2930,14 +2952,14 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2000008, 0x0, 0x8001671, 0x3c0a0001, 0x8001671, 0x3c0a0002, 0x8001671, 0x0, -0x8002994, 0x0, 0x8001671, 0x3c0a0003, 0x8001671, 0x3c0a0004, -0x8003110, 0x0, 0x80019ba, 0x0, 0x8003608, 0x0, -0x8003597, 0x0, 0x8001671, 0x3c0a0006, 0x8001671, 0x3c0a0007, -0x8001671, 0x3c0a0008, 0x8001671, 0x3c0a0009, 0x8003679, 0x0, -0x8002bd5, 0x0, 0x8001671, 0x3c0a000b, 0x8001671, 0x3c0a000c, -0x8001671, 0x3c0a000d, 0x80026e0, 0x0, 0x80026b3, 0x0, +0x80029b8, 0x0, 0x8001671, 0x3c0a0003, 0x8001671, 0x3c0a0004, +0x8003134, 0x0, 0x80019ba, 0x0, 0x8003653, 0x0, +0x80035e2, 0x0, 0x8001671, 0x3c0a0006, 0x8001671, 0x3c0a0007, +0x8001671, 0x3c0a0008, 0x8001671, 0x3c0a0009, 0x80036c4, 0x0, +0x8002bf9, 0x0, 0x8001671, 0x3c0a000b, 0x8001671, 0x3c0a000c, +0x8001671, 0x3c0a000d, 0x80026ee, 0x0, 0x80026ad, 0x0, 0x8001671, 0x3c0a000e, 0x8001f40, 0x0, 0x80018c9, 0x0, -0x800196b, 0x0, 0x80038f7, 0x0, 0x80038e1, 0x0, +0x800196b, 0x0, 0x8003943, 0x0, 0x800392d, 0x0, 0x8001671, 0x0, 0x800184d, 0x0, 0x8001893, 0x0, 0x8001671, 0x3c0a0013, 0x8001671, 0x3c0a0014, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, @@ -2950,68 +2972,68 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x27bdffe0, 0x3c1cc000, 0xafbf0018, 0xc0028d0, 0xd021, 0x8f820040, +0x27bdffe0, 0x3c1cc000, 0xafbf0018, 0xc0028f4, 0xd021, 0x8f820040, 0x3c03f000, 0x431824, 0x3c025000, 0x10620005, 0x3c026000, 0x1062001a, 0x24020003, 0x10000030, 0x0, 0x8f820050, 0x3c030010, 0x431024, -0x50400013, 0x24020003, 0x3c030001, 0x2463c2d0, 0x3c020001, 0x2442c354, -0x431023, 0x3c010001, 0xac2333b8, 0x8f830140, 0x3c040001, 0x2484c35c, -0x3c010001, 0xac2233a4, 0x3c020001, 0x2442c3c4, 0x3c010001, 0xac2031d8, -0x10000013, 0x441023, 0x3c030001, 0x2463c3cc, 0xaf8200ec, 0x3c020001, -0x2442c408, 0x431023, 0x3c010001, 0xac2333b8, 0x8f830140, 0x3c040001, -0x2484c410, 0x3c010001, 0xac2233a4, 0x3c020001, 0x2442c438, 0x441023, -0x3c0100c0, 0xac203ffc, 0x3c010001, 0xac2433b0, 0x3c010001, 0xac2233ac, +0x50400013, 0x24020003, 0x3c030001, 0x2463c360, 0x3c020001, 0x2442c3e4, +0x431023, 0x3c010001, 0xac233518, 0x8f830140, 0x3c040001, 0x2484c3ec, +0x3c010001, 0xac223504, 0x3c020001, 0x2442c454, 0x3c010001, 0xac203338, +0x10000013, 0x441023, 0x3c030001, 0x2463c45c, 0xaf8200ec, 0x3c020001, +0x2442c498, 0x431023, 0x3c010001, 0xac233518, 0x8f830140, 0x3c040001, +0x2484c4a0, 0x3c010001, 0xac223504, 0x3c020001, 0x2442c4c8, 0x441023, +0x3c0100c0, 0xac203ffc, 0x3c010001, 0xac243510, 0x3c010001, 0xac22350c, 0x34630004, 0xaf830140, 0xc00169c, 0x0, 0x402821, 0x3c010001, -0xac253350, 0x3c020008, 0x10a2002c, 0x45102b, 0x14400006, 0x3c020010, +0xac2534b0, 0x3c020008, 0x10a2002c, 0x45102b, 0x14400006, 0x3c020010, 0x3c020004, 0x10a20007, 0x3c02ffff, 0x1000005b, 0x0, 0x10a20045, -0x3c030003, 0x10000057, 0x0, 0x34422e10, 0x3c030001, 0x246354b0, -0x3c040001, 0x8c8431d4, 0xa31823, 0x14800002, 0x622821, 0x24a5faa8, -0x2403f000, 0xa32824, 0x51082, 0x431024, 0x3c010001, 0xac223340, -0xa21023, 0x3c010001, 0xac223348, 0x3402a000, 0x3c010001, 0xac223358, -0x24020008, 0x3c010001, 0xac223360, 0x2402001f, 0x3c010001, 0xac223368, -0x24020016, 0x3c010001, 0xac22334c, 0x10000041, 0x3c08ffff, 0x3c02ffff, -0x34422e10, 0x3c030001, 0x246354b0, 0x3c040001, 0x8c8431d4, 0xa31823, +0x3c030003, 0x10000057, 0x0, 0x34422e10, 0x3c030001, 0x24635610, +0x3c040001, 0x8c843334, 0xa31823, 0x14800002, 0x622821, 0x24a5faa8, +0x2403f000, 0xa32824, 0x51082, 0x431024, 0x3c010001, 0xac2234a0, +0xa21023, 0x3c010001, 0xac2234a8, 0x3402a000, 0x3c010001, 0xac2234b8, +0x24020008, 0x3c010001, 0xac2234c0, 0x2402001f, 0x3c010001, 0xac2234c8, +0x24020016, 0x3c010001, 0xac2234ac, 0x10000041, 0x3c08ffff, 0x3c02ffff, +0x34422e10, 0x3c030001, 0x24635610, 0x3c040001, 0x8c843334, 0xa31823, 0x14800002, 0x622821, 0x24a5faa8, 0x2403f000, 0xa32824, 0x3c040003, -0x34842000, 0x510c2, 0x431024, 0x3c010001, 0xac223340, 0xa21023, -0x3c010001, 0xac223348, 0x24020008, 0x3c010001, 0xac223360, 0x2402001f, -0x3c010001, 0xac223368, 0x24020016, 0x3c010001, 0xac243358, 0x3c010001, -0xac22334c, 0x1000001f, 0x3c08ffff, 0x34632000, 0x3c020001, 0x3c010001, -0xac223340, 0x3c020007, 0x3c010001, 0xac223348, 0x24020008, 0x3c010001, -0xac223360, 0x2402001f, 0x3c010001, 0xac223368, 0x24020016, 0x3c010001, -0xac233358, 0x3c010001, 0xac22334c, 0x1000000b, 0x3c08ffff, 0x3c040001, -0x24842540, 0x3c050001, 0x8ca53350, 0x3021, 0x3821, 0xafa00010, -0xc0028eb, 0xafa00014, 0x3c08ffff, 0x35087e10, 0x3c0500bf, 0x34a5f000, -0x3c0600bf, 0x34c6e000, 0x3c070001, 0x8ce73340, 0x3c040001, 0x8c843348, -0x3c030020, 0x3c090001, 0x8d2931d0, 0x671023, 0x441023, 0x245bb000, -0x641823, 0x3c010001, 0xac233354, 0x671823, 0x27620ffc, 0x3c010001, -0xac223220, 0x27621ffc, 0xbb2823, 0xdb3023, 0x3c010001, 0xac233344, -0x3c010001, 0xac223224, 0xaf850150, 0xaf860250, 0x1120001b, 0x368b821, -0x33620fff, 0x10400008, 0x24050019, 0x3c040001, 0x2484254c, 0x3603021, -0x3821, 0xafa00010, 0xc0028eb, 0xafa00014, 0x3c1d0001, 0x8fbd31dc, -0x3a0f021, 0xc001684, 0x0, 0x3c020001, 0x8c4231e0, 0x3c030001, -0x8c6331e4, 0x2442fe00, 0x24630200, 0x3c010001, 0xac2231e0, 0x3c010001, -0x10000004, 0xac2331e4, 0x3c1d0001, 0x8fbd3220, 0x3a0f021, 0x3c020001, -0x8c4231d4, 0x1040000d, 0x26f6faa8, 0x3c020001, 0x8c4231e0, 0x3c030001, -0x8c6331e4, 0x3c160001, 0x8ed631e4, 0x2442faa8, 0x24630558, 0x3c010001, -0xac2231e0, 0x3c010001, 0xac2331e4, 0x3c020001, 0x8c4231d8, 0x14400003, -0x0, 0x3c010001, 0xac2031e0, 0xc0011ca, 0x0, 0x8fbf0018, +0x34842000, 0x510c2, 0x431024, 0x3c010001, 0xac2234a0, 0xa21023, +0x3c010001, 0xac2234a8, 0x24020008, 0x3c010001, 0xac2234c0, 0x2402001f, +0x3c010001, 0xac2234c8, 0x24020016, 0x3c010001, 0xac2434b8, 0x3c010001, +0xac2234ac, 0x1000001f, 0x3c08ffff, 0x34632000, 0x3c020001, 0x3c010001, +0xac2234a0, 0x3c020007, 0x3c010001, 0xac2234a8, 0x24020008, 0x3c010001, +0xac2234c0, 0x2402001f, 0x3c010001, 0xac2234c8, 0x24020016, 0x3c010001, +0xac2334b8, 0x3c010001, 0xac2234ac, 0x1000000b, 0x3c08ffff, 0x3c040001, +0x24842670, 0x3c050001, 0x8ca534b0, 0x3021, 0x3821, 0xafa00010, +0xc00290f, 0xafa00014, 0x3c08ffff, 0x35087e10, 0x3c0500bf, 0x34a5f000, +0x3c0600bf, 0x34c6e000, 0x3c070001, 0x8ce734a0, 0x3c040001, 0x8c8434a8, +0x3c030020, 0x3c090001, 0x8d293330, 0x671023, 0x441023, 0x245bb000, +0x641823, 0x3c010001, 0xac2334b4, 0x671823, 0x27620ffc, 0x3c010001, +0xac223380, 0x27621ffc, 0xbb2823, 0xdb3023, 0x3c010001, 0xac2334a4, +0x3c010001, 0xac223384, 0xaf850150, 0xaf860250, 0x1120001b, 0x368b821, +0x33620fff, 0x10400008, 0x24050019, 0x3c040001, 0x2484267c, 0x3603021, +0x3821, 0xafa00010, 0xc00290f, 0xafa00014, 0x3c1d0001, 0x8fbd333c, +0x3a0f021, 0xc001684, 0x0, 0x3c020001, 0x8c423340, 0x3c030001, +0x8c633344, 0x2442fe00, 0x24630200, 0x3c010001, 0xac223340, 0x3c010001, +0x10000004, 0xac233344, 0x3c1d0001, 0x8fbd3380, 0x3a0f021, 0x3c020001, +0x8c423334, 0x1040000d, 0x26f6faa8, 0x3c020001, 0x8c423340, 0x3c030001, +0x8c633344, 0x3c160001, 0x8ed63344, 0x2442faa8, 0x24630558, 0x3c010001, +0xac223340, 0x3c010001, 0xac233344, 0x3c020001, 0x8c423338, 0x14400003, +0x0, 0x3c010001, 0xac203340, 0xc0011ca, 0x0, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdff98, 0xafbf0060, 0xafbe005c, 0xafb50058, 0xafb30054, 0xafb10050, 0x8f820240, 0x3c030001, 0x431025, 0xaf820240, -0x3c020001, 0x8c4231e0, 0x3c030001, 0x8c6331e4, 0xaf800048, 0x8f840048, +0x3c020001, 0x8c423340, 0x3c030001, 0x8c633344, 0xaf800048, 0x8f840048, 0x3c120000, 0x26524100, 0xa3a00047, 0xafa20034, 0x14800005, 0xafa30030, 0xaf800048, 0x8f820048, 0x10400004, 0x0, 0xaf800048, 0x10000003, -0x2e02021, 0xaf80004c, 0x2e02021, 0xc00296c, 0x340581f0, 0x2c02021, -0xc00296c, 0x24050558, 0x3c020001, 0x8c423344, 0x3c030001, 0x8c633340, -0x3c040001, 0x8c843348, 0x3c050001, 0x8ca53358, 0x3c060001, 0x8cc63360, -0x3c070001, 0x8ce73368, 0x3c080001, 0x8d08334c, 0xaec20534, 0x3c020001, -0x8c423354, 0x8ec90534, 0xaec50544, 0x3c050001, 0x8ca53350, 0xaec00000, +0x2e02021, 0xaf80004c, 0x2e02021, 0xc002990, 0x340581f0, 0x2c02021, +0xc002990, 0x24050558, 0x3c020001, 0x8c4234a4, 0x3c030001, 0x8c6334a0, +0x3c040001, 0x8c8434a8, 0x3c050001, 0x8ca534b8, 0x3c060001, 0x8cc634c0, +0x3c070001, 0x8ce734c8, 0x3c080001, 0x8d0834ac, 0xaec20534, 0x3c020001, +0x8c4234b4, 0x8ec90534, 0xaec50544, 0x3c050001, 0x8ca534b0, 0xaec00000, 0xaec3053c, 0xaec40540, 0xaec60548, 0xaec7054c, 0xaec80550, 0xaec20538, 0xafa90010, 0x8ec20538, 0xafa20014, 0x8ec6053c, 0x8ec70540, 0x3c040001, -0xc0028eb, 0x24842558, 0xafb70010, 0xafb60014, 0x8ec60544, 0x8ec70548, -0x3c040001, 0x24842560, 0xc0028eb, 0x24050001, 0x3c040001, 0x24842568, -0x24050001, 0x24060001, 0x24070001, 0xafa00010, 0xc0028eb, 0xafa00014, -0x3c020001, 0x8c423350, 0x3603821, 0x3c060001, 0x24c654b0, 0x2448ffff, +0xc00290f, 0x24842688, 0xafb70010, 0xafb60014, 0x8ec60544, 0x8ec70548, +0x3c040001, 0x24842690, 0xc00290f, 0x24050001, 0x3c040001, 0x24842698, +0x24050001, 0x24060001, 0x24070001, 0xafa00010, 0xc00290f, 0xafa00014, +0x3c020001, 0x8c4234b0, 0x3603821, 0x3c060001, 0x24c65610, 0x2448ffff, 0x1061824, 0xe81024, 0x43102b, 0x10400006, 0x24050002, 0x3c040001, -0x24842570, 0xafa80010, 0xc0028eb, 0xafa00014, 0x24020001, 0xa2c20529, +0x248426a0, 0xafa80010, 0xc00290f, 0xafa00014, 0x24020001, 0xa2c20529, 0xaf800054, 0xaf80011c, 0x8f420218, 0x30420002, 0x10400009, 0x0, 0x8f420220, 0x3c030002, 0x34630004, 0x431025, 0xaec20008, 0x8f42021c, 0x10000008, 0x34420004, 0x8f420220, 0x3c030002, 0x34630006, 0x431025, @@ -3028,109 +3050,109 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x9482000a, 0xaca2009c, 0x8ca200b0, 0x8ec30010, 0x431025, 0xaca200b0, 0x8f8200b0, 0x30420004, 0x1440fffd, 0x0, 0x8ee20448, 0x8ee3044c, 0xaee304bc, 0x8ee204bc, 0x2442e000, 0x2c422001, 0x1440000d, 0x26c40128, -0x8ee20448, 0x8ee3044c, 0x3c040001, 0x2484257c, 0x3c050001, 0xafa00010, -0xafa00014, 0x8ee704bc, 0x34a5f000, 0xc0028eb, 0x603021, 0x26c40128, -0xc00296c, 0x24050400, 0x27440080, 0xc00296c, 0x24050080, 0x8f42025c, -0x26c4018c, 0xaec20158, 0x8f420260, 0x27450200, 0x24060008, 0xc00297e, +0x8ee20448, 0x8ee3044c, 0x3c040001, 0x248426ac, 0x3c050001, 0xafa00010, +0xafa00014, 0x8ee704bc, 0x34a5f000, 0xc00290f, 0x603021, 0x26c40128, +0xc002990, 0x24050400, 0x27440080, 0xc002990, 0x24050080, 0x8f42025c, +0x26c4018c, 0xaec20158, 0x8f420260, 0x27450200, 0x24060008, 0xc0029a2, 0xaec20160, 0x3c043b9a, 0x3484ca00, 0x2821, 0x24020006, 0x24030002, 0xaec2015c, 0x240203e8, 0xaec3016c, 0xaec30168, 0xaec40164, 0xaec201fc, -0x24020001, 0xaec301f8, 0xaec20204, 0x3c030001, 0x651821, 0x906331e8, +0x24020001, 0xaec301f8, 0xaec20204, 0x3c030001, 0x651821, 0x90633348, 0x2c51021, 0x24a50001, 0xa0430194, 0x2ca2000f, 0x1440fff8, 0x2c51821, 0x8f820040, 0x24a50001, 0x21702, 0x24420030, 0xa0620194, 0x2c51021, -0xa0400194, 0xafa00010, 0x8fa20034, 0x3c040001, 0x24842588, 0xafa20014, -0x8fa60030, 0x3821, 0xc0028eb, 0x2821, 0x3c040000, 0x24845990, +0xa0400194, 0xafa00010, 0x8fa20034, 0x3c040001, 0x248426b8, 0xafa20014, +0x8fa60030, 0x3821, 0xc00290f, 0x2821, 0x3c040000, 0x24845990, 0x24050010, 0x27b30030, 0x2603021, 0x27b10034, 0xc0016be, 0x2203821, -0x3c030001, 0x8c6331d8, 0x3c15f000, 0x1060000a, 0xafa2003c, 0x8fa30030, +0x3c030001, 0x8c633338, 0x3c15f000, 0x1060000a, 0xafa2003c, 0x8fa30030, 0x2405ff00, 0x8fa20034, 0x246400ff, 0x852024, 0x831823, 0x431023, 0xafa20034, 0xafa40030, 0x3c040000, 0x24844100, 0x24050108, 0x2603021, 0xc0016be, 0x2203821, 0x96e30452, 0x30630003, 0x1060005f, 0x409021, 0x8f820050, 0x3c030010, 0x431024, 0x10400021, 0x0, 0x8f820040, 0x3c035000, 0x551024, 0x14430009, 0x0, 0x96e60452, 0x8f820050, -0xafa00014, 0xafa20010, 0x8f870040, 0x3c040001, 0x1000000d, 0x24842594, +0xafa00014, 0xafa20010, 0x8f870040, 0x3c040001, 0x1000000d, 0x248426c4, 0x8f420218, 0x30420040, 0x1040000d, 0x24020001, 0x8f820050, 0x96e60452, -0xafa20010, 0x8f420218, 0xafa20014, 0x8f870040, 0x3c040001, 0x2484259c, -0xc0028eb, 0x2821, 0x10000004, 0x0, 0x3c010001, 0x370821, -0xa02281ec, 0x3c040001, 0x24849a48, 0x3c050001, 0x24a59ac4, 0xa42823, +0xafa20010, 0x8f420218, 0xafa20014, 0x8f870040, 0x3c040001, 0x248426cc, +0xc00290f, 0x2821, 0x10000004, 0x0, 0x3c010001, 0x370821, +0xa02281ec, 0x3c040001, 0x24849a34, 0x3c050001, 0x24a59aac, 0xa42823, 0x27b30030, 0x2603021, 0x8ec3000c, 0x27b10034, 0x2203821, 0x24020001, 0xa2c20020, 0xa2c20021, 0x34630a00, 0xc0016be, 0xaec3000c, 0x3c040001, -0x2484ab64, 0x3c050001, 0x24a5af4c, 0xa42823, 0x2603021, 0x2203821, -0xc0016be, 0xaec200a4, 0x3c040001, 0x2484b418, 0x3c050001, 0x24a5c2c8, -0xa42823, 0x2603021, 0x3c010001, 0xac22339c, 0xc0016be, 0x2203821, -0x3c040001, 0x2484dacc, 0x3c050001, 0x24a5e290, 0xa42823, 0x2603021, -0x3c010001, 0xac2233a0, 0xc0016be, 0x2203821, 0x3c040001, 0x248425a4, -0x96e60452, 0x24050011, 0x3821, 0x3c010001, 0xac2233bc, 0xafa00010, -0xc0028eb, 0xafa00014, 0x10000028, 0x0, 0x3c040001, 0x2484989c, -0x3c050001, 0x24a59a40, 0xa42823, 0x2603021, 0xc0016be, 0x2203821, -0x3c040001, 0x2484a650, 0x3c050001, 0x24a5ab5c, 0xa42823, 0x2603021, -0x2203821, 0xc0016be, 0xaec200a4, 0x3c040001, 0x2484af54, 0x3c050001, -0x24a5b410, 0xa42823, 0x2603021, 0x3c010001, 0xac22339c, 0xc0016be, -0x2203821, 0x3c040001, 0x2484d9e4, 0x3c050001, 0x24a5dac4, 0xa42823, -0x2603021, 0x3c010001, 0xac2233a0, 0xc0016be, 0x2203821, 0x3c010001, -0xac2233bc, 0x3c020001, 0x8c42339c, 0x3c050fff, 0x34a5ffff, 0x3c030001, -0x8c6333a0, 0x3c040800, 0x451024, 0x21082, 0x441025, 0x651824, -0xae420020, 0x3c020001, 0x8c4233bc, 0x31882, 0x641825, 0xae430080, +0x2484abf4, 0x3c050001, 0x24a5afdc, 0xa42823, 0x2603021, 0x2203821, +0xc0016be, 0xaec200a4, 0x3c040001, 0x2484b4a8, 0x3c050001, 0x24a5c358, +0xa42823, 0x2603021, 0x3c010001, 0xac2234fc, 0xc0016be, 0x2203821, +0x3c040001, 0x2484dbf8, 0x3c050001, 0x24a5e3bc, 0xa42823, 0x2603021, +0x3c010001, 0xac223500, 0xc0016be, 0x2203821, 0x3c040001, 0x248426d4, +0x96e60452, 0x24050011, 0x3821, 0x3c010001, 0xac22351c, 0xafa00010, +0xc00290f, 0xafa00014, 0x10000028, 0x0, 0x3c040001, 0x24849890, +0x3c050001, 0x24a59a2c, 0xa42823, 0x2603021, 0xc0016be, 0x2203821, +0x3c040001, 0x2484a6e0, 0x3c050001, 0x24a5abec, 0xa42823, 0x2603021, +0x2203821, 0xc0016be, 0xaec200a4, 0x3c040001, 0x2484afe4, 0x3c050001, +0x24a5b4a0, 0xa42823, 0x2603021, 0x3c010001, 0xac2234fc, 0xc0016be, +0x2203821, 0x3c040001, 0x2484db10, 0x3c050001, 0x24a5dbf0, 0xa42823, +0x2603021, 0x3c010001, 0xac223500, 0xc0016be, 0x2203821, 0x3c010001, +0xac22351c, 0x3c020001, 0x8c4234fc, 0x3c050fff, 0x34a5ffff, 0x3c030001, +0x8c633500, 0x3c040800, 0x451024, 0x21082, 0x441025, 0x651824, +0xae420020, 0x3c020001, 0x8c42351c, 0x31882, 0x641825, 0xae430080, 0x451024, 0x21082, 0x441025, 0xae420078, 0x96e20462, 0x30420003, 0x14400009, 0x0, 0x96e20472, 0x30420003, 0x1040007f, 0x27b30030, 0x96e20462, 0x30420003, 0x1040006d, 0x3c020700, 0x96e20472, 0x30420003, 0x10400069, 0x3c020700, 0x96e30472, 0x96e20462, 0x14620065, 0x3c020700, 0x8f82005c, 0x3c030080, 0x431024, 0x1040000b, 0x0, 0x8f820050, 0x96e60462, 0xafa20010, 0x8f82005c, 0xafa20014, 0x8f870040, 0x3c040001, -0x248425b0, 0xc0028eb, 0x24051977, 0x8f820050, 0x3c030010, 0x431024, +0x248426e0, 0xc00290f, 0x24051977, 0x8f820050, 0x3c030010, 0x431024, 0x10400022, 0x0, 0x8f820040, 0x3c03f000, 0x431024, 0x3c035000, 0x14430009, 0x0, 0x96e60462, 0x8f820050, 0xafa00014, 0xafa20010, -0x8f870040, 0x3c040001, 0x1000000d, 0x24842594, 0x8f420218, 0x30420040, +0x8f870040, 0x3c040001, 0x1000000d, 0x248426c4, 0x8f420218, 0x30420040, 0x1040000d, 0x24020001, 0x8f820050, 0x96e60462, 0xafa20010, 0x8f420218, -0xafa20014, 0x8f870040, 0x3c040001, 0x2484259c, 0xc0028eb, 0x24050001, +0xafa20014, 0x8f870040, 0x3c040001, 0x248426cc, 0xc00290f, 0x24050001, 0x10000004, 0x0, 0x3c010001, 0x370821, 0xa02281ec, 0x3c040001, -0x2484981c, 0x3c050001, 0x24a59894, 0xa42823, 0x27b30030, 0x2603021, +0x24849810, 0x3c050001, 0x24a59888, 0xa42823, 0x27b30030, 0x2603021, 0x8ec30004, 0x27b10034, 0x2203821, 0x24020001, 0xa2c2004c, 0x34630e00, -0xc0016be, 0xaec30004, 0x3c040001, 0x2484cf2c, 0x3c050001, 0x24a5d654, +0xc0016be, 0xaec30004, 0x3c040001, 0x2484d058, 0x3c050001, 0x24a5d780, 0xa42823, 0x2603021, 0x2203821, 0xc0016be, 0xaec200a8, 0x3c040001, -0x2484dacc, 0x3c050001, 0x24a5e290, 0xa42823, 0x2603021, 0x3c010001, -0xac2233b4, 0xc0016be, 0x2203821, 0x3c040001, 0x248425bc, 0x21900, +0x2484dbf8, 0x3c050001, 0x24a5e3bc, 0xa42823, 0x2603021, 0x3c010001, +0xac223514, 0xc0016be, 0x2203821, 0x3c040001, 0x248426ec, 0x21900, 0x31982, 0x3c050800, 0x651825, 0xae430078, 0x96e60462, 0x24050012, -0x3c010001, 0xac2233bc, 0x1000000a, 0x3821, 0x34423000, 0x240a0001, -0x3c040001, 0x248425c8, 0x3405f001, 0x3021, 0x3821, 0xa3aa0047, -0xafa20020, 0xafa00010, 0xc0028eb, 0xafa00014, 0x10000015, 0x0, -0x3c040001, 0x2484960c, 0x3c050001, 0x24a59814, 0xa42823, 0x2603021, -0x27b10034, 0xc0016be, 0x2203821, 0x3c040001, 0x2484c4ec, 0x3c050001, -0x24a5cf24, 0xa42823, 0x2603021, 0x2203821, 0xc0016be, 0xaec200a8, -0x3c010001, 0xac2233b4, 0x3c020001, 0x8c4233b4, 0x3c030800, 0x21100, +0x3c010001, 0xac22351c, 0x1000000a, 0x3821, 0x34423000, 0x240a0001, +0x3c040001, 0x248426f8, 0x3405f001, 0x3021, 0x3821, 0xa3aa0047, +0xafa20020, 0xafa00010, 0xc00290f, 0xafa00014, 0x10000015, 0x0, +0x3c040001, 0x2484960c, 0x3c050001, 0x24a59808, 0xa42823, 0x2603021, +0x27b10034, 0xc0016be, 0x2203821, 0x3c040001, 0x2484c57c, 0x3c050001, +0x24a5d050, 0xa42823, 0x2603021, 0x2203821, 0xc0016be, 0xaec200a8, +0x3c010001, 0xac223514, 0x3c020001, 0x8c423514, 0x3c030800, 0x21100, 0x21182, 0x431025, 0xae420038, 0x8f420218, 0x30420040, 0x14400004, 0x24020001, 0x3c010001, 0x370821, 0xa02281ec, 0x96e20462, 0x30420010, 0x14400009, 0x0, 0x96e20472, 0x30420010, 0x10400021, 0x0, 0x96e20462, 0x30420010, 0x10400005, 0x3c020700, 0x96e20472, 0x30420010, 0x14400011, 0x3c020700, 0x34423000, 0x240a0001, 0xa3aa0047, 0xafa20020, 0x8ee20154, 0x96e60462, 0x96e70472, 0x24420001, 0xaee20154, 0x8ee20154, -0x3c040001, 0x248425d4, 0x3405f002, 0xafa00010, 0xc0028eb, 0xafa00014, -0x96e60472, 0x96e70462, 0x3c040001, 0x248425dc, 0x24050012, 0xafa00010, -0xc0028eb, 0xafa00014, 0x3c040001, 0x2484d65c, 0x3c050001, 0x24a5d818, +0x3c040001, 0x24842704, 0x3405f002, 0xafa00010, 0xc00290f, 0xafa00014, +0x96e60472, 0x96e70462, 0x3c040001, 0x2484270c, 0x24050012, 0xafa00010, +0xc00290f, 0xafa00014, 0x3c040001, 0x2484d788, 0x3c050001, 0x24a5d944, 0xa42823, 0x27b30030, 0x2603021, 0x27b10034, 0xc0016be, 0x2203821, -0x3c1e0fff, 0x37deffff, 0x3c040001, 0x2484d820, 0x3c050001, 0x24a5d9dc, -0xa42823, 0x2603021, 0x2203821, 0x3c010001, 0xac2233a8, 0x5e1024, +0x3c1e0fff, 0x37deffff, 0x3c040001, 0x2484d94c, 0x3c050001, 0x24a5db08, +0xa42823, 0x2603021, 0x2203821, 0x3c010001, 0xac223508, 0x5e1024, 0x21082, 0x3c150800, 0x551025, 0xc0016be, 0xae420050, 0x3c040000, 0x24847d00, 0x3c050000, 0x24a57f50, 0xa42823, 0x2603021, 0x2203821, -0x3c010001, 0xac2233c0, 0x5e1024, 0x21082, 0x551025, 0xc0016be, +0x3c010001, 0xac223520, 0x5e1024, 0x21082, 0x551025, 0xc0016be, 0xae420048, 0x3c040000, 0x24846134, 0x3c050000, 0x24a56244, 0xa42823, -0x2603021, 0x2203821, 0x3c010001, 0xac223388, 0x5e1024, 0x21082, +0x2603021, 0x2203821, 0x3c010001, 0xac2234e8, 0x5e1024, 0x21082, 0x551025, 0xc0016be, 0xae4200b8, 0x3c040000, 0x2484624c, 0x3c050000, -0x24a5631c, 0xa42823, 0x2603021, 0x2203821, 0x3c010001, 0xac22337c, +0x24a5631c, 0xa42823, 0x2603021, 0x2203821, 0x3c010001, 0xac2234dc, 0x5e1024, 0x21082, 0x551025, 0xc0016be, 0xae4200e8, 0x3c040000, 0x24846324, 0x3c050000, 0x24a565a4, 0xa42823, 0x2603021, 0x2203821, -0x3c010001, 0xac22336c, 0x5e1024, 0x21082, 0x551025, 0xc0016be, +0x3c010001, 0xac2234cc, 0x5e1024, 0x21082, 0x551025, 0xc0016be, 0xae4200f0, 0x3c040000, 0x248465ac, 0x3c050000, 0x24a566e0, 0xa42823, -0x2603021, 0x2203821, 0x3c010001, 0xac223374, 0x5e1024, 0x21082, -0x551025, 0xc0016be, 0xae4200c0, 0x3c040001, 0x2484e3dc, 0x3c050001, -0x24a5e98c, 0xa42823, 0x2603021, 0x2203821, 0x3c010001, 0xac223380, +0x2603021, 0x2203821, 0x3c010001, 0xac2234d4, 0x5e1024, 0x21082, +0x551025, 0xc0016be, 0xae4200c0, 0x3c040001, 0x2484e50c, 0x3c050001, +0x24a5eabc, 0xa42823, 0x2603021, 0x2203821, 0x3c010001, 0xac2234e0, 0x5e1024, 0x21082, 0x551025, 0xc0016be, 0xae4200c8, 0x3c040001, -0x2484ed00, 0x3c050001, 0x24a5edd8, 0xa42823, 0x2603021, 0x2203821, -0x3c010001, 0xac2233c4, 0x5e1024, 0x21082, 0x551025, 0xc0016be, -0xae4200d0, 0x3c040001, 0x8c8433b8, 0x3c050001, 0x8ca533a4, 0x2603021, -0x2203821, 0xc0016be, 0xaec200ac, 0x3c040001, 0x8c8433b0, 0x3c050001, -0x8ca533ac, 0x2603021, 0x3c010001, 0xac2233b8, 0xc0016be, 0x2203821, -0x3c010001, 0xac2233b0, 0x3c070001, 0xf73821, 0x90e781ec, 0xafa00010, -0x8fa20034, 0xafa20014, 0x8fa60030, 0x3c040001, 0x248425e8, 0xc0028eb, -0x2821, 0x8faa003c, 0xc003beb, 0x1408021, 0xc0038a8, 0x0, +0x2484ee30, 0x3c050001, 0x24a5ef08, 0xa42823, 0x2603021, 0x2203821, +0x3c010001, 0xac223524, 0x5e1024, 0x21082, 0x551025, 0xc0016be, +0xae4200d0, 0x3c040001, 0x8c843518, 0x3c050001, 0x8ca53504, 0x2603021, +0x2203821, 0xc0016be, 0xaec200ac, 0x3c040001, 0x8c843510, 0x3c050001, +0x8ca5350c, 0x2603021, 0x3c010001, 0xac223518, 0xc0016be, 0x2203821, +0x3c010001, 0xac223510, 0x3c070001, 0xf73821, 0x90e781ec, 0xafa00010, +0x8fa20034, 0xafa20014, 0x8fa60030, 0x3c040001, 0x24842718, 0xc00290f, +0x2821, 0x8faa003c, 0xc003c37, 0x1408021, 0xc0038f4, 0x0, 0xc002548, 0x0, 0xaec0002c, 0xaf400228, 0xaf40022c, 0xaee004a8, 0xaec00014, 0xaec00018, 0xaec00024, 0x96e20450, 0x2442ffff, 0xaec20028, 0x3c010001, 0x370821, 0xac2081d4, 0xaec00038, 0xaec00044, 0xaec0003c, @@ -3141,55 +3163,55 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0xa2c00115, 0x3c1433d8, 0x3694c348, 0x3c020800, 0x34420080, 0x3c040000, 0x248459dc, 0x3c050000, 0x24a55a08, 0xa42823, 0x2603021, 0x2203821, 0xaf820060, 0x2402ffff, 0xaec00030, 0xaec00034, 0xc0016be, 0xaf820064, -0x3c010001, 0xac223364, 0x5e1024, 0x21082, 0x551025, 0xc00181c, +0x3c010001, 0xac2234c4, 0x5e1024, 0x21082, 0x551025, 0xc00181c, 0xae420000, 0x8f820240, 0x3c030001, 0x431025, 0xaf820240, 0x3c020000, 0x24424034, 0xaf820244, 0xaf800240, 0x8f820060, 0x551024, 0x14400005, -0x3c030800, 0x8f820060, 0x431024, 0x1040fffd, 0x0, 0xc0038b5, +0x3c030800, 0x8f820060, 0x431024, 0x1040fffd, 0x0, 0xc003901, 0x0, 0x3c020100, 0xafa20028, 0x8ec3002c, 0x240200ff, 0x10620003, 0x8821, 0x8ec2002c, 0x24510001, 0x8f420228, 0x1622000f, 0x24070008, -0x3c040001, 0x248424fc, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, -0x3c050009, 0xc0028eb, 0x34a5f005, 0x8ec202a0, 0x24420001, 0xaec202a0, +0x3c040001, 0x2484262c, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, +0x3c050009, 0xc00290f, 0x34a5f005, 0x8ec202a0, 0x24420001, 0xaec202a0, 0x10000046, 0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021, 0x8fa30028, 0x8fa4002c, 0xac4304c0, 0xac4404c4, 0x8ec3002c, 0x8ee40428, 0x8ee5042c, 0x8ec6002c, 0x2402000d, 0xafa20010, 0xafb10014, 0x8ec20008, 0x318c0, 0x604821, 0x4021, 0xa92821, 0xa9182b, 0x882021, 0x832021, 0x630c0, 0xafa20018, 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, -0x5440000c, 0xaed1002c, 0x3c040001, 0x24842508, 0xafa00010, 0xafa00014, -0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f000, 0x1000001d, +0x5440000c, 0xaed1002c, 0x3c040001, 0x24842638, 0xafa00010, 0xafa00014, +0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f000, 0x1000001d, 0x0, 0x8ee40488, 0x8ee5048c, 0x8ec3002c, 0x8ec80008, 0x8f860120, 0x24020011, 0xafa20010, 0xafa30014, 0xafa80018, 0x8ec200a8, 0x24070008, -0x40f809, 0x24c6001c, 0x1440000e, 0x0, 0x3c040001, 0x24842510, -0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, +0x40f809, 0x24c6001c, 0x1440000e, 0x0, 0x3c040001, 0x24842640, +0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f001, 0x8ec202a4, 0x24420001, 0xaec202a4, 0x8ec202a4, 0x8ec20248, 0x24420001, 0xaec20248, 0x8ec20248, 0x93a20047, 0x10400070, 0x240200ff, 0x8ec3002c, 0x10620004, 0x27a70020, 0x8ec2002c, 0x10000002, 0x24510001, -0x8821, 0x8f420228, 0x1622000f, 0x4021, 0x3c040001, 0x248424fc, -0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, +0x8821, 0x8f420228, 0x1622000f, 0x4021, 0x3c040001, 0x2484262c, +0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f005, 0x8ec202a0, 0x24420001, 0xaec202a0, 0x10000046, 0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021, 0x8ce30000, 0x8ce40004, 0xac4304c0, 0xac4404c4, 0x8ec3002c, 0x8ee40428, 0x8ee5042c, 0x8ec6002c, 0x24070008, 0x2402000d, 0xafa20010, 0xafb10014, 0x8ec20008, 0x318c0, 0x604821, 0xa92821, 0xa9182b, 0x882021, 0x832021, 0x630c0, 0xafa20018, 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 0x5440000c, 0xaed1002c, -0x3c040001, 0x24842508, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, -0x3c050009, 0xc0028eb, 0x34a5f000, 0x1000001d, 0x0, 0x8ee40488, +0x3c040001, 0x24842638, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, +0x3c050009, 0xc00290f, 0x34a5f000, 0x1000001d, 0x0, 0x8ee40488, 0x8ee5048c, 0x8ec3002c, 0x8ec80008, 0x8f860120, 0x24020011, 0xafa20010, 0xafa30014, 0xafa80018, 0x8ec200a8, 0x24070008, 0x40f809, 0x24c6001c, -0x1440000e, 0x0, 0x3c040001, 0x24842510, 0xafa00010, 0xafa00014, -0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f001, 0x8ec202a4, -0x24420001, 0xaec202a4, 0x8ec202a4, 0x3c040001, 0x248425f4, 0x8ec20254, +0x1440000e, 0x0, 0x3c040001, 0x24842640, 0xafa00010, 0xafa00014, +0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f001, 0x8ec202a4, +0x24420001, 0xaec202a4, 0x8ec202a4, 0x3c040001, 0x24842724, 0x8ec20254, 0x3c050009, 0x34a59999, 0x24420001, 0xaec20254, 0x8ec20254, 0x3021, -0x3821, 0xafa00010, 0xc0028eb, 0xafa00014, 0x10000004, 0x0, +0x3821, 0xafa00010, 0xc00290f, 0xafa00014, 0x10000004, 0x0, 0x8f420264, 0x10400005, 0x0, 0x8f8200a0, 0x30420004, 0x1440fffa, 0x0, 0x8f820044, 0x34420004, 0xaf820044, 0x8ec2026c, 0x24420001, 0xaec2026c, 0x8ec2026c, 0x8f8200d8, 0x8f8300d4, 0x431023, 0x2442fff8, 0xaec20088, 0x8ec20088, 0x4410006, 0x24020001, 0x8ec20088, 0x8ec3053c, 0x431021, 0xaec20088, 0x24020001, 0xaec20070, 0x96e20452, 0x30420010, 0x10400005, 0x0, 0x8f820214, 0x3c038100, 0x431025, 0xaf820214, -0x3c020001, 0x8c4232a8, 0x30420001, 0x10400007, 0x0, 0x3c040000, +0x3c020001, 0x8c423408, 0x30420001, 0x10400007, 0x0, 0x3c040000, 0x24846bb4, 0x3c050000, 0x24a570e8, 0x10000006, 0xa42823, 0x3c040000, 0x248466e8, 0x3c050000, 0x24a56bac, 0xa42823, 0x27a60030, 0xc0016be, -0x27a70034, 0x3c010001, 0xac223378, 0x3c020001, 0x8c423378, 0x3c030800, +0x27a70034, 0x3c010001, 0xac2234d8, 0x3c020001, 0x8c4234d8, 0x3c030800, 0x21100, 0x21182, 0x431025, 0xae420040, 0x8f830060, 0x74100b, 0x242000a, 0x200f821, 0x0, 0xd, 0x8fbf0060, 0x8fbe005c, 0x8fb50058, 0x8fb30054, 0x8fb10050, 0x3e00008, 0x27bd0068, 0x3e00008, @@ -3199,69 +3221,69 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x27bdfde0, 0x27a70018, 0x3c02dead, 0x3442beef, 0xafbf0218, 0x8f830150, 0x3c04001f, 0x3484ffff, 0xafa20018, 0xe33823, 0xe43824, 0x8ce30000, 0x10620008, 0x0, 0xafa30010, 0xafa00014, 0x8f860150, 0x3c040001, -0x24842600, 0xc0028eb, 0x24050020, 0x8fbf0218, 0x3e00008, 0x27bd0220, +0x24842730, 0xc00290f, 0x24050020, 0x8fbf0218, 0x3e00008, 0x27bd0220, 0x27bdffe0, 0x3c06abba, 0x34c6babe, 0xafb10018, 0x3c110004, 0x3c07007f, 0x34e7ffff, 0xafbf001c, 0x112840, 0x8e240000, 0x8ca30000, 0xaca00000, 0xae260000, 0x8ca20000, 0xaca30000, 0x10460005, 0xae240000, 0xa08821, -0xf1102b, 0x1040fff5, 0x112840, 0x3c040001, 0x2484260c, 0x2202821, -0x3021, 0x3821, 0xafa00010, 0xc0028eb, 0xafa00014, 0x2201021, +0xf1102b, 0x1040fff5, 0x112840, 0x3c040001, 0x2484273c, 0x2202821, +0x3021, 0x3821, 0xafa00010, 0xc00290f, 0xafa00014, 0x2201021, 0x8fbf001c, 0x8fb10018, 0x3e00008, 0x27bd0020, 0x27bdffc8, 0xafb30024, 0x809821, 0xafbe002c, 0xafb50028, 0xe0a821, 0x24a50003, 0xafbf0030, 0xafb10020, 0x8ea20000, 0x2403fffc, 0xa38824, 0x51102b, 0x14400020, 0xc0f021, 0x8fc80000, 0xafa00010, 0xafa8001c, 0x8ea20000, 0x3c040001, -0x24842618, 0xafa20014, 0x8fc60000, 0x2602821, 0xc0028eb, 0x2203821, +0x24842748, 0xafa20014, 0x8fc60000, 0x2602821, 0xc00290f, 0x2203821, 0x8fc60000, 0x111882, 0x2463ffff, 0x2402ffff, 0x10620008, 0x2602021, 0x2405ffff, 0x8c820000, 0x24840004, 0x2463ffff, 0xacc20000, 0x1465fffb, 0x24c60004, 0x8ea20000, 0x511023, 0xaea20000, 0x8fc20000, 0x511021, -0x1000000b, 0xafc20000, 0xafa00010, 0x8ea20000, 0x3c040001, 0x24842620, -0xafa20014, 0x8fc60000, 0x2602821, 0x2203821, 0xc0028eb, 0xafa5001c, +0x1000000b, 0xafc20000, 0xafa00010, 0x8ea20000, 0x3c040001, 0x24842750, +0xafa20014, 0x8fc60000, 0x2602821, 0x2203821, 0xc00290f, 0xafa5001c, 0x8fa2001c, 0x8fbf0030, 0x8fbe002c, 0x8fb50028, 0x8fb30024, 0x8fb10020, 0x3e00008, 0x27bd0038, 0x27bdffe8, 0x3c1cc000, 0xd021, 0x3c05ffff, -0x3c030001, 0x8c633340, 0x3c040001, 0x8c843348, 0x34a57e10, 0x24021ffc, -0x3c010001, 0xac2231e0, 0x3c0200c0, 0x3c010001, 0xac2231e4, 0x3c020020, +0x3c030001, 0x8c6334a0, 0x3c040001, 0x8c8434a8, 0x34a57e10, 0x24021ffc, +0x3c010001, 0xac223340, 0x3c0200c0, 0x3c010001, 0xac223344, 0x3c020020, 0xafbf0010, 0x3c0100c0, 0xac201ffc, 0x431023, 0x441023, 0x245bb000, -0x365b821, 0x3c1d0001, 0x8fbd31dc, 0x3a0f021, 0x3c0400c0, 0x34840200, -0x3c1600c0, 0x3c0300c0, 0x34630758, 0x24021dfc, 0x3c010001, 0xac2231e0, -0x240218a4, 0x3c010001, 0xac2431e4, 0x3c010001, 0xac2231e0, 0x3c010001, -0xac2331e4, 0xc00172c, 0x36d60200, 0x8fbf0010, 0x3e00008, 0x27bd0018, -0x27bdffc8, 0x3c040001, 0x24842628, 0x2821, 0x3c020001, 0x8c4231e0, -0x3c030001, 0x8c6331e4, 0x3021, 0x3603821, 0xafbf0030, 0xafbe002c, +0x365b821, 0x3c1d0001, 0x8fbd333c, 0x3a0f021, 0x3c0400c0, 0x34840200, +0x3c1600c0, 0x3c0300c0, 0x34630758, 0x24021dfc, 0x3c010001, 0xac223340, +0x240218a4, 0x3c010001, 0xac243344, 0x3c010001, 0xac223340, 0x3c010001, +0xac233344, 0xc00172c, 0x36d60200, 0x8fbf0010, 0x3e00008, 0x27bd0018, +0x27bdffc8, 0x3c040001, 0x24842758, 0x2821, 0x3c020001, 0x8c423340, +0x3c030001, 0x8c633344, 0x3021, 0x3603821, 0xafbf0030, 0xafbe002c, 0xafb50028, 0xafb30024, 0xafb10020, 0xafa2001c, 0xafa30018, 0xafb70010, -0xc0028eb, 0xafb60014, 0xc001849, 0x0, 0x8f820240, 0x34420004, +0xc00290f, 0xafb60014, 0xc001849, 0x0, 0x8f820240, 0x34420004, 0xaf820240, 0x24020001, 0xaec20000, 0x3c020001, 0x571021, 0x904281ec, -0x10400090, 0x2402fffc, 0x3c110001, 0x2631a33b, 0x3c150001, 0x26b59ee8, +0x10400090, 0x2402fffc, 0x3c110001, 0x2631a3c3, 0x3c150001, 0x26b59f70, 0x2351823, 0x8fa6001c, 0x628824, 0xd1102b, 0x1440001e, 0x27be0018, -0x8fb30018, 0x3c040001, 0x24842618, 0x2a02821, 0x2203821, 0xafa00010, -0xafa60014, 0xc0028eb, 0x2603021, 0x8fa40018, 0x111882, 0x2463ffff, +0x8fb30018, 0x3c040001, 0x24842748, 0x2a02821, 0x2203821, 0xafa00010, +0xafa60014, 0xc00290f, 0x2603021, 0x8fa40018, 0x111882, 0x2463ffff, 0x2402ffff, 0x10620008, 0x2a02821, 0x2406ffff, 0x8ca20000, 0x24a50004, 0x2463ffff, 0xac820000, 0x1466fffb, 0x24840004, 0x8fa2001c, 0x511023, 0xafa2001c, 0x8fc20000, 0x511021, 0x1000000a, 0xafc20000, 0x3c040001, -0x24842620, 0x2a02821, 0xafa00010, 0xafa60014, 0x8fa60018, 0x2203821, -0xc0028eb, 0xa09821, 0x8fa3001c, 0x24150020, 0x3c010001, 0xac33335c, -0x2c620020, 0x1440001d, 0x27b30018, 0x8fb10018, 0x3c040001, 0x24842618, -0x3c050001, 0x24a533f0, 0x24070020, 0xafa00010, 0xafa30014, 0xc0028eb, -0x2203021, 0x3c050001, 0x24a533f0, 0x8fa40018, 0x24030007, 0x2406ffff, +0x24842750, 0x2a02821, 0xafa00010, 0xafa60014, 0x8fa60018, 0x2203821, +0xc00290f, 0xa09821, 0x8fa3001c, 0x24150020, 0x3c010001, 0xac3334bc, +0x2c620020, 0x1440001d, 0x27b30018, 0x8fb10018, 0x3c040001, 0x24842748, +0x3c050001, 0x24a53550, 0x24070020, 0xafa00010, 0xafa30014, 0xc00290f, +0x2203021, 0x3c050001, 0x24a53550, 0x8fa40018, 0x24030007, 0x2406ffff, 0x8ca20000, 0x24a50004, 0x2463ffff, 0xac820000, 0x1466fffb, 0x24840004, 0x8fa2001c, 0x551023, 0xafa2001c, 0x8e620000, 0x551021, 0x1000000c, -0xae620000, 0x3c040001, 0x24842620, 0x3c050001, 0x24a533f0, 0xafa00010, -0xafa30014, 0x8fa60018, 0x3c110001, 0x263133f0, 0xc0028eb, 0x24070020, -0x8fa3001c, 0x24150020, 0x3c010001, 0xac313390, 0x2c620020, 0x1440001d, -0x27b30018, 0x8fb10018, 0x3c040001, 0x24842618, 0x3c050001, 0x24a53410, -0x24070020, 0xafa00010, 0xafa30014, 0xc0028eb, 0x2203021, 0x3c050001, -0x24a53410, 0x8fa40018, 0x24030007, 0x2406ffff, 0x8ca20000, 0x24a50004, +0xae620000, 0x3c040001, 0x24842750, 0x3c050001, 0x24a53550, 0xafa00010, +0xafa30014, 0x8fa60018, 0x3c110001, 0x26313550, 0xc00290f, 0x24070020, +0x8fa3001c, 0x24150020, 0x3c010001, 0xac3134f0, 0x2c620020, 0x1440001d, +0x27b30018, 0x8fb10018, 0x3c040001, 0x24842748, 0x3c050001, 0x24a53570, +0x24070020, 0xafa00010, 0xafa30014, 0xc00290f, 0x2203021, 0x3c050001, +0x24a53570, 0x8fa40018, 0x24030007, 0x2406ffff, 0x8ca20000, 0x24a50004, 0x2463ffff, 0xac820000, 0x1466fffb, 0x24840004, 0x8fa2001c, 0x551023, 0xafa2001c, 0x8e620000, 0x551021, 0x1000000c, 0xae620000, 0x3c040001, -0x24842620, 0x3c050001, 0x24a53410, 0xafa00010, 0xafa30014, 0x8fa60018, -0x3c110001, 0x26313410, 0xc0028eb, 0x24070020, 0x3c010001, 0x10000033, -0xac31338c, 0x3c110000, 0x26317cef, 0x3c150000, 0x26b57b3c, 0x2351823, +0x24842750, 0x3c050001, 0x24a53570, 0xafa00010, 0xafa30014, 0x8fa60018, +0x3c110001, 0x26313570, 0xc00290f, 0x24070020, 0x3c010001, 0x10000033, +0xac3134ec, 0x3c110000, 0x26317cef, 0x3c150000, 0x26b57b3c, 0x2351823, 0x8fa6001c, 0x628824, 0xd1102b, 0x1440001e, 0x27be0018, 0x8fb30018, -0x3c040001, 0x24842618, 0x2a02821, 0x2203821, 0xafa00010, 0xafa60014, -0xc0028eb, 0x2603021, 0x8fa40018, 0x111882, 0x2463ffff, 0x2402ffff, +0x3c040001, 0x24842748, 0x2a02821, 0x2203821, 0xafa00010, 0xafa60014, +0xc00290f, 0x2603021, 0x8fa40018, 0x111882, 0x2463ffff, 0x2402ffff, 0x10620008, 0x2a02821, 0x2406ffff, 0x8ca20000, 0x24a50004, 0x2463ffff, 0xac820000, 0x1466fffb, 0x24840004, 0x8fa2001c, 0x511023, 0xafa2001c, -0x8fc20000, 0x511021, 0x1000000a, 0xafc20000, 0x3c040001, 0x24842620, -0x2a02821, 0xafa00010, 0xafa60014, 0x8fa60018, 0x2203821, 0xc0028eb, -0xa09821, 0x3c010001, 0xac33335c, 0x3c030001, 0x8c63335c, 0x24020400, +0x8fc20000, 0x511021, 0x1000000a, 0xafc20000, 0x3c040001, 0x24842750, +0x2a02821, 0xafa00010, 0xafa60014, 0x8fa60018, 0x2203821, 0xc00290f, +0xa09821, 0x3c010001, 0xac3334bc, 0x3c030001, 0x8c6334bc, 0x24020400, 0x60f809, 0xaf820070, 0x8fbf0030, 0x8fbe002c, 0x8fb50028, 0x8fb30024, 0x8fb10020, 0x3e00008, 0x27bd0038, 0x0, 0x0, 0x0, 0x8f820040, 0x3c03f000, 0x431824, 0x3c025000, 0x10620005, 0x3c026000, @@ -3272,13 +3294,13 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x8f820054, 0x244203e8, 0xaf820058, 0x240201f4, 0xaec200c8, 0x24020004, 0xaec200d0, 0x24020002, 0xaec000a0, 0xaec000cc, 0xaec200c4, 0xaec000c0, 0xaec000bc, 0x3e00008, 0xaec000b8, 0x8f820054, 0x24420005, 0x3e00008, -0xaf820078, 0x27bdffe8, 0xafbf0010, 0x8f820054, 0x3c030001, 0x8c6332bc, -0x244203e8, 0x1060001d, 0xaf820058, 0x3c020001, 0x8c4232a8, 0x30420001, -0x1440000c, 0x0, 0x3c020001, 0x8c4233c8, 0x10400008, 0x0, -0x8f830224, 0x3c020001, 0x8c42548c, 0x10620003, 0x0, 0xc003a65, +0xaf820078, 0x27bdffe8, 0xafbf0010, 0x8f820054, 0x3c030001, 0x8c63341c, +0x244203e8, 0x1060001d, 0xaf820058, 0x3c020001, 0x8c423408, 0x30420001, +0x1440000c, 0x0, 0x3c020001, 0x8c423528, 0x10400008, 0x0, +0x8f830224, 0x3c020001, 0x8c4255ec, 0x10620003, 0x0, 0xc003ab1, 0x0, 0x92c200ec, 0x10400003, 0x3c0208ff, 0x1000000a, 0xa2c000ec, 0x3442fffb, 0x8f830220, 0x3c040200, 0x284a025, 0x621824, 0x10000003, -0xaf830220, 0xc003d6d, 0x0, 0x8f420238, 0x1040000a, 0x0, +0xaf830220, 0xc003db9, 0x0, 0x8f420238, 0x1040000a, 0x0, 0x8ec200a0, 0x244203e8, 0xaec200a0, 0x8f430238, 0x43102b, 0x14400003, 0x0, 0xc001c3c, 0x0, 0x8f420218, 0x30420100, 0x10400003, 0x0, 0xc001e07, 0x0, 0x8ec200c0, 0x8ec300c4, 0x24420001, @@ -3297,14 +3319,14 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x3c020001, 0x571021, 0x8c4281d4, 0x10400023, 0x24070008, 0x8ed10018, 0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020012, 0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, -0x24020001, 0x3c040001, 0x24842690, 0xafb10010, 0xafa00014, 0x8ec6002c, -0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f006, 0x1021, 0x14400005, +0x24020001, 0x3c040001, 0x248427c0, 0xafb10010, 0xafa00014, 0x8ec6002c, +0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f006, 0x1021, 0x14400005, 0x24020001, 0x3c010001, 0x370821, 0x1000005c, 0xac2281d4, 0x3c010001, 0x370821, 0x10000022, 0xac2081d0, 0x8ed10018, 0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020019, 0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, 0x24020001, 0x3c040001, -0x24842690, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, -0xc0028eb, 0x34a5f006, 0x1021, 0x14400005, 0x24020001, 0x3c010001, +0x248427c0, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, +0xc00290f, 0x34a5f006, 0x1021, 0x14400005, 0x24020001, 0x3c010001, 0x370821, 0x1000003a, 0xac2281d8, 0x3c010001, 0x370821, 0xac2281d0, 0x3c010001, 0x370821, 0xac2081d8, 0x3c010001, 0x370821, 0xac2081d4, 0x8ec20264, 0xaec00024, 0xaed10028, 0x24420001, 0xaec20264, 0x1000002a, @@ -3323,8 +3345,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0xafbf0024, 0xafb10020, 0x8ec30068, 0x8ec2006c, 0x10620029, 0x24070008, 0x8ed10068, 0x8ee40490, 0x8ee50494, 0x8ec30008, 0x8f860120, 0x24020013, 0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, -0x1440000b, 0x24020001, 0x3c040001, 0x2484269c, 0xafb10010, 0xafa00014, -0x8ec60068, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f008, 0x1021, +0x1440000b, 0x24020001, 0x3c040001, 0x248427cc, 0xafb10010, 0xafa00014, +0x8ec60068, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f008, 0x1021, 0x14400005, 0x24020001, 0x3c010001, 0x370821, 0x1000000e, 0xac2281e0, 0x3c010001, 0x370821, 0xac2081e0, 0x8ec20268, 0xaec00048, 0xaed1006c, 0x24420001, 0xaec20268, 0x10000004, 0x8ec20268, 0x3c010001, 0x370821, @@ -3333,15 +3355,15 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x8f820048, 0x1040fffd, 0x0, 0x8f820060, 0x431024, 0xaf820060, 0x8ec20000, 0x10400003, 0x0, 0x10000002, 0xaf80004c, 0xaf800048, 0x8fbf0024, 0x8fb10020, 0x3e00008, 0x27bd0028, 0x3e00008, 0x0, -0x3c020001, 0x8c4232bc, 0x27bdffc0, 0xafbf0038, 0xafbe0034, 0xafb50030, +0x3c020001, 0x8c42341c, 0x27bdffc0, 0xafbf0038, 0xafbe0034, 0xafb50030, 0xafb3002c, 0x104000fe, 0xafb10028, 0x8ec200b8, 0x24430001, 0x2842000b, 0x1440011b, 0xaec300b8, 0xaec000b8, 0x8ee204a8, 0x30420002, 0x14400096, -0x0, 0x8ee204a8, 0x3c030001, 0x8c6332ac, 0x34420002, 0xaee204a8, +0x0, 0x8ee204a8, 0x3c030001, 0x8c63340c, 0x34420002, 0xaee204a8, 0x24020001, 0x14620003, 0x3c020600, 0x10000002, 0x34423000, 0x34421000, 0xafa20020, 0x8ec3002c, 0x240200ff, 0x10620004, 0x27a70020, 0x8ec2002c, 0x10000002, 0x24530001, 0x9821, 0x8f420228, 0x1662000f, 0x0, -0x3c040001, 0x248426c8, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, -0x3c050009, 0xc0028eb, 0x34a5f00f, 0x8ec202a0, 0x24420001, 0xaec202a0, +0x3c040001, 0x248427f8, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, +0x3c050009, 0xc00290f, 0x34a5f00f, 0x8ec202a0, 0x24420001, 0xaec202a0, 0x1000006d, 0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021, 0x8ce30000, 0x8ce40004, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 0x1040001e, 0xa821, 0x241e000c, 0x8ec8002c, @@ -3350,7 +3372,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x822021, 0x892021, 0x630c0, 0xafa80018, 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 0x54400006, 0x24150001, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffe5, 0x0, 0x32a200ff, 0x54400011, 0xaed3002c, -0x3c040001, 0x248426d4, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, +0x3c040001, 0x24842804, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0x10000030, 0x34a5f010, 0x8ec2026c, 0x24150001, 0x24420001, 0xaec2026c, 0x8ec2026c, 0x1000001f, 0x32a200ff, 0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 0x10400017, 0xa821, 0x3c1e0020, @@ -3358,8 +3380,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0xafb30010, 0x5e1025, 0xafa30014, 0xafa20018, 0x8ec200a8, 0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe2, 0x0, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffed, 0x0, 0x32a200ff, 0x1440000f, 0x0, -0x3c040001, 0x248426e0, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, -0x3c050009, 0x34a5f011, 0xc0028eb, 0x0, 0x8ec202d0, 0x24420001, +0x3c040001, 0x24842810, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, +0x3c050009, 0x34a5f011, 0xc00290f, 0x0, 0x8ec202d0, 0x24420001, 0xaec202d0, 0x8ec202d0, 0x8ec20250, 0x24420001, 0xaec20250, 0x8ec20250, 0x8ee204a8, 0x30420001, 0x10400054, 0x0, 0x8f420218, 0x30420080, 0x1040002b, 0x0, 0x8f820044, 0x34420040, 0xaf820044, 0x8ec200b0, @@ -3384,15 +3406,15 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x24430001, 0x284201f5, 0x14400005, 0xaec300bc, 0x8f820044, 0x38420020, 0xaf820044, 0xaec000bc, 0x2402ff7f, 0x282a024, 0x8fbf0038, 0x8fbe0034, 0x8fb50030, 0x8fb3002c, 0x8fb10028, 0x3e00008, 0x27bd0040, 0x3e00008, -0x0, 0x3c020001, 0x8c4232bc, 0x27bdffc0, 0xafbf0038, 0xafbe0034, +0x0, 0x3c020001, 0x8c42341c, 0x27bdffc0, 0xafbf0038, 0xafbe0034, 0xafb50030, 0xafb3002c, 0x10400100, 0xafb10028, 0x8ec200b8, 0x3c040001, -0x8c8432ac, 0x24430001, 0x2842000b, 0xaec400d0, 0x14400127, 0xaec300b8, +0x8c84340c, 0x24430001, 0x2842000b, 0xaec400d0, 0x14400127, 0xaec300b8, 0xaec000b8, 0x8ee204a8, 0x30420002, 0x14400094, 0x0, 0x8ee204a8, 0x34420002, 0xaee204a8, 0x24020001, 0x14820003, 0x3c020600, 0x10000002, 0x34423000, 0x34421000, 0xafa20020, 0x8ec3002c, 0x240200ff, 0x10620004, 0x27a70020, 0x8ec2002c, 0x10000002, 0x24530001, 0x9821, 0x8f420228, -0x1662000f, 0x0, 0x3c040001, 0x248426c8, 0xafa00010, 0xafa00014, -0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f00f, 0x8ec202a0, +0x1662000f, 0x0, 0x3c040001, 0x248427f8, 0xafa00010, 0xafa00014, +0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f00f, 0x8ec202a0, 0x24420001, 0xaec202a0, 0x1000006d, 0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021, 0x8ce30000, 0x8ce40004, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 0x1040001e, 0xa821, @@ -3401,7 +3423,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0xa32821, 0xa3482b, 0x822021, 0x892021, 0x630c0, 0xafa80018, 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 0x54400006, 0x24150001, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffe5, 0x0, 0x32a200ff, -0x54400011, 0xaed3002c, 0x3c040001, 0x248426d4, 0xafa00010, 0xafa00014, +0x54400011, 0xaed3002c, 0x3c040001, 0x24842804, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0x10000030, 0x34a5f010, 0x8ec2026c, 0x24150001, 0x24420001, 0xaec2026c, 0x8ec2026c, 0x1000001f, 0x32a200ff, 0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 0x10400017, @@ -3409,35 +3431,35 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x8ec3002c, 0x8f860120, 0xafb30010, 0x5e1025, 0xafa30014, 0xafa20018, 0x8ec200a8, 0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe2, 0x0, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffed, 0x0, 0x32a200ff, -0x1440000f, 0x0, 0x3c040001, 0x248426e0, 0xafa00010, 0xafa00014, -0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f011, 0xc0028eb, 0x0, +0x1440000f, 0x0, 0x3c040001, 0x24842810, 0xafa00010, 0xafa00014, +0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f011, 0xc00290f, 0x0, 0x8ec202d0, 0x24420001, 0xaec202d0, 0x8ec202d0, 0x8ec20250, 0x24420001, 0xaec20250, 0x8ec20250, 0x8ee204a8, 0x30420001, 0x10400055, 0x0, 0x8f420218, 0x30420080, 0x10400027, 0x0, 0x8ec200b0, 0x3c040001, -0x90843370, 0x24080000, 0x2409ffff, 0x403821, 0x8ec201b8, 0x8ec301bc, -0x3021, 0x34840020, 0x3c010001, 0xa0243370, 0x481024, 0x1446000d, +0x908434d0, 0x24080000, 0x2409ffff, 0x403821, 0x8ec201b8, 0x8ec301bc, +0x3021, 0x34840020, 0x3c010001, 0xa02434d0, 0x481024, 0x1446000d, 0x691824, 0x1467000b, 0x0, 0x8ec200b4, 0x403821, 0x8ec201d8, 0x8ec301dc, 0x3021, 0x481024, 0x14460003, 0x691824, 0x10670009, -0x308200bf, 0x8ec201b8, 0x8ec301bc, 0x3c040001, 0x90843370, 0x8ec601d8, -0x8ec701dc, 0x10000026, 0x38840040, 0x3c010001, 0x10000061, 0xa0223370, -0x8ec200b0, 0x3c040001, 0x90843370, 0x24080000, 0x2409ffff, 0x403821, -0x8ec201b8, 0x8ec301bc, 0x3021, 0x308400bf, 0x3c010001, 0xa0243370, +0x308200bf, 0x8ec201b8, 0x8ec301bc, 0x3c040001, 0x908434d0, 0x8ec601d8, +0x8ec701dc, 0x10000026, 0x38840040, 0x3c010001, 0x10000061, 0xa02234d0, +0x8ec200b0, 0x3c040001, 0x908434d0, 0x24080000, 0x2409ffff, 0x403821, +0x8ec201b8, 0x8ec301bc, 0x3021, 0x308400bf, 0x3c010001, 0xa02434d0, 0x481024, 0x1446000d, 0x691824, 0x1467000b, 0x0, 0x8ec200b4, 0x403821, 0x8ec201d8, 0x8ec301dc, 0x3021, 0x481024, 0x14460003, 0x691824, 0x1067000d, 0x34820020, 0x8ec201b8, 0x8ec301bc, 0x3c040001, -0x90843370, 0x8ec601d8, 0x8ec701dc, 0x38840020, 0xaec300b0, 0xaec700b4, -0x3c010001, 0x1000003a, 0xa0243370, 0x3c010001, 0x10000037, 0xa0223370, -0x3c020001, 0x90423370, 0x8ec300bc, 0x34440020, 0x24620001, 0x10000028, +0x908434d0, 0x8ec601d8, 0x8ec701dc, 0x38840020, 0xaec300b0, 0xaec700b4, +0x3c010001, 0x1000003a, 0xa02434d0, 0x3c010001, 0x10000037, 0xa02234d0, +0x3c020001, 0x904234d0, 0x8ec300bc, 0x34440020, 0x24620001, 0x10000028, 0x28630033, 0x8ec200cc, 0x8ec300c8, 0x24420001, 0xaec200cc, 0x43102a, 0x14400006, 0x24030001, 0x8ec200d0, 0x14430002, 0xaec000cc, 0x24030004, 0xaec300d0, 0x8ee204a8, 0x30420001, 0x10400012, 0x0, 0x8f420218, -0x30420080, 0x10400008, 0x0, 0x3c020001, 0x90423370, 0x34420040, -0x304200df, 0x3c010001, 0x10000015, 0xa0223370, 0x3c020001, 0x90423370, -0x34420060, 0x3c010001, 0x1000000f, 0xa0223370, 0x3c020001, 0x90423370, -0x8ec300bc, 0x34440020, 0x24620001, 0x286300fb, 0x3c010001, 0xa0243370, -0x14600005, 0xaec200bc, 0x38820040, 0x3c010001, 0xa0223370, 0xaec000bc, -0x3c020001, 0x90423370, 0x8ec300d0, 0x3044007f, 0x24020001, 0x3c010001, -0xa0243370, 0x54620003, 0x3484000f, 0x42102, 0x348400f0, 0xc004904, +0x30420080, 0x10400008, 0x0, 0x3c020001, 0x904234d0, 0x34420040, +0x304200df, 0x3c010001, 0x10000015, 0xa02234d0, 0x3c020001, 0x904234d0, +0x34420060, 0x3c010001, 0x1000000f, 0xa02234d0, 0x3c020001, 0x904234d0, +0x8ec300bc, 0x34440020, 0x24620001, 0x286300fb, 0x3c010001, 0xa02434d0, +0x14600005, 0xaec200bc, 0x38820040, 0x3c010001, 0xa02234d0, 0xaec000bc, +0x3c020001, 0x904234d0, 0x8ec300d0, 0x3044007f, 0x24020001, 0x3c010001, +0xa02434d0, 0x54620003, 0x3484000f, 0x42102, 0x348400f0, 0xc004950, 0x0, 0x2402ff7f, 0x282a024, 0x8fbf0038, 0x8fbe0034, 0x8fb50030, 0x8fb3002c, 0x8fb10028, 0x3e00008, 0x27bd0040, 0x3e00008, 0x0, 0x27bdffc0, 0xafbf0038, 0xafbe0034, 0xafb50030, 0xafb3002c, 0xafb10028, @@ -3477,7 +3499,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x8ec200a8, 0x26e60028, 0x40f809, 0x24070400, 0x104000f1, 0x3c020400, 0xafa20020, 0x92c20115, 0x10400080, 0x240200ff, 0x8ec3002c, 0x10620004, 0x27a70020, 0x8ec2002c, 0x10000002, 0x24530001, 0x9821, 0x8f420228, -0x1662000a, 0x0, 0x3c040001, 0x248426c8, 0xafa00010, 0xafa00014, +0x1662000a, 0x0, 0x3c040001, 0x248427f8, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0x1000007f, 0x34a5f00f, 0x8ec2002c, 0x210c0, 0x571021, 0x8ce30000, 0x8ce40004, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 0x1040001e, @@ -3486,8 +3508,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x8ec80008, 0xa32821, 0xa3482b, 0x822021, 0x892021, 0x630c0, 0xafa80018, 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 0x54400006, 0x24150001, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffe5, 0x0, -0x32a200ff, 0x54400018, 0xaed3002c, 0x3c040001, 0x248426d4, 0xafa00010, -0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f010, 0xc0028eb, +0x32a200ff, 0x54400018, 0xaed3002c, 0x3c040001, 0x24842804, 0xafa00010, +0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f010, 0xc00290f, 0x0, 0x8ec202d0, 0x1821, 0x24420001, 0xaec202d0, 0x1000008f, 0x8ec202d0, 0x8ec2026c, 0x24150001, 0x24420001, 0xaec2026c, 0x8ec2026c, 0x1000001d, 0x32a200ff, 0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, @@ -3495,23 +3517,23 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x8ee5048c, 0x8ec2002c, 0x8f860120, 0xafb30010, 0xafa20014, 0xafa30018, 0x8ec200a8, 0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe4, 0x0, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffee, 0x0, 0x32a200ff, -0x1440006a, 0x24030001, 0x3c040001, 0x248426e0, 0xafa00010, 0xafa00014, +0x1440006a, 0x24030001, 0x3c040001, 0x24842810, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0x1000ffcb, 0x34a5f011, 0x8ec3002c, 0x10620004, 0x27a70020, 0x8ec2002c, 0x10000002, 0x24510001, 0x8821, -0x8f420228, 0x16220011, 0x4021, 0x3c040001, 0x248426a8, 0xafa00010, -0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0x34a5f005, 0xc0028eb, +0x8f420228, 0x16220011, 0x4021, 0x3c040001, 0x248427d8, 0xafa00010, +0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0x34a5f005, 0xc00290f, 0x0, 0x8ec202a0, 0x1821, 0x24420001, 0xaec202a0, 0x10000047, 0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021, 0x8ce30000, 0x8ce40004, 0xac4304c0, 0xac4404c4, 0x8ec3002c, 0x8ee40428, 0x8ee5042c, 0x8ec6002c, 0x24070008, 0x2402000d, 0xafa20010, 0xafb10014, 0x8ec20008, 0x318c0, 0x604821, 0xa92821, 0xa9182b, 0x882021, 0x832021, 0x630c0, 0xafa20018, 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 0x5440000c, -0xaed1002c, 0x3c040001, 0x248426b4, 0xafa00010, 0xafa00014, 0x8ec6002c, -0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f000, 0x1000001e, 0x1821, +0xaed1002c, 0x3c040001, 0x248427e4, 0xafa00010, 0xafa00014, 0x8ec6002c, +0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f000, 0x1000001e, 0x1821, 0x8ee40488, 0x8ee5048c, 0x8ec3002c, 0x8ec80008, 0x8f860120, 0x24020011, 0xafa20010, 0xafa30014, 0xafa80018, 0x8ec200a8, 0x24070008, 0x40f809, -0x24c6001c, 0x1440000f, 0x24030001, 0x3c040001, 0x248426bc, 0xafa00010, -0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f001, +0x24c6001c, 0x1440000f, 0x24030001, 0x3c040001, 0x248427ec, 0xafa00010, +0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f001, 0x8ec202a4, 0x1821, 0x24420001, 0xaec202a4, 0x8ec202a4, 0x1060000d, 0x24020001, 0x8ec2024c, 0xa2c00115, 0xaec000a0, 0x24420001, 0xaec2024c, 0x8ec2024c, 0x8ee2014c, 0x24420001, 0xaee2014c, 0x10000003, 0x8ee2014c, @@ -3524,15 +3546,15 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x8f8200b0, 0x2403fffb, 0x431024, 0xaf8200b0, 0x8f82011c, 0x2403fffd, 0x431024, 0x10000040, 0xaf82011c, 0x8ec30104, 0x8f820104, 0x14620005, 0x0, 0x8ec3010c, 0x8f8200b4, 0x5062000a, 0x3c050005, 0x8f820104, -0xaec20104, 0x8f8200b4, 0xaec2010c, 0x8ec2010c, 0x3c040001, 0x248426ec, -0x10000029, 0xafa00014, 0x8ec2010c, 0x3c040001, 0x248426f8, 0xafa00014, -0xafa20010, 0x8f8600b0, 0x8ec70104, 0xc0028eb, 0x34a50900, 0x8f82011c, +0xaec20104, 0x8f8200b4, 0xaec2010c, 0x8ec2010c, 0x3c040001, 0x2484281c, +0x10000029, 0xafa00014, 0x8ec2010c, 0x3c040001, 0x24842828, 0xafa00014, +0xafa20010, 0x8f8600b0, 0x8ec70104, 0xc00290f, 0x34a50900, 0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830104, 0x8f8200b0, 0x34420001, 0xaf8200b0, 0xaf830104, 0x8f440208, 0x8f45020c, 0x2402000f, 0xafa20010, 0xafa00014, 0x8ec20008, 0xafa20018, 0x8ec200a8, 0x26e60028, 0x40f809, 0x24070400, 0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201cc, 0x24420001, -0xaee201cc, 0x8ee201cc, 0x8ec2010c, 0x3c040001, 0x24842704, 0xafa00014, -0xafa20010, 0x8f8600b0, 0x8ec70104, 0x3c050005, 0xc0028eb, 0x34a50900, +0xaee201cc, 0x8ee201cc, 0x8ec2010c, 0x3c040001, 0x24842834, 0xafa00014, +0xafa20010, 0x8f8600b0, 0x8ec70104, 0x3c050005, 0xc00290f, 0x34a50900, 0x8f8200a0, 0x30420004, 0x1040005f, 0x0, 0x8ec30108, 0x8f820124, 0x14620005, 0x0, 0x8ec30110, 0x8f8200a4, 0x10620006, 0x0, 0x8f820124, 0xaec20108, 0x8f8200a4, 0x10000052, 0xaec20110, 0x8f8200a0, @@ -3541,15 +3563,15 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x2403fffd, 0x431024, 0x10000041, 0xaf82011c, 0x8ec30108, 0x8f820124, 0x14620005, 0x0, 0x8ec30110, 0x8f8200a4, 0x5062000a, 0x3c050005, 0x8f820124, 0xaec20108, 0x8f8200a4, 0xaec20110, 0x8ec20110, 0x3c040001, -0x24842710, 0x1000002a, 0xafa00014, 0x8ec20110, 0x3c040001, 0x2484271c, -0xafa00014, 0xafa20010, 0x8f8600a0, 0x8ec70108, 0xc0028eb, 0x34a50900, +0x24842840, 0x1000002a, 0xafa00014, 0x8ec20110, 0x3c040001, 0x2484284c, +0xafa00014, 0xafa20010, 0x8f8600a0, 0x8ec70108, 0xc00290f, 0x34a50900, 0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830124, 0x8f8200a0, 0x34420001, 0xaf8200a0, 0xaf830124, 0x8f440208, 0x8f45020c, 0x24020010, 0xafa20010, -0xafa00014, 0x8ec20010, 0xafa20018, 0x8ec200a4, 0x3c060001, 0x24c63384, +0xafa00014, 0x8ec20010, 0xafa20018, 0x8ec200a4, 0x3c060001, 0x24c634e4, 0x40f809, 0x24070004, 0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201cc, 0x24420001, 0xaee201cc, 0x8ee201cc, 0x8ec20110, 0x3c040001, -0x24842728, 0xafa00014, 0xafa20010, 0x8f8600a0, 0x8ec70108, 0x3c050005, -0xc0028eb, 0x34a50900, 0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3c091000, +0x24842858, 0xafa00014, 0xafa20010, 0x8f8600a0, 0x8ec70108, 0x3c050005, +0xc00290f, 0x34a50900, 0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3c091000, 0x24080001, 0x3c070080, 0x3c050100, 0x3c062000, 0x8f820070, 0x491024, 0x1040fffd, 0x0, 0x8f820054, 0x24420005, 0xaf820078, 0x8f420234, 0x10400017, 0x2021, 0x3c020001, 0x571021, 0x8c4281dc, 0x24420005, @@ -3576,7 +3598,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x0, 0x10000002, 0xaf80004c, 0xaf800048, 0x8ec20260, 0x24420001, 0xaec20260, 0x1000006f, 0x8ec20260, 0x30c20001, 0x10400004, 0x24020001, 0xaf820064, 0x10000069, 0x0, 0x30c20002, 0x1440000b, 0x3c050003, -0x3c040001, 0x24842800, 0x34a50001, 0x3821, 0xafa00010, 0xc0028eb, +0x3c040001, 0x24842930, 0x34a50001, 0x3821, 0xafa00010, 0xc00290f, 0xafa00014, 0x2402fff8, 0x1000005c, 0xaf820064, 0x8f43022c, 0x8f42010c, 0x1062004c, 0x0, 0x8f42022c, 0x21080, 0x5a1021, 0x8c440300, 0x8f42022c, 0x24420001, 0x3042003f, 0x41e02, 0xaf42022c, 0x24020003, @@ -3596,15 +3618,15 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x3e00008, 0x27bd0020, 0x3e00008, 0x0, 0x27bdffc0, 0xafb10028, 0x808821, 0x111602, 0x2442ffff, 0x304300ff, 0x2c620011, 0xafbf0038, 0xafbe0034, 0xafb50030, 0x104001ab, 0xafb3002c, 0x31080, 0x3c010001, -0x220821, 0x8c222848, 0x400008, 0x0, 0x111302, 0x30440fff, +0x220821, 0x8c222978, 0x400008, 0x0, 0x111302, 0x30440fff, 0x24020001, 0x10820006, 0x3c030800, 0x24020002, 0x1082000c, 0x3c050003, -0x10000022, 0x0, 0x3c020001, 0x8c4233b4, 0x21100, 0x21182, +0x10000022, 0x0, 0x3c020001, 0x8c423514, 0x21100, 0x21182, 0x431025, 0xae420038, 0x8ee204a8, 0x1000000a, 0x34420001, 0x3c020001, -0x2442c440, 0x21100, 0x21182, 0x431025, 0xae420038, 0x8ee204a8, +0x2442c4d0, 0x21100, 0x21182, 0x431025, 0xae420038, 0x8ee204a8, 0x2403fffe, 0x431024, 0xaee204a8, 0xaec40168, 0xaec4016c, 0x8f840054, 0x41442, 0x41c82, 0x431021, 0x41cc2, 0x431023, 0x41d02, 0x431021, 0x41d42, 0x431023, 0x10000009, 0xaec20170, 0x3c040001, -0x2484280c, 0x34a50004, 0x2203021, 0x3821, 0xafa00010, 0xc0028eb, +0x2484293c, 0x34a50004, 0x2203021, 0x3821, 0xafa00010, 0xc00290f, 0xafa00014, 0x8ec20208, 0x24420001, 0xaec20208, 0x100001e1, 0x8ec20208, 0xc0022fe, 0x0, 0x100001dd, 0x0, 0xc002419, 0x0, 0x100001d9, 0x0, 0x111302, 0x30430fff, 0x24020001, 0x10620005, @@ -3614,24 +3636,24 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0xaf82022c, 0xaf820230, 0xaf820234, 0x24020001, 0x10000016, 0xa2c2011c, 0x92c2011c, 0x50400013, 0xa2c0011c, 0x8ee204ac, 0xaf820228, 0x8ee204b0, 0xaf82022c, 0x8ee204b4, 0xaf820230, 0x8ee204b8, 0xaf820234, 0x10000009, -0xa2c0011c, 0x3c040001, 0x24842818, 0x34a5f009, 0x2203021, 0x3821, -0xafa00010, 0xc0028eb, 0xafa00014, 0x8ec20234, 0x24420001, 0xaec20234, +0xa2c0011c, 0x3c040001, 0x24842948, 0x34a5f009, 0x2203021, 0x3821, +0xafa00010, 0xc00290f, 0xafa00014, 0x8ec20234, 0x24420001, 0xaec20234, 0x100001a3, 0x8ec20234, 0x111302, 0x30440fff, 0x24020001, 0x10820005, 0x24020002, 0x1082000d, 0x3c050003, 0x10000013, 0x0, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420008, 0xaf820220, 0x24020001, 0xa2c2011d, 0x10000011, 0xaec40200, 0x8f820220, 0x3c0308ff, 0x3463fff7, 0x431024, 0xaf820220, 0xa2c0011d, 0x10000009, 0xaec40200, 0x3c040001, -0x24842824, 0x34a5f00a, 0x2203021, 0x3821, 0xafa00010, 0xc0028eb, +0x24842954, 0x34a5f00a, 0x2203021, 0x3821, 0xafa00010, 0xc00290f, 0xafa00014, 0x8ec20224, 0x24420001, 0xaec20224, 0x1000017b, 0x8ec20224, -0x27840208, 0x27450200, 0xc00297e, 0x24060008, 0x26c4018c, 0x27450200, -0xc00297e, 0x24060008, 0x8ec2022c, 0x24420001, 0xaec2022c, 0x1000016e, +0x27840208, 0x27450200, 0xc0029a2, 0x24060008, 0x26c4018c, 0x27450200, +0xc0029a2, 0x24060008, 0x8ec2022c, 0x24420001, 0xaec2022c, 0x1000016e, 0x8ec2022c, 0x111302, 0x30430fff, 0x24020001, 0x10620011, 0x28620002, 0x50400005, 0x24020002, 0x10600007, 0x0, 0x10000017, 0x0, 0x1062000f, 0x0, 0x10000013, 0x0, 0x8f460248, 0x24040001, -0xc004680, 0x24050004, 0x10000007, 0x0, 0x8f460248, 0x24040001, -0xc004680, 0x24050004, 0x10000010, 0x0, 0x8f46024c, 0x24040001, -0xc004680, 0x24050001, 0x1000000a, 0x0, 0x3c040001, 0x24842830, -0x3c050003, 0x34a50005, 0x2203021, 0x3821, 0xafa00010, 0xc0028eb, +0xc0046cc, 0x24050004, 0x10000007, 0x0, 0x8f460248, 0x24040001, +0xc0046cc, 0x24050004, 0x10000010, 0x0, 0x8f46024c, 0x24040001, +0xc0046cc, 0x24050001, 0x1000000a, 0x0, 0x3c040001, 0x24842960, +0x3c050003, 0x34a50005, 0x2203021, 0x3821, 0xafa00010, 0xc00290f, 0xafa00014, 0x8ec20228, 0x24420001, 0xaec20228, 0x1000013f, 0x8ec20228, 0xc002221, 0x0, 0x1000013b, 0x0, 0x24020001, 0xa2c20528, 0x24110014, 0x8ee404a0, 0x8ee504a4, 0xafb10010, 0xafa00014, 0x8ec20010, @@ -3639,8 +3661,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x0, 0x1000012a, 0x0, 0x3c020900, 0xaec00054, 0xaec00058, 0xaec0005c, 0xaec00060, 0xaec002c0, 0xa2c00065, 0xafa20020, 0x8ec3002c, 0x240200ff, 0x10620004, 0x27a70020, 0x8ec2002c, 0x10000002, 0x24530001, -0x9821, 0x8f420228, 0x1662000f, 0x0, 0x3c040001, 0x248427dc, -0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, +0x9821, 0x8f420228, 0x1662000f, 0x0, 0x3c040001, 0x2484290c, +0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f00f, 0x8ec202a0, 0x24420001, 0xaec202a0, 0x1000006b, 0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021, 0x8ce30000, 0x8ce40004, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, @@ -3649,7 +3671,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x1021, 0x8ec80008, 0xa32821, 0xa3482b, 0x822021, 0x892021, 0x630c0, 0xafa80018, 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 0x54400006, 0x24150001, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffe5, -0x0, 0x32a200ff, 0x54400011, 0xaed3002c, 0x3c040001, 0x248427e8, +0x0, 0x32a200ff, 0x54400011, 0xaed3002c, 0x3c040001, 0x24842918, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0x1000002e, 0x34a5f010, 0x8ec2026c, 0x24150001, 0x24420001, 0xaec2026c, 0x8ec2026c, 0x1000001d, 0x32a200ff, 0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, @@ -3657,33 +3679,33 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x8ee5048c, 0x8ec2002c, 0x8f860120, 0xafb30010, 0xafa20014, 0xafa30018, 0x8ec200a8, 0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe4, 0x0, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffee, 0x0, 0x32a200ff, -0x1440000f, 0x0, 0x3c040001, 0x248427f4, 0xafa00010, 0xafa00014, -0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f011, 0xc0028eb, 0x0, +0x1440000f, 0x0, 0x3c040001, 0x24842924, 0xafa00010, 0xafa00014, +0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f011, 0xc00290f, 0x0, 0x8ec202d0, 0x24420001, 0xaec202d0, 0x8ec202d0, 0x8ec20218, 0x24420001, 0xaec20218, 0x8ec20218, 0x8ec2025c, 0x24420001, 0xaec2025c, 0x10000096, 0x8ec2025c, 0x8f42025c, 0x26c4018c, 0xaec20158, 0x8f420260, 0x27450200, -0x24060008, 0xc00297e, 0xaec20160, 0x8f820220, 0x30420008, 0x14400002, +0x24060008, 0xc0029a2, 0xaec20160, 0x8f820220, 0x30420008, 0x14400002, 0x24020001, 0x24020002, 0xaec20200, 0x8ec20214, 0x24420001, 0xaec20214, 0x10000083, 0x8ec20214, 0x3c0200ff, 0x96e30462, 0x3442ffff, 0x2222024, 0x3402fffb, 0x44102b, 0x38420001, 0x30630003, 0x2c630001, 0x621824, -0x10600003, 0x0, 0x10000075, 0xaec40050, 0x3c040001, 0x2484283c, -0x3c050003, 0x34a5f00f, 0x2203021, 0x3821, 0xafa00010, 0xc0028eb, +0x10600003, 0x0, 0x10000075, 0xaec40050, 0x3c040001, 0x2484296c, +0x3c050003, 0x34a5f00f, 0x2203021, 0x3821, 0xafa00010, 0xc00290f, 0xafa00014, 0x3c030700, 0x34631000, 0x111602, 0x431025, 0xafa20020, 0x8ec3002c, 0x240200ff, 0x10620004, 0x27a70020, 0x8ec2002c, 0x10000002, 0x24510001, 0x8821, 0x8f420228, 0x1622000f, 0x4021, 0x3c040001, -0x248427bc, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, -0xc0028eb, 0x34a5f005, 0x8ec202a0, 0x24420001, 0xaec202a0, 0x10000046, +0x248428ec, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, +0xc00290f, 0x34a5f005, 0x8ec202a0, 0x24420001, 0xaec202a0, 0x10000046, 0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021, 0x8ce30000, 0x8ce40004, 0xac4304c0, 0xac4404c4, 0x8ec3002c, 0x8ee40428, 0x8ee5042c, 0x8ec6002c, 0x24070008, 0x2402000d, 0xafa20010, 0xafb10014, 0x8ec20008, 0x318c0, 0x604821, 0xa92821, 0xa9182b, 0x882021, 0x832021, 0x630c0, 0xafa20018, 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 0x5440000c, -0xaed1002c, 0x3c040001, 0x248427c8, 0xafa00010, 0xafa00014, 0x8ec6002c, -0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f000, 0x1000001d, 0x0, +0xaed1002c, 0x3c040001, 0x248428f8, 0xafa00010, 0xafa00014, 0x8ec6002c, +0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f000, 0x1000001d, 0x0, 0x8ee40488, 0x8ee5048c, 0x8ec3002c, 0x8ec80008, 0x8f860120, 0x24020011, 0xafa20010, 0xafa30014, 0xafa80018, 0x8ec200a8, 0x24070008, 0x40f809, -0x24c6001c, 0x1440000e, 0x0, 0x3c040001, 0x248427d0, 0xafa00010, -0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f001, +0x24c6001c, 0x1440000e, 0x0, 0x3c040001, 0x24842900, 0xafa00010, +0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f001, 0x8ec202a4, 0x24420001, 0xaec202a4, 0x8ec202a4, 0x8ec20244, 0x24420001, 0xaec20244, 0x8ec20244, 0x8ec20254, 0x24420001, 0xaec20254, 0x8ec20254, 0x8fbf0038, 0x8fbe0034, 0x8fb50030, 0x8fb3002c, 0x8fb10028, 0x3e00008, @@ -3697,16 +3719,16 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0xaf820220, 0x8f820200, 0x3c03c0ff, 0x3463ffff, 0x431024, 0x34420004, 0xaf820200, 0x8ede02bc, 0x8ec702c0, 0xafa70014, 0x8ec702c4, 0xafa7001c, 0x8ec20238, 0x26c40128, 0x24420001, 0xaec20238, 0x8ed10238, 0x8ed3016c, -0x8ed50168, 0xc00296c, 0x24050400, 0xaede02bc, 0x8fa70014, 0xaec702c0, +0x8ed50168, 0xc002990, 0x24050400, 0xaede02bc, 0x8fa70014, 0xaec702c0, 0x8fa7001c, 0xaec702c4, 0xaed10238, 0xaed3016c, 0xaed50168, 0x8f42025c, 0x26c4018c, 0xaec20158, 0x8f420260, 0x27450200, 0x24060008, 0xaec20160, -0x24020006, 0xc00297e, 0xaec2015c, 0x3c023b9a, 0x3442ca00, 0xaec20164, +0x24020006, 0xc0029a2, 0xaec2015c, 0x3c023b9a, 0x3442ca00, 0xaec20164, 0x240203e8, 0x24040002, 0x24030001, 0xaec201fc, 0xaec401f8, 0xaec30204, 0x8f820220, 0x30420008, 0x10400004, 0x0, 0xaec30200, 0x10000003, -0x3021, 0xaec40200, 0x3021, 0x3c030001, 0x661821, 0x90633200, +0x3021, 0xaec40200, 0x3021, 0x3c030001, 0x661821, 0x90633360, 0x2c61021, 0x24c60001, 0xa0430194, 0x2cc2000f, 0x1440fff8, 0x2c61821, 0x24c60001, 0x8f820040, 0x27440080, 0x24050080, 0x21702, 0x24420030, -0xa0620194, 0x2c61021, 0xc00296c, 0xa0400194, 0x8fa70024, 0x30e20004, +0xa0620194, 0x2c61021, 0xc002990, 0xa0400194, 0x8fa70024, 0x30e20004, 0x14400006, 0x0, 0x8f820220, 0x3c0308ff, 0x3463fffb, 0x431024, 0xaf820220, 0x8fa7002c, 0x30e20004, 0x14400006, 0x0, 0x8f820200, 0x3c03c0ff, 0x3463fffb, 0x431024, 0xaf820200, 0x8fbf0040, 0x8fbe003c, @@ -3736,11 +3758,11 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x431026, 0x2c460001, 0xc01021, 0x14400005, 0x510c0, 0x2e21021, 0x944575c0, 0x14a0ffed, 0x510c0, 0xa03021, 0x10c00010, 0x610c0, 0x571821, 0x8c6375c0, 0x571021, 0xafa30010, 0x8c4275c4, 0x3c040001, -0x2484294c, 0xafa20014, 0x8f460210, 0x8f470214, 0x3c050003, 0xc0028eb, +0x24842a7c, 0xafa20014, 0x8f460210, 0x8f470214, 0x3c050003, 0xc00290f, 0x34a5f012, 0x10000051, 0x3c020800, 0x8ec50124, 0x10a00004, 0x510c0, 0x2e21021, 0x944275c0, 0xaec20124, 0xa03021, 0x14c0000f, 0x27440212, -0x810c0, 0x2e21021, 0xafa80010, 0x944271c0, 0x3c040001, 0x24842958, -0xafa20014, 0x8f460210, 0x8f470214, 0x3c050003, 0xc0028eb, 0x34a5f013, +0x810c0, 0x2e21021, 0xafa80010, 0x944271c0, 0x3c040001, 0x24842a88, +0xafa20014, 0x8f460210, 0x8f470214, 0x3c050003, 0xc00290f, 0x34a5f013, 0x1000003a, 0x3c020800, 0x628c0, 0x94830000, 0xb71021, 0x244275c2, 0xa4430000, 0x8c830002, 0x820c0, 0xac430002, 0x2e41021, 0x944371c0, 0x2e51021, 0xa44375c0, 0x2e41021, 0xa44671c0, 0x8ec20120, 0x24420001, @@ -3753,8 +3775,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x24020001, 0x821004, 0x621825, 0xaca30228, 0x3c020800, 0x34421000, 0xafa20020, 0x8ec3002c, 0x240200ff, 0x10620004, 0x27a70020, 0x8ec2002c, 0x10000002, 0x24530001, 0x9821, 0x8f420228, 0x1662000f, 0x0, -0x3c040001, 0x24842928, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, -0x3c050009, 0xc0028eb, 0x34a5f00f, 0x8ec202a0, 0x24420001, 0xaec202a0, +0x3c040001, 0x24842a58, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, +0x3c050009, 0xc00290f, 0x34a5f00f, 0x8ec202a0, 0x24420001, 0xaec202a0, 0x1000006b, 0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021, 0x8ce30000, 0x8ce40004, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 0x1040001e, 0xa821, 0x241e000d, 0x8ec8002c, @@ -3763,16 +3785,16 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x822021, 0x892021, 0x630c0, 0xafa80018, 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 0x54400006, 0x24150001, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffe5, 0x0, 0x32a200ff, 0x54400011, 0xaed3002c, -0x3c040001, 0x24842934, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, +0x3c040001, 0x24842a64, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0x1000002e, 0x34a5f010, 0x8ec2026c, 0x24150001, 0x24420001, 0xaec2026c, 0x8ec2026c, 0x1000001d, 0x32a200ff, 0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 0x10400015, 0xa821, 0x24130011, 0x8ec30008, 0x8ee40488, 0x8ee5048c, 0x8ec2002c, 0x8f860120, 0xafb30010, 0xafa20014, 0xafa30018, 0x8ec200a8, 0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe4, 0x0, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffee, -0x0, 0x32a200ff, 0x1440000f, 0x0, 0x3c040001, 0x24842940, +0x0, 0x32a200ff, 0x1440000f, 0x0, 0x3c040001, 0x24842a70, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f011, -0xc0028eb, 0x0, 0x8ec202d0, 0x24420001, 0xaec202d0, 0x8ec202d0, +0xc00290f, 0x0, 0x8ec202d0, 0x24420001, 0xaec202d0, 0x8ec202d0, 0x8ec2021c, 0x24420001, 0xaec2021c, 0x8ec2021c, 0x8ec20258, 0x24420001, 0xaec20258, 0x8ec20258, 0x8fbf0038, 0x8fbe0034, 0x8fb50030, 0x8fb3002c, 0x8fb10028, 0x3e00008, 0x27bd0040, 0x27bdffb0, 0x27440212, 0x24050006, @@ -3783,8 +3805,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x94a20004, 0x95230004, 0x431026, 0x2c460001, 0xc01021, 0x14400006, 0x710c0, 0xe04021, 0x2e21021, 0x944775c0, 0x14e0ffec, 0x710c0, 0xe02821, 0x14a0000f, 0xafa80028, 0x410c0, 0x2e21021, 0xafa40010, -0x944271c0, 0x3c040001, 0x24842964, 0xafa20014, 0x8f460210, 0x8f470214, -0x3c050003, 0xc0028eb, 0x34a5f01c, 0x10000062, 0x3c020800, 0x11000007, +0x944271c0, 0x3c040001, 0x24842a94, 0xafa20014, 0x8f460210, 0x8f470214, +0x3c050003, 0xc00290f, 0x34a5f01c, 0x10000062, 0x3c020800, 0x11000007, 0x510c0, 0x2e21021, 0x944375c0, 0x810c0, 0x2e21021, 0x10000006, 0xa44375c0, 0x2e21021, 0x944375c0, 0x410c0, 0x2e21021, 0xa44371c0, 0x8ec30124, 0x510c0, 0x2e21021, 0x26e871c0, 0xa44375c0, 0x8ec20120, @@ -3803,8 +3825,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x8c420228, 0x831804, 0x31827, 0x431024, 0xaca20228, 0x3c020800, 0x34422000, 0xafa20020, 0x8ec3002c, 0x240200ff, 0x10620004, 0x27a70020, 0x8ec2002c, 0x10000002, 0x24530001, 0x9821, 0x8f420228, 0x1662000f, -0x0, 0x3c040001, 0x24842928, 0xafa00010, 0xafa00014, 0x8ec6002c, -0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f00f, 0x8ec202a0, 0x24420001, +0x0, 0x3c040001, 0x24842a58, 0xafa00010, 0xafa00014, 0x8ec6002c, +0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f00f, 0x8ec202a0, 0x24420001, 0xaec202a0, 0x1000006b, 0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021, 0x8ce30000, 0x8ce40004, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 0x1040001e, 0xa821, 0x241e000d, @@ -3813,7 +3835,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0xa3482b, 0x822021, 0x892021, 0x630c0, 0xafa80018, 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 0x54400006, 0x24150001, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffe5, 0x0, 0x32a200ff, 0x54400011, -0xaed3002c, 0x3c040001, 0x24842934, 0xafa00010, 0xafa00014, 0x8f860120, +0xaed3002c, 0x3c040001, 0x24842a64, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0x1000002e, 0x34a5f010, 0x8ec2026c, 0x24150001, 0x24420001, 0xaec2026c, 0x8ec2026c, 0x1000001d, 0x32a200ff, 0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 0x10400015, 0xa821, @@ -3821,12 +3843,12 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0xafb30010, 0xafa20014, 0xafa30018, 0x8ec200a8, 0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe4, 0x0, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffee, 0x0, 0x32a200ff, 0x1440000f, 0x0, 0x3c040001, -0x24842940, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, -0x34a5f011, 0xc0028eb, 0x0, 0x8ec202d0, 0x24420001, 0xaec202d0, +0x24842a70, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, +0x34a5f011, 0xc00290f, 0x0, 0x8ec202d0, 0x24420001, 0xaec202d0, 0x8ec202d0, 0x8ec20220, 0x24420001, 0xaec20220, 0x8ec20220, 0x8ec20258, 0x24420001, 0xaec20258, 0x8ec20258, 0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c, 0x8fb10038, 0x3e00008, 0x27bd0050, 0x0, 0x0, -0x27bdffe8, 0x27644000, 0xafbf0010, 0xc00296c, 0x24051000, 0x24020020, +0x27bdffe8, 0x27644000, 0xafbf0010, 0xc002990, 0x24051000, 0x24020020, 0xaf82011c, 0xaf800100, 0xaf800104, 0xaf800108, 0xaf800110, 0xaf800114, 0xaf800118, 0xaf800120, 0xaf800124, 0xaf800128, 0xaf800130, 0xaf800134, 0xaf800138, 0xaec000dc, 0xaec000e0, 0xaec000e4, 0xaec000e8, 0x3c020001, @@ -3835,173 +3857,179 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x3c026000, 0x1062000b, 0x0, 0x10000010, 0x0, 0x8f420218, 0x30420040, 0x14400009, 0x0, 0x8f820050, 0x3c030010, 0x10000003, 0x431024, 0x8f420218, 0x30420040, 0x10400004, 0x0, 0x8f82011c, -0x34420004, 0xaf82011c, 0x8fbf0010, 0x3e00008, 0x27bd0018, 0x8faa0010, -0x8f83012c, 0x8fab0014, 0x1060000c, 0x8fac0018, 0x8ec20534, 0x8f890128, -0x24680020, 0x51020005, 0x27624800, 0x11280005, 0x24620020, 0x10000009, -0x0, 0x15220007, 0x24620020, 0x8ec30298, 0x1021, 0x24630001, -0xaec30298, 0x1000006b, 0x8ec30298, 0xac640000, 0xac650004, 0xac660008, -0xa467000e, 0xac6a0018, 0xac6b001c, 0xac6c0010, 0x2543ffee, 0x2c630002, -0xaf820120, 0x39420011, 0x2c420001, 0x621825, 0x10600025, 0x0, -0x8ec200e4, 0x210c0, 0x24426fc0, 0x2e22021, 0x8c830000, 0x24020012, -0x1462000f, 0x0, 0x8ec300e4, 0x8ec200e8, 0x1062000b, 0x24030040, -0x8c820004, 0x24420001, 0xac820004, 0x8ec200e8, 0x8ec500e4, 0x24420001, -0x1043002b, 0x0, 0x10000023, 0x0, 0x8ec200e4, 0x24030040, -0x24420001, 0x50430003, 0x1021, 0x8ec200e4, 0x24420001, 0xaec200e4, -0x8ec200e4, 0x210c0, 0x24426fc0, 0x2e22021, 0x10000034, 0x24020012, -0x8ec200e4, 0x210c0, 0x24426fc0, 0x2e22021, 0x8c830000, 0x24020007, -0x1462001f, 0x0, 0x8ec300e4, 0x8ec200e8, 0x1062001b, 0x24030040, -0x8c820004, 0x24420001, 0xac820004, 0x8ec200e8, 0x8ec500e4, 0x24420001, -0x10430007, 0x0, 0x8ec200e8, 0x24420001, 0x10a20005, 0x0, -0x10000007, 0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, -0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, -0x10000012, 0x24020001, 0x8ec200e4, 0x24030040, 0x24420001, 0x50430003, -0x1021, 0x8ec200e4, 0x24420001, 0xaec200e4, 0x8ec200e4, 0x210c0, -0x24426fc0, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, -0x24020001, 0x3e00008, 0x0, 0x3e00008, 0x0, 0x8faa0010, -0x8fab0014, 0x8f880120, 0x8ec20534, 0x8fac0018, 0x25030020, 0x14620002, -0x604821, 0x27694800, 0x8f820128, 0x1122000c, 0x25030016, 0xad040000, -0xad050004, 0xad060008, 0xa507000e, 0xad0a0018, 0xad0b001c, 0xad030014, -0xad0c0010, 0xaf890120, 0x10000006, 0x24020001, 0x8ec30298, 0x1021, -0x24630001, 0xaec30298, 0x8ec30298, 0x3e00008, 0x0, 0x3e00008, -0x0, 0x8faa0010, 0x8f83010c, 0x8fab0014, 0x1060000c, 0x8fac0018, -0x8f890108, 0x24680020, 0x27624800, 0x51020005, 0x27624000, 0x11280005, -0x24620020, 0x10000009, 0x0, 0x15220007, 0x24620020, 0x8ec3029c, -0x1021, 0x24630001, 0xaec3029c, 0x10000052, 0x8ec3029c, 0xac640000, -0xac650004, 0xac660008, 0xa467000e, 0xac6a0018, 0xac6b001c, 0xac6c0010, -0xaf820100, 0x2542fffb, 0x2c420002, 0x10400037, 0x24030040, 0x8ec200dc, -0x210c0, 0x24426dc0, 0x2e22021, 0x8c830000, 0x24020005, 0x1462001f, -0x0, 0x8ec300dc, 0x8ec200e0, 0x1062001b, 0x24030040, 0x8c820004, -0x24420001, 0xac820004, 0x8ec200e0, 0x8ec500dc, 0x24420001, 0x10430007, -0x0, 0x8ec200e0, 0x24420001, 0x10a20005, 0x0, 0x10000007, -0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020, 0xaf820108, -0x8f820108, 0x8c820004, 0x2c420011, 0x50400021, 0xac800000, 0x10000020, -0x24020001, 0x8ec200dc, 0x24030040, 0x24420001, 0x50430003, 0x1021, -0x8ec200dc, 0x24420001, 0xaec200dc, 0x8ec200dc, 0x210c0, 0x24426dc0, -0x2e22021, 0x24020005, 0xac820000, 0x1000000e, 0x24020001, 0x8ec200dc, -0x24420001, 0x50430003, 0x1021, 0x8ec200dc, 0x24420001, 0xaec200dc, -0x8ec200dc, 0x210c0, 0x24426dc0, 0x2e22021, 0x24020001, 0xac8a0000, -0xac820004, 0x24020001, 0x3e00008, 0x0, 0x3e00008, 0x0, -0x8f880100, 0x8fa30010, 0x8faa0014, 0x8fab0018, 0x27624800, 0x25090020, -0x122102b, 0x50400001, 0x27694000, 0x8f820108, 0x1122000d, 0x0, -0xad030018, 0x25030016, 0xad040000, 0xad050004, 0xad060008, 0xa507000e, -0xad0a001c, 0xad030014, 0xad0b0010, 0xaf890100, 0x10000006, 0x24020001, +0x34420004, 0xaf82011c, 0x8fbf0010, 0x3e00008, 0x27bd0018, 0x8fa90010, +0x8f83012c, 0x8faa0014, 0x8fab0018, 0x1060000a, 0x24680020, 0x8ec20534, +0x51020001, 0x27684800, 0x8f820128, 0x11020004, 0x0, 0x8f820124, +0x15020007, 0x39220011, 0x8ec30298, 0x1021, 0x24630001, 0xaec30298, +0x10000069, 0x8ec30298, 0xac640000, 0xac650004, 0xac660008, 0xa467000e, +0xac690018, 0xac6a001c, 0xac6b0010, 0x2523ffee, 0x2c630002, 0x2c420001, +0x621825, 0x10600025, 0xaf880120, 0x8ec200e4, 0x210c0, 0x24426fc0, +0x2e22021, 0x8c830000, 0x24020012, 0x1462000f, 0x0, 0x8ec300e4, +0x8ec200e8, 0x1062000b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, +0x8ec200e8, 0x8ec500e4, 0x24420001, 0x1043002b, 0x0, 0x10000023, +0x0, 0x8ec200e4, 0x24030040, 0x24420001, 0x50430003, 0x1021, +0x8ec200e4, 0x24420001, 0xaec200e4, 0x8ec200e4, 0x210c0, 0x24426fc0, +0x2e22021, 0x10000034, 0x24020012, 0x8ec200e4, 0x210c0, 0x24426fc0, +0x2e22021, 0x8c830000, 0x24020007, 0x1462001f, 0x0, 0x8ec300e4, +0x8ec200e8, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, +0x8ec200e8, 0x8ec500e4, 0x24420001, 0x10430007, 0x0, 0x8ec200e8, +0x24420001, 0x10a20005, 0x0, 0x10000007, 0x0, 0x14a00005, +0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, +0x2c420011, 0x50400013, 0xac800000, 0x10000012, 0x24020001, 0x8ec200e4, +0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ec200e4, 0x24420001, +0xaec200e4, 0x8ec200e4, 0x210c0, 0x24426fc0, 0x2e22021, 0x24020007, +0xac820000, 0x24020001, 0xac820004, 0x24020001, 0x3e00008, 0x0, +0x3e00008, 0x0, 0x8faa0010, 0x8fab0014, 0x8f880120, 0x8ec20534, +0x8fac0018, 0x25030020, 0x14620002, 0x604821, 0x27694800, 0x8f820128, +0x1122000c, 0x25030016, 0xad040000, 0xad050004, 0xad060008, 0xa507000e, +0xad0a0018, 0xad0b001c, 0xad030014, 0xad0c0010, 0xaf890120, 0x10000006, +0x24020001, 0x8ec30298, 0x1021, 0x24630001, 0xaec30298, 0x8ec30298, +0x3e00008, 0x0, 0x3e00008, 0x0, 0x8fa90010, 0x8f83010c, +0x8faa0014, 0x8fab0018, 0x1060000a, 0x24680020, 0x27624800, 0x51020001, +0x27684000, 0x8f820108, 0x11020004, 0x0, 0x8f820104, 0x15020007, +0x2522fffb, 0x8ec3029c, 0x1021, 0x24630001, 0xaec3029c, 0x10000051, +0x8ec3029c, 0x2c420002, 0xac640000, 0xac650004, 0xac660008, 0xa467000e, +0xac690018, 0xac6a001c, 0xac6b0010, 0xaf880100, 0x10400037, 0x24030040, +0x8ec200dc, 0x210c0, 0x24426dc0, 0x2e22021, 0x8c830000, 0x24020005, +0x1462001f, 0x0, 0x8ec300dc, 0x8ec200e0, 0x1062001b, 0x24030040, +0x8c820004, 0x24420001, 0xac820004, 0x8ec200e0, 0x8ec500dc, 0x24420001, +0x10430007, 0x0, 0x8ec200e0, 0x24420001, 0x10a20005, 0x0, +0x10000007, 0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020, +0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, 0x50400021, 0xac800000, +0x10000020, 0x24020001, 0x8ec200dc, 0x24030040, 0x24420001, 0x50430003, +0x1021, 0x8ec200dc, 0x24420001, 0xaec200dc, 0x8ec200dc, 0x210c0, +0x24426dc0, 0x2e22021, 0x24020005, 0xac820000, 0x1000000e, 0x24020001, +0x8ec200dc, 0x24420001, 0x50430003, 0x1021, 0x8ec200dc, 0x24420001, +0xaec200dc, 0x8ec200dc, 0x210c0, 0x24426dc0, 0x2e22021, 0x24020001, +0xac890000, 0xac820004, 0x24020001, 0x3e00008, 0x0, 0x3e00008, +0x0, 0x8fab0010, 0x8f880100, 0x8faa0014, 0x8fac0018, 0x27624800, +0x25030020, 0x14620002, 0x604821, 0x27694000, 0x8f820108, 0x1122000c, +0x25030016, 0xad040000, 0xad050004, 0xad060008, 0xa507000e, 0xad0b0018, +0xad0a001c, 0xad030014, 0xad0c0010, 0xaf890100, 0x10000006, 0x24020001, 0x8ec3029c, 0x1021, 0x24630001, 0xaec3029c, 0x8ec3029c, 0x3e00008, 0x0, 0x3e00008, 0x0, 0x27bdffe0, 0xafbf0018, 0x8f820104, -0xafa20010, 0x8f820100, 0x3c050002, 0xafa20014, 0x8f8600b0, 0x8f87011c, -0x3c040001, 0x24842a2c, 0xc0028eb, 0x34a5f000, 0x8f420218, 0x30420100, +0xafa20010, 0x8f820100, 0x3c040001, 0x24842b5c, 0xafa20014, 0x8f8600b0, +0x8f87011c, 0x3c050002, 0xc00290f, 0x34a5f000, 0x8f420218, 0x30420100, 0x10400017, 0x0, 0x8f8200b0, 0x3c030200, 0x431024, 0x10400012, 0x0, 0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830104, 0x8f8200b0, 0x34420001, 0xaf8200b0, 0xaf830104, 0x8f82011c, 0x2403fffd, 0x431024, -0xaf82011c, 0x8ec20294, 0x24420001, 0xaec20294, 0x10000004, 0x8ec20294, -0x8f8200b0, 0x34420001, 0xaf8200b0, 0x8fbf0018, 0x3e00008, 0x27bd0020, -0x27bdffe0, 0xafbf0018, 0x8f820120, 0xafa20010, 0x8f820124, 0x3c050001, -0xafa20014, 0x8f8600a0, 0x8f87011c, 0x3c040001, 0x24842a38, 0xc0028eb, -0x34a5f000, 0x8f420218, 0x30420100, 0x10400017, 0x0, 0x8f8200a0, -0x3c030200, 0x431024, 0x10400012, 0x0, 0x8f82011c, 0x34420002, -0xaf82011c, 0x8f830124, 0x8f8200a0, 0x34420001, 0xaf8200a0, 0xaf830124, -0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ec20290, 0x24420001, -0xaec20290, 0x10000004, 0x8ec20290, 0x8f8200a0, 0x34420001, 0xaf8200a0, -0x8fbf0018, 0x3e00008, 0x27bd0020, 0x6021, 0x5021, 0x3021, -0x2821, 0x6821, 0x4821, 0x7821, 0x7021, 0x8f880124, -0x8f870104, 0x1580002e, 0x8f8b011c, 0x11a00014, 0x31620800, 0x8f820120, -0x10460029, 0x0, 0x3c040001, 0x8c843390, 0x8cc20000, 0x8cc30004, -0xac820000, 0xac830004, 0x8cc20008, 0xac820008, 0x94c2000e, 0xa482000e, -0x8cc20010, 0x240c0001, 0xac820010, 0x8cc20014, 0x10000012, 0x24c60020, -0x10400017, 0x0, 0x3c040001, 0x8c843390, 0x8d020000, 0x8d030004, -0xac820000, 0xac830004, 0x8d020008, 0xac820008, 0x9502000e, 0xa482000e, -0x8d020010, 0x25060020, 0xac820010, 0x8d020014, 0x240c0001, 0xc01821, -0xac820014, 0x27624fe0, 0x43102b, 0x54400001, 0x27634800, 0x603021, -0x1540002f, 0x31620100, 0x11200014, 0x31628000, 0x8f820100, 0x1045002a, -0x31620100, 0x3c040001, 0x8c84338c, 0x8ca20000, 0x8ca30004, 0xac820000, -0xac830004, 0x8ca20008, 0xac820008, 0x94a2000e, 0xa482000e, 0x8ca20010, -0x240a0001, 0xac820010, 0x8ca20014, 0x10000012, 0x24a50020, 0x10400018, -0x31620100, 0x3c040001, 0x8c84338c, 0x8ce20000, 0x8ce30004, 0xac820000, -0xac830004, 0x8ce20008, 0xac820008, 0x94e2000e, 0xa482000e, 0x8ce20010, -0x24e50020, 0xac820010, 0x8ce20014, 0x240a0001, 0xa01821, 0xac820014, -0x276247e0, 0x43102b, 0x54400001, 0x27634000, 0x602821, 0x31620100, -0x5440001d, 0x31621000, 0x11a00009, 0x31a20800, 0x10400004, 0x25020020, -0x8f8200a8, 0xa5e20000, 0x25020020, 0xaf820124, 0x8f880124, 0x6821, -0x11800011, 0x31621000, 0x3c040001, 0x8c843390, 0x8c820000, 0x8c830004, -0xaf820080, 0xaf830084, 0x8c820008, 0xaf8200a4, 0x9482000e, 0xaf8200ac, -0x8c820010, 0x6021, 0xaf8200a0, 0x8c8d0010, 0x8c8f0014, 0x31621000, -0x1440ff82, 0x0, 0x1120000f, 0x31220800, 0x10400004, 0x3c020002, -0x8f8200b8, 0xa5c20000, 0x3c020002, 0x1221024, 0x10400004, 0x24e20020, -0x8f8200b4, 0xaf8200d4, 0x24e20020, 0xaf820104, 0x8f870104, 0x4821, -0x1140ff70, 0x0, 0x3c040001, 0x8c84338c, 0x8c820000, 0x8c830004, -0xaf820090, 0xaf830094, 0x8c820008, 0xaf8200b4, 0x9482000e, 0xaf82009c, -0x8c820010, 0x5021, 0xaf8200b0, 0x8c890010, 0x1000ff60, 0x8c8e0014, -0x3e00008, 0x0, 0x6021, 0x5821, 0x3021, 0x2821, -0x6821, 0x5021, 0x7821, 0x7021, 0x8f880124, 0x8f870104, -0x3c180100, 0x1580002e, 0x8f89011c, 0x11a00014, 0x31220800, 0x8f820120, -0x10460029, 0x0, 0x3c040001, 0x8c843390, 0x8cc20000, 0x8cc30004, -0xac820000, 0xac830004, 0x8cc20008, 0xac820008, 0x94c2000e, 0xa482000e, -0x8cc20010, 0x240c0001, 0xac820010, 0x8cc20014, 0x10000012, 0x24c60020, -0x10400017, 0x0, 0x3c040001, 0x8c843390, 0x8d020000, 0x8d030004, -0xac820000, 0xac830004, 0x8d020008, 0xac820008, 0x9502000e, 0xa482000e, -0x8d020010, 0x25060020, 0xac820010, 0x8d020014, 0x240c0001, 0xc01821, -0xac820014, 0x27624fe0, 0x43102b, 0x54400001, 0x27634800, 0x603021, -0x1560002f, 0x31220100, 0x11400014, 0x31228000, 0x8f820100, 0x1045002a, -0x31220100, 0x3c040001, 0x8c84338c, 0x8ca20000, 0x8ca30004, 0xac820000, -0xac830004, 0x8ca20008, 0xac820008, 0x94a2000e, 0xa482000e, 0x8ca20010, -0x240b0001, 0xac820010, 0x8ca20014, 0x10000012, 0x24a50020, 0x10400018, -0x31220100, 0x3c040001, 0x8c84338c, 0x8ce20000, 0x8ce30004, 0xac820000, -0xac830004, 0x8ce20008, 0xac820008, 0x94e2000e, 0xa482000e, 0x8ce20010, -0x24e50020, 0xac820010, 0x8ce20014, 0x240b0001, 0xa01821, 0xac820014, -0x276247e0, 0x43102b, 0x54400001, 0x27634000, 0x602821, 0x31220100, -0x5440001d, 0x31221000, 0x11a00009, 0x31a20800, 0x10400004, 0x25020020, -0x8f8200a8, 0xa5e20000, 0x25020020, 0xaf820124, 0x8f880124, 0x6821, -0x11800011, 0x31221000, 0x3c040001, 0x8c843390, 0x8c820000, 0x8c830004, -0xaf820080, 0xaf830084, 0x8c820008, 0xaf8200a4, 0x9482000e, 0xaf8200ac, -0x8c820010, 0x6021, 0xaf8200a0, 0x8c8d0010, 0x8c8f0014, 0x31221000, -0x14400022, 0x0, 0x1140000f, 0x31420800, 0x10400004, 0x3c020002, -0x8f8200b8, 0xa5c20000, 0x3c020002, 0x1421024, 0x10400004, 0x24e20020, -0x8f8200b4, 0xaf8200d4, 0x24e20020, 0xaf820104, 0x8f870104, 0x5021, -0x11600010, 0x0, 0x3c040001, 0x8c84338c, 0x8c820000, 0x8c830004, -0xaf820090, 0xaf830094, 0x8c820008, 0xaf8200b4, 0x9482000e, 0xaf82009c, -0x8c820010, 0x5821, 0xaf8200b0, 0x8c8a0010, 0x8c8e0014, 0x8f820070, -0x3c031000, 0x431024, 0x1040ff5c, 0x0, 0x8f820054, 0x24420005, -0xaf820078, 0x8f420234, 0x10400017, 0x2021, 0x3c020001, 0x571021, -0x8c4281dc, 0x24420005, 0x3c010001, 0x370821, 0xac2281dc, 0x3c020001, -0x571021, 0x8c4281dc, 0x8f430234, 0x43102b, 0x14400009, 0x24020001, -0x3c040080, 0x3c010001, 0x370821, 0xac2281d4, 0x3c010001, 0x370821, -0x1000000c, 0xac2081dc, 0x3c020001, 0x571021, 0x8c4281d4, 0x14400006, -0x3c020080, 0x3c020001, 0x571021, 0x8c4281d8, 0x10400002, 0x3c020080, -0x822025, 0x8f420230, 0x10400014, 0x0, 0x3c020001, 0x571021, -0x8c4281e4, 0x24420005, 0x3c010001, 0x370821, 0xac2281e4, 0x3c020001, -0x571021, 0x8c4281e4, 0x8f430230, 0x43102b, 0x14400006, 0x0, -0x3c010001, 0x370821, 0xac2081e4, 0x10000006, 0x982025, 0x3c020001, -0x571021, 0x8c4281e0, 0x54400001, 0x982025, 0x3c020001, 0x571021, -0x8c4281e8, 0x10400005, 0x3c022000, 0x822025, 0x3c010001, 0x370821, -0xac2081e8, 0x1080ff0f, 0x0, 0x8ec20000, 0x10400007, 0x0, -0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 0x0, -0xaf800048, 0x8f820048, 0x1040fffd, 0x0, 0x8f820060, 0x441025, -0xaf820060, 0x8ec20000, 0x10400003, 0x0, 0x1000fefa, 0xaf80004c, -0x1000fef8, 0xaf800048, 0x3e00008, 0x0, 0x3c020001, 0x8c423228, -0x27bdffe8, 0xafbf0014, 0x14400012, 0xafb10010, 0x3c110001, 0x26313430, -0x2202021, 0xc00296c, 0x24052000, 0x26221fe0, 0x3c010001, 0xac223398, -0x3c010001, 0xac223394, 0xaf420250, 0x24022000, 0xaf510254, 0xaf420258, -0x24020001, 0x3c010001, 0xac223228, 0x8fbf0014, 0x8fb10010, 0x3e00008, -0x27bd0018, 0x3c030001, 0x8c633398, 0x8c820000, 0x8fa80010, 0x8fa90014, -0xac620000, 0x3c020001, 0x8c423398, 0x8c830004, 0xac430004, 0xac450008, +0xaf82011c, 0x8ec20294, 0x24420001, 0xaec20294, 0x10000018, 0x8ec20294, +0x3c040001, 0x24842b68, 0x3405dead, 0x3021, 0x3c070001, 0x24e72b70, +0x24020287, 0xafa20010, 0xc00290f, 0xafa00014, 0x8f82011c, 0x34420002, +0xaf82011c, 0x8f820220, 0x34420004, 0xaf820220, 0x8f820140, 0x3c030001, +0x431025, 0xaf820140, 0x8f8200b0, 0x34420001, 0xaf8200b0, 0x8fbf0018, +0x3e00008, 0x27bd0020, 0x27bdffe0, 0xafbf0018, 0x8f820120, 0xafa20010, +0x8f820124, 0x3c040001, 0x24842b98, 0xafa20014, 0x8f8600a0, 0x8f87011c, +0x3c050001, 0xc00290f, 0x34a5f000, 0x8f420218, 0x30420100, 0x10400017, +0x0, 0x8f8200a0, 0x3c030200, 0x431024, 0x10400012, 0x0, +0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830124, 0x8f8200a0, 0x34420001, +0xaf8200a0, 0xaf830124, 0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, +0x8ec20290, 0x24420001, 0xaec20290, 0x10000018, 0x8ec20290, 0x3c040001, +0x24842b68, 0x3405dead, 0x3021, 0x3c070001, 0x24e72b70, 0x240202a3, +0xafa20010, 0xc00290f, 0xafa00014, 0x8f82011c, 0x34420002, 0xaf82011c, +0x8f820220, 0x34420004, 0xaf820220, 0x8f820140, 0x3c030001, 0x431025, +0xaf820140, 0x8f8200a0, 0x34420001, 0xaf8200a0, 0x8fbf0018, 0x3e00008, +0x27bd0020, 0x6021, 0x5021, 0x3021, 0x2821, 0x6821, +0x4821, 0x7821, 0x7021, 0x8f880124, 0x8f870104, 0x1580002e, +0x8f8b011c, 0x11a00014, 0x31620800, 0x8f820120, 0x10460029, 0x0, +0x3c040001, 0x8c8434f0, 0x8cc20000, 0x8cc30004, 0xac820000, 0xac830004, +0x8cc20008, 0xac820008, 0x94c2000e, 0xa482000e, 0x8cc20010, 0x240c0001, +0xac820010, 0x8cc20014, 0x10000012, 0x24c60020, 0x10400017, 0x0, +0x3c040001, 0x8c8434f0, 0x8d020000, 0x8d030004, 0xac820000, 0xac830004, +0x8d020008, 0xac820008, 0x9502000e, 0xa482000e, 0x8d020010, 0x25060020, +0xac820010, 0x8d020014, 0x240c0001, 0xc01821, 0xac820014, 0x27624fe0, +0x43102b, 0x54400001, 0x27634800, 0x603021, 0x1540002f, 0x31620100, +0x11200014, 0x31628000, 0x8f820100, 0x1045002a, 0x31620100, 0x3c040001, +0x8c8434ec, 0x8ca20000, 0x8ca30004, 0xac820000, 0xac830004, 0x8ca20008, +0xac820008, 0x94a2000e, 0xa482000e, 0x8ca20010, 0x240a0001, 0xac820010, +0x8ca20014, 0x10000012, 0x24a50020, 0x10400018, 0x31620100, 0x3c040001, +0x8c8434ec, 0x8ce20000, 0x8ce30004, 0xac820000, 0xac830004, 0x8ce20008, +0xac820008, 0x94e2000e, 0xa482000e, 0x8ce20010, 0x24e50020, 0xac820010, +0x8ce20014, 0x240a0001, 0xa01821, 0xac820014, 0x276247e0, 0x43102b, +0x54400001, 0x27634000, 0x602821, 0x31620100, 0x5440001d, 0x31621000, +0x11a00009, 0x31a20800, 0x10400004, 0x25020020, 0x8f8200a8, 0xa5e20000, +0x25020020, 0xaf820124, 0x8f880124, 0x6821, 0x11800011, 0x31621000, +0x3c040001, 0x8c8434f0, 0x8c820000, 0x8c830004, 0xaf820080, 0xaf830084, +0x8c820008, 0xaf8200a4, 0x9482000e, 0xaf8200ac, 0x8c820010, 0x6021, +0xaf8200a0, 0x8c8d0010, 0x8c8f0014, 0x31621000, 0x1440ff82, 0x0, +0x1120000f, 0x31220800, 0x10400004, 0x3c020002, 0x8f8200b8, 0xa5c20000, +0x3c020002, 0x1221024, 0x10400004, 0x24e20020, 0x8f8200b4, 0xaf8200d4, +0x24e20020, 0xaf820104, 0x8f870104, 0x4821, 0x1140ff70, 0x0, +0x3c040001, 0x8c8434ec, 0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094, +0x8c820008, 0xaf8200b4, 0x9482000e, 0xaf82009c, 0x8c820010, 0x5021, +0xaf8200b0, 0x8c890010, 0x1000ff60, 0x8c8e0014, 0x3e00008, 0x0, +0x6021, 0x5821, 0x3021, 0x2821, 0x6821, 0x5021, +0x7821, 0x7021, 0x8f880124, 0x8f870104, 0x3c180100, 0x1580002e, +0x8f89011c, 0x11a00014, 0x31220800, 0x8f820120, 0x10460029, 0x0, +0x3c040001, 0x8c8434f0, 0x8cc20000, 0x8cc30004, 0xac820000, 0xac830004, +0x8cc20008, 0xac820008, 0x94c2000e, 0xa482000e, 0x8cc20010, 0x240c0001, +0xac820010, 0x8cc20014, 0x10000012, 0x24c60020, 0x10400017, 0x0, +0x3c040001, 0x8c8434f0, 0x8d020000, 0x8d030004, 0xac820000, 0xac830004, +0x8d020008, 0xac820008, 0x9502000e, 0xa482000e, 0x8d020010, 0x25060020, +0xac820010, 0x8d020014, 0x240c0001, 0xc01821, 0xac820014, 0x27624fe0, +0x43102b, 0x54400001, 0x27634800, 0x603021, 0x1560002f, 0x31220100, +0x11400014, 0x31228000, 0x8f820100, 0x1045002a, 0x31220100, 0x3c040001, +0x8c8434ec, 0x8ca20000, 0x8ca30004, 0xac820000, 0xac830004, 0x8ca20008, +0xac820008, 0x94a2000e, 0xa482000e, 0x8ca20010, 0x240b0001, 0xac820010, +0x8ca20014, 0x10000012, 0x24a50020, 0x10400018, 0x31220100, 0x3c040001, +0x8c8434ec, 0x8ce20000, 0x8ce30004, 0xac820000, 0xac830004, 0x8ce20008, +0xac820008, 0x94e2000e, 0xa482000e, 0x8ce20010, 0x24e50020, 0xac820010, +0x8ce20014, 0x240b0001, 0xa01821, 0xac820014, 0x276247e0, 0x43102b, +0x54400001, 0x27634000, 0x602821, 0x31220100, 0x5440001d, 0x31221000, +0x11a00009, 0x31a20800, 0x10400004, 0x25020020, 0x8f8200a8, 0xa5e20000, +0x25020020, 0xaf820124, 0x8f880124, 0x6821, 0x11800011, 0x31221000, +0x3c040001, 0x8c8434f0, 0x8c820000, 0x8c830004, 0xaf820080, 0xaf830084, +0x8c820008, 0xaf8200a4, 0x9482000e, 0xaf8200ac, 0x8c820010, 0x6021, +0xaf8200a0, 0x8c8d0010, 0x8c8f0014, 0x31221000, 0x14400022, 0x0, +0x1140000f, 0x31420800, 0x10400004, 0x3c020002, 0x8f8200b8, 0xa5c20000, +0x3c020002, 0x1421024, 0x10400004, 0x24e20020, 0x8f8200b4, 0xaf8200d4, +0x24e20020, 0xaf820104, 0x8f870104, 0x5021, 0x11600010, 0x0, +0x3c040001, 0x8c8434ec, 0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094, +0x8c820008, 0xaf8200b4, 0x9482000e, 0xaf82009c, 0x8c820010, 0x5821, +0xaf8200b0, 0x8c8a0010, 0x8c8e0014, 0x8f820070, 0x3c031000, 0x431024, +0x1040ff5c, 0x0, 0x8f820054, 0x24420005, 0xaf820078, 0x8f420234, +0x10400017, 0x2021, 0x3c020001, 0x571021, 0x8c4281dc, 0x24420005, +0x3c010001, 0x370821, 0xac2281dc, 0x3c020001, 0x571021, 0x8c4281dc, +0x8f430234, 0x43102b, 0x14400009, 0x24020001, 0x3c040080, 0x3c010001, +0x370821, 0xac2281d4, 0x3c010001, 0x370821, 0x1000000c, 0xac2081dc, +0x3c020001, 0x571021, 0x8c4281d4, 0x14400006, 0x3c020080, 0x3c020001, +0x571021, 0x8c4281d8, 0x10400002, 0x3c020080, 0x822025, 0x8f420230, +0x10400014, 0x0, 0x3c020001, 0x571021, 0x8c4281e4, 0x24420005, +0x3c010001, 0x370821, 0xac2281e4, 0x3c020001, 0x571021, 0x8c4281e4, +0x8f430230, 0x43102b, 0x14400006, 0x0, 0x3c010001, 0x370821, +0xac2081e4, 0x10000006, 0x982025, 0x3c020001, 0x571021, 0x8c4281e0, +0x54400001, 0x982025, 0x3c020001, 0x571021, 0x8c4281e8, 0x10400005, +0x3c022000, 0x822025, 0x3c010001, 0x370821, 0xac2081e8, 0x1080ff0f, +0x0, 0x8ec20000, 0x10400007, 0x0, 0xaf80004c, 0x8f82004c, +0x1040fffd, 0x0, 0x10000005, 0x0, 0xaf800048, 0x8f820048, +0x1040fffd, 0x0, 0x8f820060, 0x441025, 0xaf820060, 0x8ec20000, +0x10400003, 0x0, 0x1000fefa, 0xaf80004c, 0x1000fef8, 0xaf800048, +0x3e00008, 0x0, 0x0, 0x0, 0x3c020001, 0x8c423388, +0x27bdffe8, 0xafbf0014, 0x14400012, 0xafb10010, 0x3c110001, 0x26313590, +0x2202021, 0xc002990, 0x24052000, 0x26221fe0, 0x3c010001, 0xac2234f8, +0x3c010001, 0xac2234f4, 0xaf420250, 0x24022000, 0xaf510254, 0xaf420258, +0x24020001, 0x3c010001, 0xac223388, 0x8fbf0014, 0x8fb10010, 0x3e00008, +0x27bd0018, 0x3c030001, 0x8c6334f8, 0x8c820000, 0x8fa80010, 0x8fa90014, +0xac620000, 0x3c020001, 0x8c4234f8, 0x8c830004, 0xac430004, 0xac450008, 0x8f840054, 0x2443ffe0, 0xac460010, 0xac470014, 0xac480018, 0xac49001c, -0x3c010001, 0xac233398, 0xac44000c, 0x3c020001, 0x24423430, 0x62182b, -0x10600005, 0x0, 0x3c020001, 0x8c423394, 0x3c010001, 0xac223398, -0x3c030001, 0x8c633398, 0x3c020001, 0x8c423210, 0xac620000, 0x3c030001, -0x8c633398, 0x3c020001, 0x8c423210, 0xac620004, 0x3e00008, 0xaf430250, -0x27bdffd8, 0xafb10010, 0x808821, 0x3c030001, 0x8c633398, 0x3c020001, -0x8c423210, 0x8fa40040, 0xafb30014, 0xa09821, 0xafbf0020, 0xafbe001c, -0xafb50018, 0xac620000, 0x3c050001, 0x8ca53398, 0x3c020001, 0x8c423210, -0xc0a821, 0xe0f021, 0x10800006, 0xaca20004, 0x24a50008, 0xc002974, -0x24060018, 0x10000004, 0x0, 0x24a40008, 0xc00296c, 0x24050018, -0x3c020001, 0x8c423398, 0x3c050001, 0x24a53430, 0x2442ffe0, 0x3c010001, -0xac223398, 0x45102b, 0x10400005, 0x0, 0x3c020001, 0x8c423394, -0x3c010001, 0xac223398, 0x3c030001, 0x8c633398, 0x8e220000, 0xac620000, -0x3c030001, 0x8c633398, 0x8e220004, 0xac620004, 0xac730008, 0x8f840054, +0x3c010001, 0xac2334f8, 0xac44000c, 0x3c020001, 0x24423590, 0x62182b, +0x10600005, 0x0, 0x3c020001, 0x8c4234f4, 0x3c010001, 0xac2234f8, +0x3c030001, 0x8c6334f8, 0x3c020001, 0x8c423370, 0xac620000, 0x3c030001, +0x8c6334f8, 0x3c020001, 0x8c423370, 0xac620004, 0x3e00008, 0xaf430250, +0x27bdffd8, 0xafb10010, 0x808821, 0x3c030001, 0x8c6334f8, 0x3c020001, +0x8c423370, 0x8fa40040, 0xafb30014, 0xa09821, 0xafbf0020, 0xafbe001c, +0xafb50018, 0xac620000, 0x3c050001, 0x8ca534f8, 0x3c020001, 0x8c423370, +0xc0a821, 0xe0f021, 0x10800006, 0xaca20004, 0x24a50008, 0xc002998, +0x24060018, 0x10000004, 0x0, 0x24a40008, 0xc002990, 0x24050018, +0x3c020001, 0x8c4234f8, 0x3c050001, 0x24a53590, 0x2442ffe0, 0x3c010001, +0xac2234f8, 0x45102b, 0x10400005, 0x0, 0x3c020001, 0x8c4234f4, +0x3c010001, 0xac2234f8, 0x3c030001, 0x8c6334f8, 0x8e220000, 0xac620000, +0x3c030001, 0x8c6334f8, 0x8e220004, 0xac620004, 0xac730008, 0x8f840054, 0xac750010, 0xac7e0014, 0x8fa80038, 0xac680018, 0x8fa8003c, 0x2462ffe0, -0x3c010001, 0xac223398, 0x45102b, 0xac68001c, 0x10400005, 0xac64000c, -0x3c020001, 0x8c423394, 0x3c010001, 0xac223398, 0x3c030001, 0x8c633398, -0x3c020001, 0x8c423210, 0xac620000, 0x3c030001, 0x8c633398, 0x3c020001, -0x8c423210, 0xac620004, 0xaf430250, 0x8fbf0020, 0x8fbe001c, 0x8fb50018, +0x3c010001, 0xac2234f8, 0x45102b, 0xac68001c, 0x10400005, 0xac64000c, +0x3c020001, 0x8c4234f4, 0x3c010001, 0xac2234f8, 0x3c030001, 0x8c6334f8, +0x3c020001, 0x8c423370, 0xac620000, 0x3c030001, 0x8c6334f8, 0x3c020001, +0x8c423370, 0xac620004, 0xaf430250, 0x8fbf0020, 0x8fbe001c, 0x8fb50018, 0x8fb30014, 0x8fb10010, 0x3e00008, 0x27bd0028, 0x10a00005, 0x0, 0xac800000, 0x24a5fffc, 0x14a0fffd, 0x24840004, 0x3e00008, 0x0, 0x10c00007, 0x0, 0x8c820000, 0x24840004, 0x24c6fffc, 0xaca20000, @@ -4025,7 +4053,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x24020017, 0x24020006, 0xafa20010, 0x8ec2001c, 0xafa20014, 0x8ec2000c, 0x8fa40028, 0x8fa5002c, 0x3c030002, 0x431025, 0xafa20018, 0x8ec60080, 0x8ec200a4, 0x40f809, 0x0, 0x5440000b, 0x3225ffff, 0x8fa9002c, -0xafa90010, 0x8ec20080, 0x3c040001, 0x24842cfc, 0x3c050004, 0xafa20014, +0xafa90010, 0x8ec20080, 0x3c040001, 0x24842e5c, 0x3c050004, 0xafa20014, 0x8ec6001c, 0x100000a5, 0x34a5f004, 0x8ec20078, 0x451021, 0xaec20078, 0x8ec2001c, 0x8ee304bc, 0x8ec40074, 0x21100, 0x431021, 0xac44000c, 0x8ec30074, 0xafa30020, 0x8ec40078, 0xafa40024, 0x8ec2052c, 0x10400006, @@ -4037,8 +4065,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x0, 0x8ec202a8, 0x1821, 0x24420001, 0xaec202a8, 0x10000008, 0x8ec202a8, 0x8fa20020, 0x8fa30024, 0xacc20000, 0xacc30004, 0x24c20008, 0xaf8200f0, 0x24030001, 0x14600012, 0x131142, 0x8f8200f0, 0xafa20010, -0x8f8200f4, 0x3c040001, 0x24842d08, 0xafa20014, 0x8fa60020, 0x8fa70024, -0x3c050004, 0xc0028eb, 0x34a5f005, 0x8ec20180, 0x24420001, 0xaec20180, +0x8f8200f4, 0x3c040001, 0x24842e68, 0xafa20014, 0x8fa60020, 0x8fa70024, +0x3c050004, 0xc00290f, 0x34a5f005, 0x8ec20180, 0x24420001, 0xaec20180, 0x8ec20180, 0x10000039, 0x24020001, 0x30430003, 0x24020002, 0x10620016, 0x28620003, 0x10400005, 0x24020001, 0x10620008, 0x0, 0x10000023, 0x0, 0x24020003, 0x10620017, 0x0, 0x1000001e, 0x0, @@ -4052,8 +4080,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x1000002f, 0xa2c20529, 0x3227ffff, 0x10e0002c, 0x0, 0x14400002, 0x24020016, 0x24020005, 0xafa20010, 0x8ec2001c, 0x8fa40028, 0x8fa5002c, 0xafa20014, 0x8ec2000c, 0xafa20018, 0x8ec60080, 0x8ec200a4, 0x40f809, -0x0, 0x1440000d, 0x3225ffff, 0x3c040001, 0x24842d14, 0x8fa8002c, -0x3c050004, 0xafa00014, 0xafa80010, 0x8ec6001c, 0x34a5f007, 0xc0028eb, +0x0, 0x1440000d, 0x3225ffff, 0x3c040001, 0x24842e74, 0x8fa8002c, +0x3c050004, 0xafa00014, 0xafa80010, 0x8ec6001c, 0x34a5f007, 0xc00290f, 0x2203821, 0x10000030, 0x0, 0x8ec20080, 0x8ec40538, 0x451021, 0xaec20080, 0x8ec20078, 0x8ec30080, 0x451021, 0x64182b, 0x14600005, 0xaec20078, 0x8ec20080, 0x8ec3053c, 0x431023, 0xaec20080, 0xa2c00529, @@ -4086,7 +4114,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0xafa20010, 0x8ec2001c, 0x8fa40020, 0x8fa50024, 0x3c030002, 0xc31825, 0xafa30018, 0xafa20014, 0x8ec60080, 0x8ec200a4, 0x40f809, 0x0, 0x1440000b, 0x24030001, 0x8fab0024, 0xafab0010, 0x8ec20080, 0x3c040001, -0x24842cfc, 0x3c050004, 0xafa20014, 0x8ec60018, 0x10000037, 0x34a5f004, +0x24842e5c, 0x3c050004, 0xafa20014, 0x8ec60018, 0x10000037, 0x34a5f004, 0x8ec40070, 0x8ec20080, 0x8ec50538, 0x2406fff8, 0xa2c30021, 0xaec0052c, 0xaec00530, 0x24840001, 0xaec40070, 0x3224ffff, 0x441021, 0x24420007, 0x461024, 0x24840007, 0xaec20074, 0x8ec20088, 0x8ec30074, 0x862024, @@ -4094,9 +4122,9 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x431023, 0xaec20074, 0x8ec20074, 0x1000002d, 0xaec20080, 0x10e0002b, 0x0, 0x15000002, 0x24020016, 0x24020005, 0xafa20010, 0x8ec2001c, 0x8fa40020, 0x8fa50024, 0xafa60018, 0xafa20014, 0x8ec60080, 0x8ec200a4, -0x40f809, 0x0, 0x1440000d, 0x3225ffff, 0x3c040001, 0x24842d14, +0x40f809, 0x0, 0x1440000d, 0x3225ffff, 0x3c040001, 0x24842e74, 0x8faa0024, 0x3c050004, 0xafa00014, 0xafaa0010, 0x8ec60018, 0x34a5f007, -0xc0028eb, 0x2203821, 0x10000030, 0x0, 0x8ec20080, 0x8ec40538, +0xc00290f, 0x2203821, 0x10000030, 0x0, 0x8ec20080, 0x8ec40538, 0x451021, 0xaec20080, 0x8ec20088, 0x8ec30080, 0xa2c00021, 0x451023, 0x64182b, 0x14600005, 0xaec20088, 0x8ec20080, 0x8ec3053c, 0x431023, 0xaec20080, 0x8ec3001c, 0x96e20450, 0x24630001, 0x2442ffff, 0x621824, @@ -4119,26 +4147,26 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x0, 0x96e20452, 0x8ed10018, 0x30420020, 0x1040001e, 0x24070008, 0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020019, 0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, -0x24020001, 0x3c040001, 0x24842ca0, 0xafb10010, 0xafa00014, 0x8ec6002c, -0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f006, 0x1021, 0x1040004a, +0x24020001, 0x3c040001, 0x24842e00, 0xafb10010, 0xafa00014, 0x8ec6002c, +0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f006, 0x1021, 0x1040004a, 0x24020001, 0x3c010001, 0x370821, 0x1000006f, 0xac2281d0, 0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020012, 0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, 0x24020001, -0x3c040001, 0x24842ca0, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, -0x3c050009, 0xc0028eb, 0x34a5f006, 0x1021, 0x1040004f, 0x24020001, +0x3c040001, 0x24842e00, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, +0x3c050009, 0xc00290f, 0x34a5f006, 0x1021, 0x1040004f, 0x24020001, 0x10000051, 0x0, 0x2c420002, 0x10400062, 0x24a2fffe, 0x8cc2001c, 0x96e30450, 0x8ec40024, 0x24420001, 0x2463ffff, 0x431024, 0x872021, 0xaec20018, 0xaec40024, 0x96e20452, 0x8ed10018, 0x30420020, 0x10400023, 0x24070008, 0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020019, 0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, -0x1440000b, 0x24020001, 0x3c040001, 0x24842ca0, 0xafb10010, 0xafa00014, -0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f006, 0x1021, +0x1440000b, 0x24020001, 0x3c040001, 0x24842e00, 0xafb10010, 0xafa00014, +0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f006, 0x1021, 0x14400006, 0x24020001, 0x24020001, 0x3c010001, 0x370821, 0x10000031, 0xac2281d8, 0x3c010001, 0x370821, 0x10000021, 0xac2281d0, 0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020012, 0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, 0x24020001, -0x3c040001, 0x24842ca0, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, -0x3c050009, 0xc0028eb, 0x34a5f006, 0x1021, 0x14400005, 0x24020001, +0x3c040001, 0x24842e00, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, +0x3c050009, 0xc00290f, 0x34a5f006, 0x1021, 0x14400005, 0x24020001, 0x3c010001, 0x370821, 0x10000010, 0xac2281d4, 0x3c010001, 0x370821, 0xac2081d0, 0x3c010001, 0x370821, 0xac2081d8, 0x3c010001, 0x370821, 0xac2081d4, 0x8ec20264, 0xaec00024, 0xaed10028, 0x24420001, 0xaec20264, @@ -4150,12 +4178,12 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x8ec202c4, 0x641821, 0x306300ff, 0x10000009, 0xaec3005c, 0x8ec202bc, 0x8ec3003c, 0x441021, 0xaec202bc, 0x8ec202c4, 0x641821, 0x306301ff, 0xaec3003c, 0x441021, 0xaec202c4, 0x10000022, 0x36940040, 0x24020014, -0x14a20014, 0x24020010, 0x3c020001, 0x8c4231d4, 0x1040000a, 0x26e50028, +0x14a20014, 0x24020010, 0x3c020001, 0x8c423334, 0x1040000a, 0x26e50028, 0x26c40128, 0x240300ff, 0x2406ffff, 0x8ca20000, 0x24a50004, 0x2463ffff, 0xac820000, 0x1466fffb, 0x24840004, 0x8ec20240, 0xa2c00528, 0x24420001, 0xaec20240, 0x1000000c, 0x8ec20240, 0x10a2000a, 0x3c050008, 0x94c7000e, -0x8cc2001c, 0x3c040001, 0x24842d20, 0xafa60014, 0xafa20010, 0x8cc60018, -0xc0028eb, 0x34a50910, 0x8fbf0024, 0x8fb10020, 0x3e00008, 0x27bd0028, +0x8cc2001c, 0x3c040001, 0x24842e80, 0xafa60014, 0xafa20010, 0x8cc60018, +0xc00290f, 0x34a50910, 0x8fbf0024, 0x8fb10020, 0x3e00008, 0x27bd0028, 0x3e00008, 0x0, 0x27bdff80, 0xafbf0078, 0xafbe0074, 0xafb50070, 0xafb3006c, 0xafb10068, 0x8f820104, 0x8f950108, 0xafa00034, 0x12a2039b, 0xafa0003c, 0x8f820108, 0x24420020, 0xaf820108, 0x8ead0018, 0xafad0044, @@ -4185,8 +4213,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0xaecd0094, 0x8ec3009c, 0x8ec20538, 0x24650017, 0xa2102b, 0x14400003, 0x0, 0x8ec2053c, 0xa22823, 0x90a50000, 0xa3a5005f, 0x93a6005f, 0x38c30006, 0x3182b, 0x38c20011, 0x2102b, 0x621824, 0x1060000c, -0x3c050008, 0x8fad0054, 0xafad0010, 0x8ec2009c, 0x3c040001, 0x24842d2c, -0xafa20014, 0x8ec70094, 0xc0028eb, 0x34a5f055, 0x100000d7, 0x0, +0x3c050008, 0x8fad0054, 0xafad0010, 0x8ec2009c, 0x3c040001, 0x24842e8c, +0xafa20014, 0x8ec70094, 0xc00290f, 0x34a5f055, 0x100000d7, 0x0, 0x96e20452, 0x30420008, 0x1040000c, 0x2625000e, 0x8ec20538, 0xa2102b, 0x14400003, 0xf021, 0x8ec2053c, 0xa22823, 0x90a20000, 0x3042000f, 0x21080, 0x10000068, 0xafa20028, 0x8ec20094, 0x8fad0054, 0x11a20013, @@ -4264,13 +4292,13 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x2c420002, 0x1040012f, 0x0, 0x96e20452, 0x8ed10018, 0x30420020, 0x1040001e, 0x24070008, 0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020019, 0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, -0x24c6001c, 0x1440000b, 0x24020001, 0x3c040001, 0x24842ca0, 0xafb10010, -0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f006, +0x24c6001c, 0x1440000b, 0x24020001, 0x3c040001, 0x24842e00, 0xafb10010, +0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f006, 0x1021, 0x1040008f, 0x24020001, 0x3c010001, 0x370821, 0x100000b4, 0xac2281d0, 0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020012, 0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, -0x1440000b, 0x24020001, 0x3c040001, 0x24842ca0, 0xafb10010, 0xafa00014, -0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f006, 0x1021, +0x1440000b, 0x24020001, 0x3c040001, 0x24842e00, 0xafb10010, 0xafa00014, +0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f006, 0x1021, 0x10400094, 0x24020001, 0x10000096, 0x0, 0x15a20043, 0x24020016, 0x96a3000e, 0x8ec20078, 0x8ec40024, 0x431021, 0xaec20078, 0x8ea3001c, 0x96e20450, 0x24840001, 0xaec40024, 0x24630001, 0x2442ffff, 0x621824, @@ -4278,8 +4306,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x8ed10018, 0x30420020, 0x1040001e, 0x24070008, 0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020019, 0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, 0x24020001, 0x3c040001, -0x24842ca0, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, -0xc0028eb, 0x34a5f006, 0x1021, 0x1040003f, 0x24020001, 0x3c010001, +0x24842e00, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, +0xc00290f, 0x34a5f006, 0x1021, 0x1040003f, 0x24020001, 0x3c010001, 0x370821, 0x10000064, 0xac2281d0, 0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020012, 0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, 0x1040ffb1, 0x0, 0x1000ffb9, 0x24020001, @@ -4288,14 +4316,14 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0xaec30018, 0x96e20452, 0x8ed10018, 0x30420020, 0x10400023, 0x24070008, 0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020019, 0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, -0x24020001, 0x3c040001, 0x24842ca0, 0xafb10010, 0xafa00014, 0x8ec6002c, -0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f006, 0x1021, 0x14400006, +0x24020001, 0x3c040001, 0x24842e00, 0xafb10010, 0xafa00014, 0x8ec6002c, +0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f006, 0x1021, 0x14400006, 0x24020001, 0x24020001, 0x3c010001, 0x370821, 0x10000031, 0xac2281d8, 0x3c010001, 0x370821, 0x10000021, 0xac2281d0, 0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020012, 0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, 0x24020001, 0x3c040001, -0x24842ca0, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, -0xc0028eb, 0x34a5f006, 0x1021, 0x14400005, 0x24020001, 0x3c010001, +0x24842e00, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, +0xc00290f, 0x34a5f006, 0x1021, 0x14400005, 0x24020001, 0x3c010001, 0x370821, 0x10000010, 0xac2281d4, 0x3c010001, 0x370821, 0xac2081d0, 0x3c010001, 0x370821, 0xac2081d8, 0x3c010001, 0x370821, 0xac2081d4, 0x8ec20264, 0xaec00024, 0xaed10028, 0x24420001, 0xaec20264, 0x8ec20264, @@ -4307,11 +4335,11 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x8ec202c4, 0x641821, 0x306300ff, 0x10000009, 0xaec3005c, 0x8ec202bc, 0x8ec3003c, 0x441021, 0xaec202bc, 0x8ec202c4, 0x641821, 0x306301ff, 0xaec3003c, 0x441021, 0xaec202c4, 0x1000001f, 0x36940040, 0x8fad0044, -0x24020014, 0x15a20010, 0x24020010, 0x3c020001, 0x8c4231d4, 0x10400017, +0x24020014, 0x15a20010, 0x24020010, 0x3c020001, 0x8c423334, 0x10400017, 0x26e50028, 0x26c40128, 0x240300ff, 0x2406ffff, 0x8ca20000, 0x24a50004, 0x2463ffff, 0xac820000, 0x1466fffb, 0x24840004, 0x1000000c, 0x0, -0x11a2000a, 0x3c050008, 0x96a7000e, 0x8ea2001c, 0x3c040001, 0x24842d20, -0xafb50014, 0xafa20010, 0x8ea60018, 0xc0028eb, 0x34a50910, 0x8fbf0078, +0x11a2000a, 0x3c050008, 0x96a7000e, 0x8ea2001c, 0x3c040001, 0x24842e80, +0xafb50014, 0xafa20010, 0x8ea60018, 0xc00290f, 0x34a50910, 0x8fbf0078, 0x8fbe0074, 0x8fb50070, 0x8fb3006c, 0x8fb10068, 0x3e00008, 0x27bd0080, 0x3e00008, 0x0, 0x803821, 0x8f8600e4, 0x8f8400e0, 0x2402fff8, 0x8cc30004, 0x822024, 0x10c4000d, 0x3c020100, 0x3c050100, 0x651024, @@ -4338,14 +4366,14 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0xaf8800c8, 0xaf8700e4, 0xaf8700e8, 0x3e00008, 0x0, 0x27bdff70, 0xafbf0088, 0xafbe0084, 0xafb50080, 0xafb3007c, 0xafb10078, 0x92c200ed, 0xa3a0004f, 0x1040000b, 0xa3a00067, 0x8ecd00f0, 0xafad0034, 0x8ece00f4, -0xafae002c, 0x8ecd00fc, 0x8ed500f8, 0xafad006c, 0x8ece0100, 0x100000d9, -0xafae003c, 0x3c020001, 0x8c4233b8, 0x40f809, 0x27a40020, 0x1040026e, +0xafae002c, 0x8ecd00fc, 0x8ed500f8, 0xafad006c, 0x8ece0100, 0x100000e9, +0xafae003c, 0x3c020001, 0x8c423518, 0x40f809, 0x27a40020, 0x10400295, 0x0, 0x8fa30024, 0x8fb50020, 0x306dffff, 0x25adfffc, 0xafad0034, 0x92a20000, 0xafb5002c, 0x30420001, 0x10400017, 0xafa3006c, 0x8ec2011c, 0x3c03ffff, 0x431024, 0x14400012, 0x2402ffff, 0x8ea30000, 0x14620004, 0x3402ffff, 0x96a30004, 0x1062000c, 0x0, 0xc0022ad, 0x2a02021, -0x304200ff, 0x14400007, 0x0, 0x3c020001, 0x8c4233b0, 0x40f809, -0x0, 0x1000024e, 0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff, +0x304200ff, 0x14400007, 0x0, 0x3c020001, 0x8c423510, 0x40f809, +0x0, 0x10000275, 0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff, 0x431024, 0x3c03ffff, 0x432824, 0x14a00003, 0xafa20024, 0x10000053, 0x1821, 0x3c020080, 0xa21024, 0x50400007, 0x3c040040, 0x8ec202e4, 0x24420001, 0xaec202e4, 0x8ec202e4, 0x10000049, 0x24030001, 0x3c070004, @@ -4362,1001 +4390,1008 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = { 0x8ec20128, 0x10000006, 0x42042, 0x8ec202e0, 0x24420001, 0xaec202e0, 0x8ec202e0, 0x42042, 0x1488ffc6, 0x851824, 0x24030001, 0x8f420260, 0x8fae0034, 0x4e102b, 0x10400015, 0x306400ff, 0x8f8200e0, 0xafa20010, -0x8f8200e4, 0x3c040001, 0x24842dfc, 0xafa20014, 0x8fa60020, 0x8fa70024, -0x3c050006, 0xc0028eb, 0x34a5f003, 0x8ec30150, 0x8fad006c, 0x3c020100, +0x8f8200e4, 0x3c040001, 0x24842f5c, 0xafa20014, 0x8fa60020, 0x8fa70024, +0x3c050006, 0xc00290f, 0x34a5f003, 0x8ec30150, 0x8fad006c, 0x3c020100, 0x24040001, 0x1a26825, 0x24630001, 0xafad006c, 0xaec30150, 0x8ec20150, 0x1080000f, 0x0, 0x8f420218, 0x30420800, 0x1440000b, 0x3c020180, 0x8fae006c, 0x1c21024, 0x10400005, 0x0, 0x8ec20174, 0x24420001, -0xaec20174, 0x8ec20174, 0x100001bd, 0x8fa30034, 0x8f420218, 0x30420400, +0xaec20174, 0x8ec20174, 0x100001e4, 0x8fa30034, 0x8f420218, 0x30420400, 0x10400004, 0x0, 0x8fad0034, 0x25ad0004, 0xafad0034, 0x8ec20050, -0x5040001d, 0xafa0003c, 0x8fae0034, 0x4e102b, 0x50400019, 0xafa0003c, -0x8ec20050, 0x1c21023, 0xafa2003c, 0x8ecd0050, 0x10000013, 0xafad0034, -0x8ec2005c, 0xafa20010, 0x8ec20060, 0x3c040001, 0x24842e08, 0xafa20014, -0x8ec6003c, 0x8ec70044, 0x3c050006, 0xc0028eb, 0x34a5f002, 0x8ec202b4, -0x2403ffbf, 0x283a024, 0x24420001, 0xaec202b4, 0x10000172, 0x8ec202b4, -0x96e20460, 0x8fae0034, 0x4e102b, 0x10400004, 0x0, 0x240d0001, -0xa3ad004f, 0x8fae0034, 0x11c00189, 0x3c02ffff, 0x8fad006c, 0x1a21024, -0xafa20074, 0x8ec20068, 0x8f430280, 0x24420001, 0x304203ff, 0x1062015f, -0x0, 0x93a2004f, 0x10400015, 0x0, 0x8ec3005c, 0x8ec20060, -0x1062000a, 0x26ce0060, 0x8ec60060, 0xafae0054, 0x8ec30060, 0x21140, -0x24424dc0, 0x2e28821, 0x24630001, 0x10000014, 0x306300ff, 0x92c20064, -0x1440ffc9, 0x0, 0x8ec202c8, 0x24420001, 0xaec202c8, 0x8ec202c8, -0x8ec3003c, 0x8ec20044, 0x1062ffc1, 0x26cd0044, 0x8ec60044, 0xafad0054, -0x8ec30044, 0x21140, 0x24420dc0, 0x2e28821, 0x24630001, 0x306301ff, -0xafa3005c, 0x96e20462, 0x30420010, 0x1040001a, 0x340e8100, 0x96a2000c, -0x144e0017, 0x0, 0x92c200ed, 0x14400014, 0x0, 0x96a2000e, -0xa6220016, 0x8ea20008, 0x8ea30004, 0x8fad0034, 0x8ea40000, 0x25adfffc, -0xafad0034, 0xaea2000c, 0xaea30008, 0xaea40004, 0x9622000e, 0x8fae002c, -0x240d0001, 0xa3ad0067, 0x25ce0004, 0x34420200, 0xafae002c, 0xa622000e, -0x9627000a, 0x8fae0034, 0xee102b, 0x14400002, 0x30f3fff8, 0x8fb30034, -0x8e240000, 0x8e250004, 0x8fad002c, 0x24020007, 0xae2d0018, 0xafa20010, -0xafa60014, 0x8ec20004, 0x8fa6002c, 0xafa20018, 0x8ec200a8, 0x40f809, -0x2603821, 0x1440001a, 0x3c050006, 0x3c040001, 0x24842e14, 0x8e220018, -0x34a5f009, 0xafa20010, 0x8e220000, 0x8e230004, 0x2203021, 0x2603821, -0xc0028eb, 0xafa30014, 0x93a20067, 0x104000fb, 0x0, 0x8ea20004, -0x8ea30008, 0x8ea4000c, 0x340e8100, 0xa6ae000c, 0xaea20000, 0xaea30004, -0xaea40008, 0x96220016, 0x100000f0, 0xa6a2000e, 0x8fad0034, 0x166d0089, -0x0, 0x962e000a, 0xafae0044, 0x8fae003c, 0x9623000e, 0x1ae1021, -0xa622000a, 0x34620004, 0xa622000e, 0x8fad0074, 0x11a00006, 0x307effff, -0x34620404, 0xa622000e, 0x8fae006c, 0xe1402, 0xa6220014, 0x8ec30068, -0x8ee40478, 0x8ee5047c, 0x24020004, 0xafa20010, 0x8ec20068, 0x2203021, -0x24070020, 0xafa20014, 0x8ec20008, 0x31940, 0x604821, 0xafa20018, -0x8ec200a8, 0x4021, 0xa92821, 0xa9182b, 0x882021, 0x40f809, -0x832021, 0x54400018, 0xa2c000ed, 0x97ad0046, 0xa63e000e, 0xa62d000a, -0x8f820100, 0xafa20010, 0x8f820104, 0x3c040001, 0x24842e20, 0x3c050006, -0xafa20014, 0x8ec60068, 0x34a5f00b, 0xc0028eb, 0x2203821, 0x93a20067, -0x104000b6, 0x0, 0x8ea20004, 0x8ea30008, 0x8ea4000c, 0x340e8100, -0x10000083, 0xa6ae000c, 0x8fae005c, 0x8fad0054, 0xadae0000, 0x8ec202c4, -0x8ec30068, 0x2442ffff, 0xaec202c4, 0x8ec202c4, 0x24630001, 0x306303ff, -0x26c20060, 0x15a20006, 0xaec30068, 0x8ec202c0, 0x2442ffff, 0xaec202c0, -0x10000005, 0x8ec202c0, 0x8ec202bc, 0x2442ffff, 0xaec202bc, 0x8ec202bc, -0x8ec20048, 0x24420001, 0xaec20048, 0x8f430240, 0x43102b, 0x54400090, -0xafa00034, 0x8ed10068, 0x8ee40490, 0x8ee50494, 0x8ec30008, 0x8f860120, -0x24020013, 0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x24070008, -0x40f809, 0x24c6001c, 0x1440000b, 0x24020001, 0x3c040001, 0x24842dac, -0xafb10010, 0xafa00014, 0x8ec60068, 0x8f470228, 0x3c050009, 0xc0028eb, -0x34a5f008, 0x1021, 0x14400005, 0x24020001, 0x3c010001, 0x370821, -0x1000000a, 0xac2281e0, 0x3c010001, 0x370821, 0xac2081e0, 0x8ec20268, -0xaec00048, 0xaed1006c, 0x24420001, 0xaec20268, 0x8ec20268, 0x8ec2027c, -0x24420001, 0xaec2027c, 0x8ec2027c, 0x10000062, 0xafa00034, 0x962d000a, -0xafad0044, 0x9622000e, 0xa633000a, 0x8fae0074, 0x11c00006, 0x305effff, -0x34420400, 0xa622000e, 0x8fad006c, 0xd1402, 0xa6220014, 0x8ec30068, -0x8ee40478, 0x8ee5047c, 0x24020004, 0xafa20010, 0x8ec20068, 0x2203021, -0x24070020, 0xafa20014, 0x8ec20008, 0x31940, 0x604821, 0xafa20018, -0x8ec200a8, 0x4021, 0xa92821, 0xa9182b, 0x882021, 0x40f809, -0x832021, 0x1440001f, 0x3c04001f, 0x97ae0046, 0xa63e000e, 0xa62e000a, -0x8f820100, 0xafa20010, 0x8f820104, 0x3c040001, 0x24842e20, 0x3c050006, -0xafa20014, 0x8ec60068, 0x34a5f00d, 0xc0028eb, 0x2203821, 0x93a20067, -0x10400032, 0x340d8100, 0x8ea20004, 0x8ea30008, 0x8ea4000c, 0xa6ad000c, -0xaea20000, 0xaea30004, 0xaea40008, 0x96220016, 0xa6a2000e, 0x9622000e, -0x3042fdff, 0x10000025, 0xa622000e, 0x8ec202c4, 0x8fae002c, 0x3484ffff, -0x1d37021, 0x2442ffff, 0xafae002c, 0xaec202c4, 0x8ec202c4, 0x8ec302bc, -0x24020001, 0x8e202b, 0xa2c200ed, 0x2463ffff, 0xaec302bc, 0x10800004, -0x8ec202bc, 0x8ec20540, 0x1c27023, 0xafae002c, 0x8fad0034, 0x8fae0054, -0x1b36823, 0xafad0034, 0x8fad005c, 0xadcd0000, 0x8ec20068, 0xa3a0004f, -0x8ec30048, 0x24420001, 0x304203ff, 0x24630001, 0xaec20068, 0xaec30048, -0x8fae0034, 0x15c0fe9d, 0x0, 0x8fad0034, 0x11a0001f, 0x0, -0xaecd00f0, 0x8fae002c, 0xaece00f4, 0xaed500f8, 0x93a20067, 0x10400004, -0x0, 0x8ec200f8, 0x24420004, 0xaec200f8, 0x8fad006c, 0x8ec20068, -0xaecd00fc, 0x8fae003c, 0xaece0100, 0x8f430280, 0x24420001, 0x304203ff, -0x14620006, 0x0, 0x8ec202b8, 0x24420001, 0xaec202b8, 0x10000016, -0x8ec202b8, 0x8ec202b0, 0x24420001, 0xaec202b0, 0x10000011, 0x8ec202b0, -0x8fad006c, 0x31a4ffff, 0x2484fffc, 0x801821, 0x8ec401b8, 0x8ec501bc, -0x3c060001, 0x8cc633b0, 0x1021, 0xa32821, 0xa3382b, 0x822021, -0x872021, 0xaec401b8, 0xc0f809, 0xaec501bc, 0x8fbf0088, 0x8fbe0084, -0x8fb50080, 0x8fb3007c, 0x8fb10078, 0x3e00008, 0x27bd0090, 0x3e00008, -0x0, 0x27bdff90, 0xafbf0068, 0xafbe0064, 0xafb50060, 0xafb3005c, -0xafb10058, 0x92c200ed, 0xafa0002c, 0x10400007, 0xa3a00037, 0x8ecf00fc, -0x8ec800f0, 0x8ec900f4, 0x8ed500f8, 0x100000d1, 0xafaf003c, 0x3c020001, -0x8c4233b8, 0x40f809, 0x27a40020, 0x104001ae, 0x0, 0x8fa30024, -0x8fb50020, 0x3068ffff, 0x92a20000, 0x2508fffc, 0x2a04821, 0x30420001, -0x1040001a, 0xafa3003c, 0x8ec2011c, 0x3c03ffff, 0x431024, 0x14400015, -0x2402ffff, 0x8ea30000, 0x14620005, 0x2a02021, 0x96a30004, 0x3402ffff, -0x1062000e, 0x0, 0xafa80048, 0xc0022ad, 0xafa9004c, 0x304200ff, -0x8fa80048, 0x14400007, 0x8fa9004c, 0x3c020001, 0x8c4233b0, 0x40f809, -0x0, 0x1000018c, 0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff, -0x431024, 0x3c03ffff, 0x432824, 0x14a00003, 0xafa20024, 0x10000053, -0x1821, 0x3c020080, 0xa21024, 0x50400007, 0x3c040040, 0x8ec202e4, -0x24420001, 0xaec202e4, 0x8ec202e4, 0x10000049, 0x24030001, 0x3c070004, -0x3c0e0001, 0x3c0d0002, 0x3c060010, 0x3c0c0008, 0x8ec20178, 0x3c0b0020, -0x340a8000, 0x24420001, 0xaec20178, 0x8ec20178, 0x851824, 0x10670021, -0xe3102b, 0x14400007, 0x0, 0x106e0011, 0x0, 0x106d0015, -0x0, 0x10000030, 0x42042, 0x10660023, 0xc3102b, 0x14400005, -0x0, 0x106c0019, 0x0, 0x10000028, 0x42042, 0x106b0021, -0x0, 0x10000024, 0x42042, 0x8ec2012c, 0x24420001, 0xaec2012c, -0x8ec2012c, 0x1000001e, 0x42042, 0x8ec202d4, 0x24420001, 0xaec202d4, -0x8ec202d4, 0x10000018, 0x42042, 0x8ec202d8, 0x24420001, 0xaec202d8, -0x8ec202d8, 0x10000012, 0x42042, 0x8ec202dc, 0x24420001, 0xaec202dc, -0x8ec202dc, 0x1000000c, 0x42042, 0x8ec20128, 0x24420001, 0xaec20128, -0x8ec20128, 0x10000006, 0x42042, 0x8ec202e0, 0x24420001, 0xaec202e0, -0x8ec202e0, 0x42042, 0x148affc6, 0x851824, 0x24030001, 0x8f420260, -0x48102b, 0x10400019, 0x306400ff, 0x8f8200e0, 0xafa20010, 0x8f8200e4, -0x3c040001, 0x24842dfc, 0xafa20014, 0x8fa60020, 0x8fa70024, 0x3c050006, -0x34a5f003, 0xafa80048, 0xc0028eb, 0xafa9004c, 0x8ec30150, 0x8faf003c, -0x3c020100, 0x24040001, 0x1e27825, 0x24630001, 0xafaf003c, 0xaec30150, -0x8ec20150, 0x8fa9004c, 0x8fa80048, 0x10800025, 0x0, 0x8f420218, -0x30420800, 0x14400021, 0x3c020180, 0x8faf003c, 0x1e21024, 0x104000fe, -0x1001821, 0x8ec20174, 0x24420001, 0xaec20174, 0x8ec20174, 0x100000f8, -0x1001821, 0x8ec2005c, 0xafa20010, 0x8ec20060, 0x3c040001, 0x24842e08, -0xafa20014, 0x8ec6003c, 0x8ec70044, 0x3c050006, 0x34a5f002, 0xafa80048, -0xc0028eb, 0xafa9004c, 0x8ec202b4, 0x2403ffbf, 0x283a024, 0x24420001, -0xaec202b4, 0x8ec202b4, 0x8fa80048, 0x100000c2, 0x8fa9004c, 0x8f420218, -0x30420400, 0x54400001, 0x25080004, 0x96e20460, 0x48102b, 0x10400003, -0x0, 0x3c0f8000, 0xafaf002c, 0x110000d2, 0x3c02ffff, 0x8faf003c, -0x1e21024, 0xafa20044, 0x8ec20068, 0x8f430280, 0x24420001, 0x304203ff, -0x106200ad, 0x0, 0x8faf002c, 0x11e00014, 0x0, 0x8ec3005c, -0x8ec20060, 0x10620009, 0x26cb0060, 0x8ec60060, 0x8ec30060, 0x21140, -0x24424dc0, 0x2e28821, 0x24630001, 0x10000014, 0x306a00ff, 0x92c20064, -0x1440ffc4, 0x0, 0x8ec202c8, 0x24420001, 0xaec202c8, 0x8ec202c8, -0x8ec3003c, 0x8ec20044, 0x1062ffbc, 0x26cb0044, 0x8ec60044, 0xafa0002c, -0x8ec30044, 0x21140, 0x24420dc0, 0x2e28821, 0x24630001, 0x306a01ff, -0x96e20462, 0x30420010, 0x10400017, 0x0, 0x96a2000c, 0x340f8100, -0x144f0013, 0x0, 0x92c200ed, 0x14400010, 0x0, 0x96a2000e, -0xa6220016, 0x8ea20008, 0x8ea30004, 0x8ea40000, 0x2508fffc, 0xaea2000c, -0xaea30008, 0xaea40004, 0x9622000e, 0x25290004, 0x240f0001, 0xa3af0037, -0x34420200, 0xa622000e, 0x9623000a, 0x68102b, 0x14400002, 0x3073fff8, -0x1009821, 0x92c300ed, 0x2e62003d, 0x2c630001, 0x621824, 0x1060000f, -0x260f021, 0x9523000c, 0x24020800, 0x5462000c, 0xae290018, 0x91220017, -0x38430006, 0x2c630001, 0x38420011, 0x2c420001, 0x621825, 0x50600004, -0xae290018, 0x95220010, 0x245e000e, 0xae290018, 0x92c300ed, 0x8e240000, -0x8e250004, 0x8faf002c, 0x2402000b, 0xafa20010, 0x3182b, 0x31ec0, -0xcf1025, 0x431025, 0xafa20014, 0x8ec20004, 0xafa20018, 0x8ec200a8, -0x3c03821, 0x1203021, 0xafa80048, 0xafa9004c, 0xafaa0050, 0x40f809, -0xafab0054, 0x8fa80048, 0x8fa9004c, 0x8faa0050, 0x8fab0054, 0x1440001d, -0x3c050006, 0x3c040001, 0x24842e14, 0x8e220018, 0x34a5f009, 0xafa20010, -0x8e220000, 0x8e230004, 0x2203021, 0x3c03821, 0xafa80048, 0xafa9004c, -0xc0028eb, 0xafa30014, 0x93a20037, 0x8fa80048, 0x8fa9004c, 0x1040002a, -0x340f8100, 0x8ea20004, 0x8ea30008, 0x8ea4000c, 0xa6af000c, 0xaea20000, -0xaea30004, 0xaea40008, 0x96220016, 0x10000020, 0xa6a2000e, 0x8faf0044, -0x11e00007, 0x0, 0x8faf003c, 0x9623000e, 0xf1402, 0x34630400, -0xa6220014, 0xa623000e, 0x56680008, 0x1334821, 0x9622000e, 0xa628000a, -0x4021, 0x34420004, 0xa622000e, 0x1000000c, 0xa2c000ed, 0x3c03001f, -0x3463ffff, 0x24020001, 0x69182b, 0xa633000a, 0x10600003, 0xa2c200ed, -0x8ec20540, 0x1224823, 0x1134023, 0xafa0002c, 0x1500ff4f, 0xad6a0000, -0x1100001b, 0x0, 0xaec800f0, 0xaec900f4, 0xaed500f8, 0x93a20037, -0x10400004, 0x0, 0x8ec200f8, 0x24420004, 0xaec200f8, 0x8faf003c, -0x8ec20068, 0xaecf00fc, 0x8f430280, 0x24420001, 0x14620006, 0x0, -0x8ec202b8, 0x24420001, 0xaec202b8, 0x10000016, 0x8ec202b8, 0x8ec202b0, -0x24420001, 0xaec202b0, 0x10000011, 0x8ec202b0, 0x8faf003c, 0x31e4ffff, -0x2484fffc, 0x801821, 0x8ec401b8, 0x8ec501bc, 0x3c060001, 0x8cc633b0, -0x1021, 0xa32821, 0xa3382b, 0x822021, 0x872021, 0xaec401b8, -0xc0f809, 0xaec501bc, 0x8fbf0068, 0x8fbe0064, 0x8fb50060, 0x8fb3005c, -0x8fb10058, 0x3e00008, 0x27bd0070, 0x3e00008, 0x0, 0x27bdffd8, -0xafbf0024, 0xafb10020, 0x8ec30040, 0x8ec20038, 0x1062004d, 0x0, -0x8ec30038, 0x8ec20040, 0x623823, 0x4e20001, 0x24e70200, 0x8ec30044, -0x8ec20040, 0x43102b, 0x14400004, 0x24020200, 0x8ec30040, 0x10000005, -0x431823, 0x8ec20044, 0x8ec30040, 0x431023, 0x2443ffff, 0xe08821, -0x71102a, 0x54400001, 0x608821, 0x8ec90040, 0x8ee40458, 0x8ee5045c, -0x8ec60040, 0x113940, 0x24080002, 0xafa80010, 0x8ec80040, 0x94940, -0x1201821, 0x1021, 0xafa80014, 0x8ec80010, 0xa32821, 0xa3482b, -0x822021, 0x892021, 0x63140, 0xafa80018, 0x8ec200a4, 0x24c60dc0, -0x40f809, 0x2e63021, 0x1440000e, 0x24030040, 0x8ec20040, 0xafa20010, -0x8ec20044, 0x3c040001, 0x24842e2c, 0xafa20014, 0x8ec60038, 0x8ec7003c, -0x3c050007, 0xc0028eb, 0x34a5f001, 0x10000010, 0x0, 0x8ec20030, -0x24420001, 0x50430003, 0x1021, 0x8ec20030, 0x24420001, 0xaec20030, -0x8ec20030, 0x21080, 0x571021, 0xac510cc0, 0x8ec20040, 0x511021, -0x304201ff, 0xaec20040, 0x8ec30040, 0x8ec20038, 0x14620017, 0x0, -0x8ec20000, 0x10400007, 0x2403fdff, 0xaf80004c, 0x8f82004c, 0x1040fffd, -0x0, 0x10000005, 0x0, 0xaf800048, 0x8f820048, 0x1040fffd, -0x0, 0x8f820060, 0x431024, 0xaf820060, 0x8ec20000, 0x10400003, -0x0, 0x10000002, 0xaf80004c, 0xaf800048, 0x8fbf0024, 0x8fb10020, -0x3e00008, 0x27bd0028, 0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024, -0xafb10020, 0x8ec30058, 0x8ec20054, 0x1062004d, 0x0, 0x8ec30054, -0x8ec20058, 0x623823, 0x4e20001, 0x24e70100, 0x8ec30060, 0x8ec20058, -0x43102b, 0x14400004, 0x24020100, 0x8ec30058, 0x10000005, 0x431823, -0x8ec20060, 0x8ec30058, 0x431023, 0x2443ffff, 0xe08821, 0x71102a, -0x54400001, 0x608821, 0x8ec90058, 0x8ee40468, 0x8ee5046c, 0x8ec60058, -0x113940, 0x24080003, 0xafa80010, 0x8ec80058, 0x94940, 0x1201821, -0x1021, 0xafa80014, 0x8ec80010, 0xa32821, 0xa3482b, 0x822021, -0x892021, 0x63140, 0xafa80018, 0x8ec200a4, 0x24c64dc0, 0x40f809, -0x2e63021, 0x1440000e, 0x24030040, 0x8ec20058, 0xafa20010, 0x8ec20060, -0x3c040001, 0x24842e38, 0xafa20014, 0x8ec60054, 0x8ec7005c, 0x3c050007, -0xc0028eb, 0x34a5f010, 0x10000010, 0x0, 0x8ec20030, 0x24420001, -0x50430003, 0x1021, 0x8ec20030, 0x24420001, 0xaec20030, 0x8ec20030, -0x21080, 0x571021, 0xac510cc0, 0x8ec20058, 0x511021, 0x304200ff, -0xaec20058, 0x8ec30058, 0x8ec20054, 0x14620017, 0x0, 0x8ec20000, -0x10400007, 0x2403feff, 0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0, -0x10000005, 0x0, 0xaf800048, 0x8f820048, 0x1040fffd, 0x0, -0x8f820060, 0x431024, 0xaf820060, 0x8ec20000, 0x10400003, 0x0, -0x10000002, 0xaf80004c, 0xaf800048, 0x8fbf0024, 0x8fb10020, 0x3e00008, -0x27bd0028, 0x3e00008, 0x0, 0x8f820120, 0x8ec300e8, 0x8f820124, -0x8f860128, 0x24020040, 0x24630001, 0x50620003, 0x1021, 0x8ec200e8, -0x24420001, 0xaec200e8, 0x8ec200e8, 0x8ec400e8, 0x8ec300e4, 0x210c0, -0x24426fc0, 0x14830007, 0x2e22821, 0x8f820128, 0x24420020, 0xaf820128, -0x8f820128, 0x10000011, 0xaca00000, 0x8ec200e8, 0x24030040, 0x24420001, -0x50430003, 0x1021, 0x8ec200e8, 0x24420001, 0x220c0, 0x2e41021, -0x8c426fc4, 0x8f830128, 0x21140, 0x621821, 0x2e41021, 0xaf830128, -0xac406fc0, 0x8cc20018, 0x2443fffe, 0x2c620018, 0x1040000a, 0x31080, -0x3c010001, 0x220821, 0x8c222e48, 0x400008, 0x0, 0x24020001, -0x3c010001, 0x370821, 0xac2281e8, 0x3e00008, 0x0, 0x3e00008, -0x0, 0x27bdffa8, 0xafbf0050, 0xafbe004c, 0xafb50048, 0xafb30044, -0xafb10040, 0x8f830128, 0x8f820124, 0x106201e1, 0x0, 0x8f9e0128, -0x8f820128, 0x24420020, 0xaf820128, 0x8fc40018, 0x8f820128, 0x2402000b, -0x1482018f, 0x24020002, 0x8fc3001c, 0x97c20016, 0x3064ffff, 0xafc20014, -0x3c028000, 0x621024, 0xafc4001c, 0xafa2002c, 0x8fab002c, 0x3c020800, -0x11600004, 0x622824, 0x41140, 0x10000003, 0x24424dc0, 0x41140, -0x24420dc0, 0x2e2a821, 0x96a2000e, 0x3043fffc, 0x30420400, 0x10400003, -0xa6a3000e, 0x10000137, 0x8821, 0x10a00004, 0x8821, 0x97d10016, -0x10000132, 0x0, 0x8eab0018, 0xafab0034, 0x9563000c, 0x96eb0462, -0x24020800, 0x1462012b, 0xafab003c, 0x8fab0034, 0x2573000e, 0x8fab003c, -0x31620002, 0x1040003f, 0x3c030020, 0x8ec70540, 0x263102b, 0x14400002, -0x2604821, 0x2674823, 0x25220014, 0x43102b, 0x10400027, 0x24030005, -0x91220000, 0x3042000f, 0x14430024, 0x1202021, 0x952a0000, 0x25290002, -0x95280000, 0x25290002, 0x95270000, 0x25290002, 0x95260000, 0x25290002, -0x95250000, 0x25290002, 0x95230000, 0x25290002, 0x95220000, 0x25290002, -0x95240000, 0x25290002, 0x1485021, 0x1475021, 0x1465021, 0x1455021, -0x1435021, 0x1425021, 0x95220000, 0x95230002, 0x1445021, 0x1425021, -0x1435021, 0xa1c02, 0x3142ffff, 0x625021, 0xa1c02, 0x3142ffff, -0x10000009, 0x625021, 0x1202021, 0x90850000, 0x3c060020, 0x8ec200ac, -0x30a5000f, 0x40f809, 0x52840, 0x304affff, 0x3143ffff, 0x50600001, -0x3403ffff, 0x96a2000e, 0x34420002, 0x10000002, 0xa6a2000e, 0x1821, -0xa6a30010, 0x8fab003c, 0x31620001, 0x104000e1, 0x0, 0x92620009, -0x38430006, 0x2c630001, 0x38420011, 0x2c420001, 0x621825, 0x106000d9, -0x3c030020, 0x8fa60034, 0x8ec70540, 0xc3102b, 0x50400001, 0xc73023, -0x24c2000e, 0x43102b, 0x1040001a, 0xc02021, 0x94c70000, 0x24c60002, -0x94c50000, 0x24c60002, 0x94c30000, 0x24c60002, 0x94c20000, 0x24c60002, -0x94c40000, 0x24c60002, 0xe53821, 0xe33821, 0xe23821, 0x94c20000, -0x94c30002, 0xe43821, 0xe23821, 0xe33821, 0x71c02, 0x30e2ffff, -0x623821, 0x71c02, 0x30e2ffff, 0x10000006, 0x623821, 0x8ec200ac, -0x24050007, 0x40f809, 0x3c060020, 0x3047ffff, 0x8fab003c, 0x31620008, -0x10400003, 0x30e8ffff, 0x1000005b, 0x4821, 0x96620006, 0x30421fff, -0x10400007, 0x2602821, 0x92620000, 0x96630002, 0x3042000f, 0x21080, -0x10000051, 0x624823, 0x3c070020, 0x8ec30540, 0xa7102b, 0x50400001, -0xa32823, 0x24a20014, 0x47102b, 0x10400015, 0xa02021, 0x90a20000, -0x94a30002, 0x3042000f, 0x21080, 0x623023, 0xafa20020, 0x90a30009, -0x24a5000c, 0x94a20000, 0x24a50002, 0x94a40000, 0x24a50002, 0xc33021, -0xc23021, 0x94a20000, 0x94a30002, 0xc43021, 0xc23021, 0x1000002d, -0xc33021, 0x24a50002, 0xa7102b, 0x50400001, 0xa32823, 0x94a60000, -0x802821, 0xa7102b, 0x50400001, 0xa32823, 0x90a20000, 0x24850009, -0x3042000f, 0x21080, 0xc23023, 0xafa20020, 0xa7102b, 0x50400001, -0xa32823, 0x90a20000, 0x2485000c, 0xc23021, 0xa7102b, 0x50400001, -0xa32823, 0x94a20000, 0x24a50002, 0xc23021, 0xa7102b, 0x50400001, -0xa32823, 0x94a20000, 0x24a50002, 0xc23021, 0xa7102b, 0x50400001, -0xa32823, 0x94a20000, 0x24a50002, 0xc23021, 0xa7102b, 0x50400001, -0xa32823, 0x94a20000, 0xc23021, 0x61c02, 0x30c2ffff, 0x623021, -0x61402, 0x30c3ffff, 0x431021, 0x3049ffff, 0x96a2000e, 0x30420004, -0x10400041, 0x0, 0x8f420218, 0x30420400, 0x1040003d, 0x3c070020, -0x97c2000e, 0x8fc30008, 0x8ec60540, 0x621821, 0x2463fffc, 0x67102b, -0x50400001, 0x661823, 0x602821, 0x24a20004, 0x47102b, 0x5040000a, -0xa7102b, 0x90a20000, 0x90a40001, 0x90a30002, 0x21200, 0x441021, -0x90a40003, 0x31a00, 0x10000017, 0x431021, 0x50400001, 0xa62823, -0x90a20000, 0x24a50001, 0x22200, 0xa7102b, 0x50400001, 0xa62823, -0x90a20000, 0x24a50001, 0x822021, 0xa7102b, 0x50400001, 0xa62823, -0x90a20000, 0x24a50001, 0x21200, 0x822021, 0xa7102b, 0x50400001, -0xa62823, 0x90a20000, 0x822021, 0x41c02, 0x3082ffff, 0x622021, -0x41402, 0x3083ffff, 0x431021, 0x3042ffff, 0x1024021, 0x81c02, -0x3102ffff, 0x624021, 0x81c02, 0x3102ffff, 0x624021, 0x3108ffff, -0x8fc20014, 0x488823, 0x111402, 0x2228821, 0x2298821, 0x111402, -0x2228821, 0x3231ffff, 0x52200001, 0x3411ffff, 0x96a2000e, 0x34420001, -0xa6a2000e, 0x96a2000e, 0x24080002, 0x30420004, 0x10400002, 0xa6b10012, -0x24080004, 0x8ec90068, 0x8ee40478, 0x8ee5047c, 0xafa80010, 0x8ec80068, -0x8fab002c, 0x2a03021, 0x24070020, 0x10b4025, 0xafa80014, 0x8ec80008, -0x94940, 0x1201821, 0xafa80018, 0x8ec800a8, 0x1021, 0xa32821, -0xa3482b, 0x822021, 0x100f809, 0x892021, 0x1440000e, 0x0, -0x8f820120, 0xafa20010, 0x8f820128, 0x3c040001, 0x24842ea8, 0xafa20014, -0x8fc6001c, 0x8f870124, 0x3c050008, 0xc0028eb, 0x34a50001, 0x1000005f, -0x0, 0x8ec20068, 0x24420001, 0x304203ff, 0xaec20068, 0x8fab002c, -0x11600006, 0x0, 0x8ec202c0, 0x2442ffff, 0xaec202c0, 0x10000005, -0x8ec202c0, 0x8ec202bc, 0x2442ffff, 0xaec202bc, 0x8ec202bc, 0x8ec202c4, -0x2442ffff, 0xaec202c4, 0x1000004a, 0x8ec202c4, 0x14820005, 0x24020004, -0x8ec20048, 0x24420001, 0x10000044, 0xaec20048, 0x14820036, 0x38830011, -0x97c2001e, 0xafc2001c, 0x8ec20048, 0x24420001, 0xaec20048, 0x8f430240, -0x43102b, 0x14400039, 0x24070008, 0x8ed10068, 0x8ee40490, 0x8ee50494, -0x8ec30008, 0x8f860120, 0x24020013, 0xafa20010, 0xafb10014, 0xafa30018, -0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, 0x24020001, 0x3c040001, -0x24842dac, 0xafb10010, 0xafa00014, 0x8ec60068, 0x8f470228, 0x3c050009, -0xc0028eb, 0x34a5f008, 0x1021, 0x14400005, 0x24020001, 0x3c010001, -0x370821, 0x1000000a, 0xac2281e0, 0x3c010001, 0x370821, 0xac2081e0, -0x8ec20268, 0xaec00048, 0xaed1006c, 0x24420001, 0xaec20268, 0x8ec20268, -0x8ec2027c, 0x24420001, 0xaec2027c, 0x1000000d, 0x8ec2027c, 0x2c630001, -0x38820013, 0x2c420001, 0x621825, 0x14600004, 0x24020001, 0x24020012, -0x14820004, 0x24020001, 0x3c010001, 0x370821, 0xac2281e8, 0x8fbf0050, -0x8fbe004c, 0x8fb50048, 0x8fb30044, 0x8fb10040, 0x3e00008, 0x27bd0058, -0x3e00008, 0x0, 0x0, 0x0, 0x8ec20538, 0xaf8200c0, -0x8ec20538, 0xaf8200c4, 0x8ec20538, 0xaf8200c8, 0x8ec20534, 0xaf8200d0, -0x8ec20534, 0xaf8200d4, 0x8ec20534, 0x3e00008, 0xaf8200d8, 0x27bdffe8, -0x27840208, 0x27450200, 0xafbf0010, 0xc00297e, 0x24060008, 0x8f420204, -0xc003c3a, 0xaf820210, 0x24040001, 0x8f460248, 0x24020004, 0x3c010001, -0xac2232ac, 0xc004680, 0x24050004, 0x3c020001, 0x8c4232a8, 0x30420001, -0x10400007, 0x24020001, 0x3c010001, 0xac2232ac, 0x24040001, 0x24050001, -0xc004680, 0x3c06601b, 0x8ec20548, 0x8ec4054c, 0x8ec30550, 0x3c010001, -0xac2032a4, 0x3c010001, 0xac2032bc, 0x21640, 0x42140, 0x34840403, -0x441025, 0x31bc0, 0x431025, 0xaf82021c, 0x8fbf0010, 0x3e00008, -0x27bd0018, 0x27bdffe0, 0x3c050008, 0x34a50400, 0xafbf0018, 0xafa00010, -0xafa00014, 0x8f860200, 0x3c040001, 0x24842f7c, 0xc0028eb, 0x3821, -0x8ec20368, 0x24420001, 0xaec20368, 0x8ec20368, 0x8f830200, 0x3c023f00, -0x621824, 0x8fbf0018, 0x3c020400, 0x3e00008, 0x27bd0020, 0x27bdffd8, -0xafbf0020, 0xafb3001c, 0xafb10018, 0x8f910220, 0x8ec202fc, 0x24420001, -0xaec202fc, 0x8ec202fc, 0x8ec30310, 0x3c020001, 0x8c4232bc, 0x3c040001, -0x24842f88, 0xafa20014, 0xafa30010, 0x8ec70314, 0x3c050008, 0xc0028eb, -0x2203021, 0x3c024000, 0x2221024, 0x104000e5, 0x3c040100, 0x8ec20314, -0x24420001, 0xaec20314, 0x8ec20314, 0x8f820220, 0x3c0308ff, 0x3463ffff, -0x431024, 0x34420004, 0xaf820220, 0x8f8200e0, 0x8f8300c4, 0x3c02001f, -0x3442ffff, 0x24690008, 0x49102b, 0x10400003, 0x0, 0x8ec20540, -0x1224823, 0x8f8700c8, 0x8f850120, 0x8f840124, 0x10000005, 0x5821, -0x8ec20534, 0x82102b, 0x50400001, 0x27644800, 0x10a40010, 0x316200ff, -0x8c820018, 0x38430007, 0x2c630001, 0x3842000b, 0x2c420001, 0x621825, -0x5060fff3, 0x24840020, 0x8ec20328, 0x240b0001, 0x24420001, 0xaec20328, -0x8ec20328, 0x8c870008, 0x316200ff, 0x14400078, 0x0, 0x92c200ed, -0x14400075, 0x0, 0x8f8500e4, 0x8f8200e0, 0x2403fff8, 0x433024, -0xc51023, 0x218c3, 0x4620001, 0x24630100, 0x8f8a00c4, 0x10600005, -0x24020001, 0x10620009, 0x0, 0x10000021, 0x0, 0x8ec20318, -0x1403821, 0x24420001, 0xaec20318, 0x10000060, 0x8ec20318, 0x8ec2031c, -0x24420001, 0xaec2031c, 0x8ca70000, 0x8ec20540, 0x8ec3031c, 0x1471823, -0x43102b, 0x10400004, 0x2c62233f, 0x8ec20540, 0x621821, 0x2c62233f, -0x14400051, 0x3c020100, 0xaca20004, 0x8f8200e8, 0x24420008, 0xaf8200e8, -0x8f8200e8, 0x8f8200e4, 0x1403821, 0x24420008, 0xaf8200e4, 0x10000046, -0x8f8200e4, 0x8ec20320, 0x24420001, 0xaec20320, 0x8ca80000, 0x8ec20540, -0x8ec30320, 0x1092023, 0x44102b, 0x10400003, 0x0, 0x8ec20540, -0x822021, 0x8ec20544, 0x44102b, 0x10400003, 0x3c030100, 0x10000034, -0x1003821, 0x8ca20004, 0x431025, 0xaca20004, 0x8f8200e4, 0x24450008, -0xaf8500e4, 0x8f8500e4, 0x10a60025, 0x3c080100, 0x8ec20174, 0x24420001, -0xaec20174, 0x8ca20004, 0x8ec30174, 0x481024, 0x1440000e, 0x0, -0x8ca30000, 0x8ec20540, 0x692023, 0x44102b, 0x10400003, 0x0, -0x8ec20540, 0x822021, 0x8ec20544, 0x44102b, 0x10400006, 0x0, -0x603821, 0x8ec20544, 0x44102b, 0x1440000a, 0x0, 0x8ca20004, -0x481025, 0xaca20004, 0x8f8200e4, 0x24450008, 0xaf8500e4, 0x8f8500e4, -0x14a6ffdf, 0x0, 0x14a60005, 0x0, 0x1403821, 0xaf8600e4, -0x10000003, 0xaf8600e8, 0xaf8500e4, 0xaf8500e8, 0x8f8300c8, 0x8ec20540, -0x692023, 0x44102b, 0x10400003, 0x0, 0x8ec20540, 0x822021, -0x8ec20544, 0x82102b, 0x50400008, 0x5821, 0x8ec20540, 0xe92023, +0x5040002d, 0xafa0003c, 0x8fae0034, 0x4e102b, 0x50400029, 0xafa0003c, +0x8ec20050, 0x1c21023, 0xafa2003c, 0x8ecd0050, 0x10000023, 0xafad0034, +0x8ec2005c, 0xafa20010, 0x8ec20060, 0x3c040001, 0x24842f68, 0xafa20014, +0x8ec6003c, 0x8ec70044, 0x3c050006, 0xc00290f, 0x34a5f002, 0x8ec202b4, +0x2403ffbf, 0x283a024, 0x24420001, 0xaec202b4, 0x10000199, 0x8ec202b4, +0x8e220018, 0x8fa70034, 0x3c040001, 0x24842f74, 0xafa20010, 0x8e220000, +0x8e230004, 0x34a5f709, 0x2203021, 0xc00290f, 0xafa30014, 0x8ec20298, +0x24420001, 0xaec20298, 0x10000189, 0x8ec20298, 0x96e20460, 0x8fae0034, +0x4e102b, 0x10400004, 0x0, 0x240d0001, 0xa3ad004f, 0x8fae0034, +0x11c001a0, 0x3c02ffff, 0x8fad006c, 0x1a21024, 0xafa20074, 0x8ec20068, +0x8f430280, 0x24420001, 0x304203ff, 0x10620176, 0x0, 0x93a2004f, +0x10400015, 0x0, 0x8ec3005c, 0x8ec20060, 0x1062000a, 0x26ce0060, +0x8ec60060, 0xafae0054, 0x8ec30060, 0x21140, 0x24424dc0, 0x2e28821, +0x24630001, 0x10000014, 0x306300ff, 0x92c20064, 0x1440ffb9, 0x0, +0x8ec202c8, 0x24420001, 0xaec202c8, 0x8ec202c8, 0x8ec3003c, 0x8ec20044, +0x1062ffb1, 0x26cd0044, 0x8ec60044, 0xafad0054, 0x8ec30044, 0x21140, +0x24420dc0, 0x2e28821, 0x24630001, 0x306301ff, 0xafa3005c, 0x8f83012c, +0x10600011, 0x24040002, 0x8f820124, 0x431023, 0x21143, 0x58400001, +0x24420040, 0x82102a, 0x1040000a, 0x1021, 0x8f820128, 0x431023, +0x21143, 0x58400001, 0x24420040, 0x82102a, 0x14400002, 0x24020001, +0x1021, 0x304200ff, 0x1040ffa3, 0x3c050006, 0x96e20462, 0x30420010, +0x1040001a, 0x340e8100, 0x96a2000c, 0x144e0017, 0x0, 0x92c200ed, +0x14400014, 0x0, 0x96a2000e, 0xa6220016, 0x8ea20008, 0x8ea30004, +0x8fad0034, 0x8ea40000, 0x25adfffc, 0xafad0034, 0xaea2000c, 0xaea30008, +0xaea40004, 0x9622000e, 0x8fae002c, 0x240d0001, 0xa3ad0067, 0x25ce0004, +0x34420200, 0xafae002c, 0xa622000e, 0x9627000a, 0x8fae0034, 0xee102b, +0x14400002, 0x30f3fff8, 0x8fb30034, 0x8e240000, 0x8e250004, 0x8fad002c, +0x24020007, 0xae2d0018, 0xafa20010, 0xafa60014, 0x8ec20004, 0x8fa6002c, +0xafa20018, 0x8ec200a8, 0x40f809, 0x2603821, 0x1440001a, 0x3c050006, +0x3c040001, 0x24842f80, 0x8e220018, 0x34a5f009, 0xafa20010, 0x8e220000, +0x8e230004, 0x2203021, 0x2603821, 0xc00290f, 0xafa30014, 0x93a20067, +0x104000fb, 0x0, 0x8ea20004, 0x8ea30008, 0x8ea4000c, 0x340e8100, +0xa6ae000c, 0xaea20000, 0xaea30004, 0xaea40008, 0x96220016, 0x100000f0, +0xa6a2000e, 0x8fad0034, 0x166d0089, 0x0, 0x962e000a, 0xafae0044, +0x8fae003c, 0x9623000e, 0x1ae1021, 0xa622000a, 0x34620004, 0xa622000e, +0x8fad0074, 0x11a00006, 0x307effff, 0x34620404, 0xa622000e, 0x8fae006c, +0xe1402, 0xa6220014, 0x8ec30068, 0x8ee40478, 0x8ee5047c, 0x24020004, +0xafa20010, 0x8ec20068, 0x2203021, 0x24070020, 0xafa20014, 0x8ec20008, +0x31940, 0x604821, 0xafa20018, 0x8ec200a8, 0x4021, 0xa92821, +0xa9182b, 0x882021, 0x40f809, 0x832021, 0x54400018, 0xa2c000ed, +0x97ad0046, 0xa63e000e, 0xa62d000a, 0x8f820100, 0xafa20010, 0x8f820104, +0x3c040001, 0x24842f8c, 0x3c050006, 0xafa20014, 0x8ec60068, 0x34a5f00b, +0xc00290f, 0x2203821, 0x93a20067, 0x104000b6, 0x0, 0x8ea20004, +0x8ea30008, 0x8ea4000c, 0x340e8100, 0x10000083, 0xa6ae000c, 0x8fae005c, +0x8fad0054, 0xadae0000, 0x8ec202c4, 0x8ec30068, 0x2442ffff, 0xaec202c4, +0x8ec202c4, 0x24630001, 0x306303ff, 0x26c20060, 0x15a20006, 0xaec30068, +0x8ec202c0, 0x2442ffff, 0xaec202c0, 0x10000005, 0x8ec202c0, 0x8ec202bc, +0x2442ffff, 0xaec202bc, 0x8ec202bc, 0x8ec20048, 0x24420001, 0xaec20048, +0x8f430240, 0x43102b, 0x54400090, 0xafa00034, 0x8ed10068, 0x8ee40490, +0x8ee50494, 0x8ec30008, 0x8f860120, 0x24020013, 0xafa20010, 0xafb10014, +0xafa30018, 0x8ec200a8, 0x24070008, 0x40f809, 0x24c6001c, 0x1440000b, +0x24020001, 0x3c040001, 0x24842f0c, 0xafb10010, 0xafa00014, 0x8ec60068, +0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f008, 0x1021, 0x14400005, +0x24020001, 0x3c010001, 0x370821, 0x1000000a, 0xac2281e0, 0x3c010001, +0x370821, 0xac2081e0, 0x8ec20268, 0xaec00048, 0xaed1006c, 0x24420001, +0xaec20268, 0x8ec20268, 0x8ec2027c, 0x24420001, 0xaec2027c, 0x8ec2027c, +0x10000062, 0xafa00034, 0x962d000a, 0xafad0044, 0x9622000e, 0xa633000a, +0x8fae0074, 0x11c00006, 0x305effff, 0x34420400, 0xa622000e, 0x8fad006c, +0xd1402, 0xa6220014, 0x8ec30068, 0x8ee40478, 0x8ee5047c, 0x24020004, +0xafa20010, 0x8ec20068, 0x2203021, 0x24070020, 0xafa20014, 0x8ec20008, +0x31940, 0x604821, 0xafa20018, 0x8ec200a8, 0x4021, 0xa92821, +0xa9182b, 0x882021, 0x40f809, 0x832021, 0x1440001f, 0x3c04001f, +0x97ae0046, 0xa63e000e, 0xa62e000a, 0x8f820100, 0xafa20010, 0x8f820104, +0x3c040001, 0x24842f8c, 0x3c050006, 0xafa20014, 0x8ec60068, 0x34a5f00d, +0xc00290f, 0x2203821, 0x93a20067, 0x10400032, 0x340d8100, 0x8ea20004, +0x8ea30008, 0x8ea4000c, 0xa6ad000c, 0xaea20000, 0xaea30004, 0xaea40008, +0x96220016, 0xa6a2000e, 0x9622000e, 0x3042fdff, 0x10000025, 0xa622000e, +0x8ec202c4, 0x8fae002c, 0x3484ffff, 0x1d37021, 0x2442ffff, 0xafae002c, +0xaec202c4, 0x8ec202c4, 0x8ec302bc, 0x24020001, 0x8e202b, 0xa2c200ed, +0x2463ffff, 0xaec302bc, 0x10800004, 0x8ec202bc, 0x8ec20540, 0x1c27023, +0xafae002c, 0x8fad0034, 0x8fae0054, 0x1b36823, 0xafad0034, 0x8fad005c, +0xadcd0000, 0x8ec20068, 0xa3a0004f, 0x8ec30048, 0x24420001, 0x304203ff, +0x24630001, 0xaec20068, 0xaec30048, 0x8fae0034, 0x15c0fe86, 0x0, +0x8fad0034, 0x11a0001f, 0x0, 0xaecd00f0, 0x8fae002c, 0xaece00f4, +0xaed500f8, 0x93a20067, 0x10400004, 0x0, 0x8ec200f8, 0x24420004, +0xaec200f8, 0x8fad006c, 0x8ec20068, 0xaecd00fc, 0x8fae003c, 0xaece0100, +0x8f430280, 0x24420001, 0x304203ff, 0x14620006, 0x0, 0x8ec202b8, +0x24420001, 0xaec202b8, 0x10000016, 0x8ec202b8, 0x8ec202b0, 0x24420001, +0xaec202b0, 0x10000011, 0x8ec202b0, 0x8fad006c, 0x31a4ffff, 0x2484fffc, +0x801821, 0x8ec401b8, 0x8ec501bc, 0x3c060001, 0x8cc63510, 0x1021, +0xa32821, 0xa3382b, 0x822021, 0x872021, 0xaec401b8, 0xc0f809, +0xaec501bc, 0x8fbf0088, 0x8fbe0084, 0x8fb50080, 0x8fb3007c, 0x8fb10078, +0x3e00008, 0x27bd0090, 0x3e00008, 0x0, 0x27bdff90, 0xafbf0068, +0xafbe0064, 0xafb50060, 0xafb3005c, 0xafb10058, 0x92c200ed, 0xafa0002c, +0x10400007, 0xa3a00037, 0x8ecf00fc, 0x8ec800f0, 0x8ec900f4, 0x8ed500f8, +0x100000d1, 0xafaf003c, 0x3c020001, 0x8c423518, 0x40f809, 0x27a40020, +0x104001ae, 0x0, 0x8fa30024, 0x8fb50020, 0x3068ffff, 0x92a20000, +0x2508fffc, 0x2a04821, 0x30420001, 0x1040001a, 0xafa3003c, 0x8ec2011c, +0x3c03ffff, 0x431024, 0x14400015, 0x2402ffff, 0x8ea30000, 0x14620005, +0x2a02021, 0x96a30004, 0x3402ffff, 0x1062000e, 0x0, 0xafa80048, +0xc0022ad, 0xafa9004c, 0x304200ff, 0x8fa80048, 0x14400007, 0x8fa9004c, +0x3c020001, 0x8c423510, 0x40f809, 0x0, 0x1000018c, 0x0, +0x8fa20024, 0x3c03ffbf, 0x3463ffff, 0x431024, 0x3c03ffff, 0x432824, +0x14a00003, 0xafa20024, 0x10000053, 0x1821, 0x3c020080, 0xa21024, +0x50400007, 0x3c040040, 0x8ec202e4, 0x24420001, 0xaec202e4, 0x8ec202e4, +0x10000049, 0x24030001, 0x3c070004, 0x3c0e0001, 0x3c0d0002, 0x3c060010, +0x3c0c0008, 0x8ec20178, 0x3c0b0020, 0x340a8000, 0x24420001, 0xaec20178, +0x8ec20178, 0x851824, 0x10670021, 0xe3102b, 0x14400007, 0x0, +0x106e0011, 0x0, 0x106d0015, 0x0, 0x10000030, 0x42042, +0x10660023, 0xc3102b, 0x14400005, 0x0, 0x106c0019, 0x0, +0x10000028, 0x42042, 0x106b0021, 0x0, 0x10000024, 0x42042, +0x8ec2012c, 0x24420001, 0xaec2012c, 0x8ec2012c, 0x1000001e, 0x42042, +0x8ec202d4, 0x24420001, 0xaec202d4, 0x8ec202d4, 0x10000018, 0x42042, +0x8ec202d8, 0x24420001, 0xaec202d8, 0x8ec202d8, 0x10000012, 0x42042, +0x8ec202dc, 0x24420001, 0xaec202dc, 0x8ec202dc, 0x1000000c, 0x42042, +0x8ec20128, 0x24420001, 0xaec20128, 0x8ec20128, 0x10000006, 0x42042, +0x8ec202e0, 0x24420001, 0xaec202e0, 0x8ec202e0, 0x42042, 0x148affc6, +0x851824, 0x24030001, 0x8f420260, 0x48102b, 0x10400019, 0x306400ff, +0x8f8200e0, 0xafa20010, 0x8f8200e4, 0x3c040001, 0x24842f5c, 0xafa20014, +0x8fa60020, 0x8fa70024, 0x3c050006, 0x34a5f003, 0xafa80048, 0xc00290f, +0xafa9004c, 0x8ec30150, 0x8faf003c, 0x3c020100, 0x24040001, 0x1e27825, +0x24630001, 0xafaf003c, 0xaec30150, 0x8ec20150, 0x8fa9004c, 0x8fa80048, +0x10800025, 0x0, 0x8f420218, 0x30420800, 0x14400021, 0x3c020180, +0x8faf003c, 0x1e21024, 0x104000fe, 0x1001821, 0x8ec20174, 0x24420001, +0xaec20174, 0x8ec20174, 0x100000f8, 0x1001821, 0x8ec2005c, 0xafa20010, +0x8ec20060, 0x3c040001, 0x24842f68, 0xafa20014, 0x8ec6003c, 0x8ec70044, +0x3c050006, 0x34a5f002, 0xafa80048, 0xc00290f, 0xafa9004c, 0x8ec202b4, +0x2403ffbf, 0x283a024, 0x24420001, 0xaec202b4, 0x8ec202b4, 0x8fa80048, +0x100000c2, 0x8fa9004c, 0x8f420218, 0x30420400, 0x54400001, 0x25080004, +0x96e20460, 0x48102b, 0x10400003, 0x0, 0x3c0f8000, 0xafaf002c, +0x110000d2, 0x3c02ffff, 0x8faf003c, 0x1e21024, 0xafa20044, 0x8ec20068, +0x8f430280, 0x24420001, 0x304203ff, 0x106200ad, 0x0, 0x8faf002c, +0x11e00014, 0x0, 0x8ec3005c, 0x8ec20060, 0x10620009, 0x26cb0060, +0x8ec60060, 0x8ec30060, 0x21140, 0x24424dc0, 0x2e28821, 0x24630001, +0x10000014, 0x306a00ff, 0x92c20064, 0x1440ffc4, 0x0, 0x8ec202c8, +0x24420001, 0xaec202c8, 0x8ec202c8, 0x8ec3003c, 0x8ec20044, 0x1062ffbc, +0x26cb0044, 0x8ec60044, 0xafa0002c, 0x8ec30044, 0x21140, 0x24420dc0, +0x2e28821, 0x24630001, 0x306a01ff, 0x96e20462, 0x30420010, 0x10400017, +0x0, 0x96a2000c, 0x340f8100, 0x144f0013, 0x0, 0x92c200ed, +0x14400010, 0x0, 0x96a2000e, 0xa6220016, 0x8ea20008, 0x8ea30004, +0x8ea40000, 0x2508fffc, 0xaea2000c, 0xaea30008, 0xaea40004, 0x9622000e, +0x25290004, 0x240f0001, 0xa3af0037, 0x34420200, 0xa622000e, 0x9623000a, +0x68102b, 0x14400002, 0x3073fff8, 0x1009821, 0x92c200ed, 0x14400012, +0x260f021, 0x9523000c, 0x24020800, 0x5462000f, 0xae290018, 0x91220017, +0x38430006, 0x2c630001, 0x38420011, 0x2c420001, 0x621825, 0x50600007, +0xae290018, 0x95220010, 0x2443000e, 0x73102b, 0x54400001, 0x60f021, +0xae290018, 0x92c300ed, 0x8e240000, 0x8e250004, 0x8faf002c, 0x2402000b, +0xafa20010, 0x3182b, 0x31ec0, 0xcf1025, 0x431025, 0xafa20014, +0x8ec20004, 0xafa20018, 0x8ec200a8, 0x3c03821, 0x1203021, 0xafa80048, +0xafa9004c, 0xafaa0050, 0x40f809, 0xafab0054, 0x8fa80048, 0x8fa9004c, +0x8faa0050, 0x8fab0054, 0x1440001d, 0x3c050006, 0x3c040001, 0x24842f80, +0x8e220018, 0x34a5f009, 0xafa20010, 0x8e220000, 0x8e230004, 0x2203021, +0x3c03821, 0xafa80048, 0xafa9004c, 0xc00290f, 0xafa30014, 0x93a20037, +0x8fa80048, 0x8fa9004c, 0x1040002a, 0x340f8100, 0x8ea20004, 0x8ea30008, +0x8ea4000c, 0xa6af000c, 0xaea20000, 0xaea30004, 0xaea40008, 0x96220016, +0x10000020, 0xa6a2000e, 0x8faf0044, 0x11e00007, 0x0, 0x8faf003c, +0x9623000e, 0xf1402, 0x34630400, 0xa6220014, 0xa623000e, 0x56680008, +0x1334821, 0x9622000e, 0xa628000a, 0x4021, 0x34420004, 0xa622000e, +0x1000000c, 0xa2c000ed, 0x3c03001f, 0x3463ffff, 0x24020001, 0x69182b, +0xa633000a, 0x10600003, 0xa2c200ed, 0x8ec20540, 0x1224823, 0x1134023, +0xafa0002c, 0x1500ff4f, 0xad6a0000, 0x1100001b, 0x0, 0xaec800f0, +0xaec900f4, 0xaed500f8, 0x93a20037, 0x10400004, 0x0, 0x8ec200f8, +0x24420004, 0xaec200f8, 0x8faf003c, 0x8ec20068, 0xaecf00fc, 0x8f430280, +0x24420001, 0x14620006, 0x0, 0x8ec202b8, 0x24420001, 0xaec202b8, +0x10000016, 0x8ec202b8, 0x8ec202b0, 0x24420001, 0xaec202b0, 0x10000011, +0x8ec202b0, 0x8faf003c, 0x31e4ffff, 0x2484fffc, 0x801821, 0x8ec401b8, +0x8ec501bc, 0x3c060001, 0x8cc63510, 0x1021, 0xa32821, 0xa3382b, +0x822021, 0x872021, 0xaec401b8, 0xc0f809, 0xaec501bc, 0x8fbf0068, +0x8fbe0064, 0x8fb50060, 0x8fb3005c, 0x8fb10058, 0x3e00008, 0x27bd0070, +0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024, 0xafb10020, 0x8ec30040, +0x8ec20038, 0x1062004d, 0x0, 0x8ec30038, 0x8ec20040, 0x623823, +0x4e20001, 0x24e70200, 0x8ec30044, 0x8ec20040, 0x43102b, 0x14400004, +0x24020200, 0x8ec30040, 0x10000005, 0x431823, 0x8ec20044, 0x8ec30040, +0x431023, 0x2443ffff, 0xe08821, 0x71102a, 0x54400001, 0x608821, +0x8ec90040, 0x8ee40458, 0x8ee5045c, 0x8ec60040, 0x113940, 0x24080002, +0xafa80010, 0x8ec80040, 0x94940, 0x1201821, 0x1021, 0xafa80014, +0x8ec80010, 0xa32821, 0xa3482b, 0x822021, 0x892021, 0x63140, +0xafa80018, 0x8ec200a4, 0x24c60dc0, 0x40f809, 0x2e63021, 0x1440000e, +0x24030040, 0x8ec20040, 0xafa20010, 0x8ec20044, 0x3c040001, 0x24842f98, +0xafa20014, 0x8ec60038, 0x8ec7003c, 0x3c050007, 0xc00290f, 0x34a5f001, +0x10000010, 0x0, 0x8ec20030, 0x24420001, 0x50430003, 0x1021, +0x8ec20030, 0x24420001, 0xaec20030, 0x8ec20030, 0x21080, 0x571021, +0xac510cc0, 0x8ec20040, 0x511021, 0x304201ff, 0xaec20040, 0x8ec30040, +0x8ec20038, 0x14620017, 0x0, 0x8ec20000, 0x10400007, 0x2403fdff, +0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 0x0, +0xaf800048, 0x8f820048, 0x1040fffd, 0x0, 0x8f820060, 0x431024, +0xaf820060, 0x8ec20000, 0x10400003, 0x0, 0x10000002, 0xaf80004c, +0xaf800048, 0x8fbf0024, 0x8fb10020, 0x3e00008, 0x27bd0028, 0x3e00008, +0x0, 0x27bdffd8, 0xafbf0024, 0xafb10020, 0x8ec30058, 0x8ec20054, +0x1062004d, 0x0, 0x8ec30054, 0x8ec20058, 0x623823, 0x4e20001, +0x24e70100, 0x8ec30060, 0x8ec20058, 0x43102b, 0x14400004, 0x24020100, +0x8ec30058, 0x10000005, 0x431823, 0x8ec20060, 0x8ec30058, 0x431023, +0x2443ffff, 0xe08821, 0x71102a, 0x54400001, 0x608821, 0x8ec90058, +0x8ee40468, 0x8ee5046c, 0x8ec60058, 0x113940, 0x24080003, 0xafa80010, +0x8ec80058, 0x94940, 0x1201821, 0x1021, 0xafa80014, 0x8ec80010, +0xa32821, 0xa3482b, 0x822021, 0x892021, 0x63140, 0xafa80018, +0x8ec200a4, 0x24c64dc0, 0x40f809, 0x2e63021, 0x1440000e, 0x24030040, +0x8ec20058, 0xafa20010, 0x8ec20060, 0x3c040001, 0x24842fa4, 0xafa20014, +0x8ec60054, 0x8ec7005c, 0x3c050007, 0xc00290f, 0x34a5f010, 0x10000010, +0x0, 0x8ec20030, 0x24420001, 0x50430003, 0x1021, 0x8ec20030, +0x24420001, 0xaec20030, 0x8ec20030, 0x21080, 0x571021, 0xac510cc0, +0x8ec20058, 0x511021, 0x304200ff, 0xaec20058, 0x8ec30058, 0x8ec20054, +0x14620017, 0x0, 0x8ec20000, 0x10400007, 0x2403feff, 0xaf80004c, +0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 0x0, 0xaf800048, +0x8f820048, 0x1040fffd, 0x0, 0x8f820060, 0x431024, 0xaf820060, +0x8ec20000, 0x10400003, 0x0, 0x10000002, 0xaf80004c, 0xaf800048, +0x8fbf0024, 0x8fb10020, 0x3e00008, 0x27bd0028, 0x3e00008, 0x0, +0x8f820120, 0x8ec300e8, 0x8f820124, 0x8f860128, 0x24020040, 0x24630001, +0x50620003, 0x1021, 0x8ec200e8, 0x24420001, 0xaec200e8, 0x8ec200e8, +0x8ec400e8, 0x8ec300e4, 0x210c0, 0x24426fc0, 0x14830007, 0x2e22821, +0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x10000011, 0xaca00000, +0x8ec200e8, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ec200e8, +0x24420001, 0x220c0, 0x2e41021, 0x8c426fc4, 0x8f830128, 0x21140, +0x621821, 0x2e41021, 0xaf830128, 0xac406fc0, 0x8cc20018, 0x2443fffe, +0x2c620018, 0x1040000a, 0x31080, 0x3c010001, 0x220821, 0x8c222fb0, +0x400008, 0x0, 0x24020001, 0x3c010001, 0x370821, 0xac2281e8, +0x3e00008, 0x0, 0x3e00008, 0x0, 0x27bdffa8, 0xafbf0050, +0xafbe004c, 0xafb50048, 0xafb30044, 0xafb10040, 0x8f830128, 0x8f820124, +0x106201e1, 0x0, 0x8f9e0128, 0x8f820128, 0x24420020, 0xaf820128, +0x8fc40018, 0x8f820128, 0x2402000b, 0x1482018f, 0x24020002, 0x8fc3001c, +0x97c20016, 0x3064ffff, 0xafc20014, 0x3c028000, 0x621024, 0xafc4001c, +0xafa2002c, 0x8fab002c, 0x3c020800, 0x11600004, 0x622824, 0x41140, +0x10000003, 0x24424dc0, 0x41140, 0x24420dc0, 0x2e2a821, 0x96a2000e, +0x3043fffc, 0x30420400, 0x10400003, 0xa6a3000e, 0x10000137, 0x8821, +0x10a00004, 0x8821, 0x97d10016, 0x10000132, 0x0, 0x8eab0018, +0xafab0034, 0x9563000c, 0x96eb0462, 0x24020800, 0x1462012b, 0xafab003c, +0x8fab0034, 0x2573000e, 0x8fab003c, 0x31620002, 0x1040003f, 0x3c030020, +0x8ec70540, 0x263102b, 0x14400002, 0x2604821, 0x2674823, 0x25220014, +0x43102b, 0x10400027, 0x24030005, 0x91220000, 0x3042000f, 0x14430024, +0x1202021, 0x952a0000, 0x25290002, 0x95280000, 0x25290002, 0x95270000, +0x25290002, 0x95260000, 0x25290002, 0x95250000, 0x25290002, 0x95230000, +0x25290002, 0x95220000, 0x25290002, 0x95240000, 0x25290002, 0x1485021, +0x1475021, 0x1465021, 0x1455021, 0x1435021, 0x1425021, 0x95220000, +0x95230002, 0x1445021, 0x1425021, 0x1435021, 0xa1c02, 0x3142ffff, +0x625021, 0xa1c02, 0x3142ffff, 0x10000009, 0x625021, 0x1202021, +0x90850000, 0x3c060020, 0x8ec200ac, 0x30a5000f, 0x40f809, 0x52840, +0x304affff, 0x3143ffff, 0x50600001, 0x3403ffff, 0x96a2000e, 0x34420002, +0x10000002, 0xa6a2000e, 0x1821, 0xa6a30010, 0x8fab003c, 0x31620001, +0x104000e1, 0x0, 0x92620009, 0x38430006, 0x2c630001, 0x38420011, +0x2c420001, 0x621825, 0x106000d9, 0x3c030020, 0x8fa60034, 0x8ec70540, +0xc3102b, 0x50400001, 0xc73023, 0x24c2000e, 0x43102b, 0x1040001a, +0xc02021, 0x94c70000, 0x24c60002, 0x94c50000, 0x24c60002, 0x94c30000, +0x24c60002, 0x94c20000, 0x24c60002, 0x94c40000, 0x24c60002, 0xe53821, +0xe33821, 0xe23821, 0x94c20000, 0x94c30002, 0xe43821, 0xe23821, +0xe33821, 0x71c02, 0x30e2ffff, 0x623821, 0x71c02, 0x30e2ffff, +0x10000006, 0x623821, 0x8ec200ac, 0x24050007, 0x40f809, 0x3c060020, +0x3047ffff, 0x8fab003c, 0x31620008, 0x10400003, 0x30e8ffff, 0x1000005b, +0x4821, 0x96620006, 0x30421fff, 0x10400007, 0x2602821, 0x92620000, +0x96630002, 0x3042000f, 0x21080, 0x10000051, 0x624823, 0x3c070020, +0x8ec30540, 0xa7102b, 0x50400001, 0xa32823, 0x24a20014, 0x47102b, +0x10400015, 0xa02021, 0x90a20000, 0x94a30002, 0x3042000f, 0x21080, +0x623023, 0xafa20020, 0x90a30009, 0x24a5000c, 0x94a20000, 0x24a50002, +0x94a40000, 0x24a50002, 0xc33021, 0xc23021, 0x94a20000, 0x94a30002, +0xc43021, 0xc23021, 0x1000002d, 0xc33021, 0x24a50002, 0xa7102b, +0x50400001, 0xa32823, 0x94a60000, 0x802821, 0xa7102b, 0x50400001, +0xa32823, 0x90a20000, 0x24850009, 0x3042000f, 0x21080, 0xc23023, +0xafa20020, 0xa7102b, 0x50400001, 0xa32823, 0x90a20000, 0x2485000c, +0xc23021, 0xa7102b, 0x50400001, 0xa32823, 0x94a20000, 0x24a50002, +0xc23021, 0xa7102b, 0x50400001, 0xa32823, 0x94a20000, 0x24a50002, +0xc23021, 0xa7102b, 0x50400001, 0xa32823, 0x94a20000, 0x24a50002, +0xc23021, 0xa7102b, 0x50400001, 0xa32823, 0x94a20000, 0xc23021, +0x61c02, 0x30c2ffff, 0x623021, 0x61402, 0x30c3ffff, 0x431021, +0x3049ffff, 0x96a2000e, 0x30420004, 0x10400041, 0x0, 0x8f420218, +0x30420400, 0x1040003d, 0x3c070020, 0x97c2000e, 0x8fc30008, 0x8ec60540, +0x621821, 0x2463fffc, 0x67102b, 0x50400001, 0x661823, 0x602821, +0x24a20004, 0x47102b, 0x5040000a, 0xa7102b, 0x90a20000, 0x90a40001, +0x90a30002, 0x21200, 0x441021, 0x90a40003, 0x31a00, 0x10000017, +0x431021, 0x50400001, 0xa62823, 0x90a20000, 0x24a50001, 0x22200, +0xa7102b, 0x50400001, 0xa62823, 0x90a20000, 0x24a50001, 0x822021, +0xa7102b, 0x50400001, 0xa62823, 0x90a20000, 0x24a50001, 0x21200, +0x822021, 0xa7102b, 0x50400001, 0xa62823, 0x90a20000, 0x822021, +0x41c02, 0x3082ffff, 0x622021, 0x41402, 0x3083ffff, 0x431021, +0x3042ffff, 0x1024021, 0x81c02, 0x3102ffff, 0x624021, 0x81c02, +0x3102ffff, 0x624021, 0x3108ffff, 0x8fc20014, 0x488823, 0x111402, +0x2228821, 0x2298821, 0x111402, 0x2228821, 0x3231ffff, 0x52200001, +0x3411ffff, 0x96a2000e, 0x34420001, 0xa6a2000e, 0x96a2000e, 0x24080002, +0x30420004, 0x10400002, 0xa6b10012, 0x24080004, 0x8ec90068, 0x8ee40478, +0x8ee5047c, 0xafa80010, 0x8ec80068, 0x8fab002c, 0x2a03021, 0x24070020, +0x10b4025, 0xafa80014, 0x8ec80008, 0x94940, 0x1201821, 0xafa80018, +0x8ec800a8, 0x1021, 0xa32821, 0xa3482b, 0x822021, 0x100f809, +0x892021, 0x1440000e, 0x0, 0x8f820120, 0xafa20010, 0x8f820128, +0x3c040001, 0x24843010, 0xafa20014, 0x8fc6001c, 0x8f870124, 0x3c050008, +0xc00290f, 0x34a50001, 0x1000005f, 0x0, 0x8ec20068, 0x24420001, +0x304203ff, 0xaec20068, 0x8fab002c, 0x11600006, 0x0, 0x8ec202c0, +0x2442ffff, 0xaec202c0, 0x10000005, 0x8ec202c0, 0x8ec202bc, 0x2442ffff, +0xaec202bc, 0x8ec202bc, 0x8ec202c4, 0x2442ffff, 0xaec202c4, 0x1000004a, +0x8ec202c4, 0x14820005, 0x24020004, 0x8ec20048, 0x24420001, 0x10000044, +0xaec20048, 0x14820036, 0x38830011, 0x97c2001e, 0xafc2001c, 0x8ec20048, +0x24420001, 0xaec20048, 0x8f430240, 0x43102b, 0x14400039, 0x24070008, +0x8ed10068, 0x8ee40490, 0x8ee50494, 0x8ec30008, 0x8f860120, 0x24020013, +0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, +0x1440000b, 0x24020001, 0x3c040001, 0x24842f0c, 0xafb10010, 0xafa00014, +0x8ec60068, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f008, 0x1021, +0x14400005, 0x24020001, 0x3c010001, 0x370821, 0x1000000a, 0xac2281e0, +0x3c010001, 0x370821, 0xac2081e0, 0x8ec20268, 0xaec00048, 0xaed1006c, +0x24420001, 0xaec20268, 0x8ec20268, 0x8ec2027c, 0x24420001, 0xaec2027c, +0x1000000d, 0x8ec2027c, 0x2c630001, 0x38820013, 0x2c420001, 0x621825, +0x14600004, 0x24020001, 0x24020012, 0x14820004, 0x24020001, 0x3c010001, +0x370821, 0xac2281e8, 0x8fbf0050, 0x8fbe004c, 0x8fb50048, 0x8fb30044, +0x8fb10040, 0x3e00008, 0x27bd0058, 0x3e00008, 0x0, 0x0, +0x0, 0x0, 0x8ec20538, 0xaf8200c0, 0x8ec20538, 0xaf8200c4, +0x8ec20538, 0xaf8200c8, 0x8ec20534, 0xaf8200d0, 0x8ec20534, 0xaf8200d4, +0x8ec20534, 0x3e00008, 0xaf8200d8, 0x27bdffe8, 0x27840208, 0x27450200, +0xafbf0010, 0xc0029a2, 0x24060008, 0x8f420204, 0xc003c86, 0xaf820210, +0x24040001, 0x8f460248, 0x24020004, 0x3c010001, 0xac22340c, 0xc0046cc, +0x24050004, 0x3c020001, 0x8c423408, 0x30420001, 0x10400007, 0x24020001, +0x3c010001, 0xac22340c, 0x24040001, 0x24050001, 0xc0046cc, 0x3c06601b, +0x8ec20548, 0x8ec4054c, 0x8ec30550, 0x3c010001, 0xac203404, 0x3c010001, +0xac20341c, 0x21640, 0x42140, 0x34840403, 0x441025, 0x31bc0, +0x431025, 0xaf82021c, 0x8fbf0010, 0x3e00008, 0x27bd0018, 0x27bdffe0, +0x3c050008, 0x34a50400, 0xafbf0018, 0xafa00010, 0xafa00014, 0x8f860200, +0x3c040001, 0x248430dc, 0xc00290f, 0x3821, 0x8ec20368, 0x24420001, +0xaec20368, 0x8ec20368, 0x8f830200, 0x3c023f00, 0x621824, 0x8fbf0018, +0x3c020400, 0x3e00008, 0x27bd0020, 0x27bdffd8, 0xafbf0020, 0xafb3001c, +0xafb10018, 0x8f910220, 0x8ec202fc, 0x24420001, 0xaec202fc, 0x8ec202fc, +0x8ec30310, 0x3c020001, 0x8c42341c, 0x3c040001, 0x248430e8, 0xafa20014, +0xafa30010, 0x8ec70314, 0x3c050008, 0xc00290f, 0x2203021, 0x3c024000, +0x2221024, 0x104000e5, 0x3c040100, 0x8ec20314, 0x24420001, 0xaec20314, +0x8ec20314, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420004, +0xaf820220, 0x8f8200e0, 0x8f8300c4, 0x3c02001f, 0x3442ffff, 0x24690008, +0x49102b, 0x10400003, 0x0, 0x8ec20540, 0x1224823, 0x8f8700c8, +0x8f850120, 0x8f840124, 0x10000005, 0x5821, 0x8ec20534, 0x82102b, +0x50400001, 0x27644800, 0x10a40010, 0x316200ff, 0x8c820018, 0x38430007, +0x2c630001, 0x3842000b, 0x2c420001, 0x621825, 0x5060fff3, 0x24840020, +0x8ec20328, 0x240b0001, 0x24420001, 0xaec20328, 0x8ec20328, 0x8c870008, +0x316200ff, 0x14400078, 0x0, 0x92c200ed, 0x14400075, 0x0, +0x8f8500e4, 0x8f8200e0, 0x2403fff8, 0x433024, 0xc51023, 0x218c3, +0x4620001, 0x24630100, 0x8f8a00c4, 0x10600005, 0x24020001, 0x10620009, +0x0, 0x10000021, 0x0, 0x8ec20318, 0x1403821, 0x24420001, +0xaec20318, 0x10000060, 0x8ec20318, 0x8ec2031c, 0x24420001, 0xaec2031c, +0x8ca70000, 0x8ec20540, 0x8ec3031c, 0x1471823, 0x43102b, 0x10400004, +0x2c62233f, 0x8ec20540, 0x621821, 0x2c62233f, 0x14400051, 0x3c020100, +0xaca20004, 0x8f8200e8, 0x24420008, 0xaf8200e8, 0x8f8200e8, 0x8f8200e4, +0x1403821, 0x24420008, 0xaf8200e4, 0x10000046, 0x8f8200e4, 0x8ec20320, +0x24420001, 0xaec20320, 0x8ca80000, 0x8ec20540, 0x8ec30320, 0x1092023, 0x44102b, 0x10400003, 0x0, 0x8ec20540, 0x822021, 0x8ec20544, -0x82102b, 0x10400006, 0x316200ff, 0x1440001c, 0x3c02fdff, 0x92c200ed, -0x14400019, 0x3c02fdff, 0xaf8700c8, 0x8f8400c8, 0x8f8300c4, 0x8ec20540, -0x832023, 0x44102b, 0x10400003, 0x0, 0x8ec20540, 0x822021, -0x8ec20544, 0x2c830001, 0x44102b, 0x431025, 0x10400009, 0x3c02fdff, -0x8f820220, 0x3c0308ff, 0x3463fffb, 0x431024, 0x3c034000, 0x431025, -0x10000075, 0xaf820220, 0x3442ffff, 0x8ec30324, 0x282a024, 0x24020001, -0xa2c200ec, 0x24630001, 0xaec30324, 0x1000006c, 0x8ec20324, 0x2241024, -0x10400013, 0x3c130200, 0x8ec20300, 0x24420001, 0xaec20300, 0x8ec20300, -0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x441025, 0xaf820220, -0x3c020004, 0x2221024, 0x14400005, 0x3c130200, 0xc003a65, 0x0, -0x10000057, 0x0, 0x2331024, 0x50400008, 0x3c130400, 0x8ec20304, -0x24420001, 0xaec20304, 0xc003a65, 0x8ec20304, 0x10000019, 0x0, -0x2331024, 0x1040001d, 0x3c020800, 0x8f830224, 0x24021402, 0x14620009, -0x3c050008, 0x3c040001, 0x24842f94, 0xafa00010, 0xafa00014, 0x8f860224, -0x34a5ffff, 0xc0028eb, 0x3821, 0x8ec20308, 0x24420001, 0xaec20308, -0x8ec20308, 0x8f820220, 0x2202021, 0x34420002, 0xc004430, 0xaf820220, -0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x531025, 0x1000002e, -0xaf820220, 0x2221024, 0x10400009, 0x3c050008, 0x3c040001, 0x24842f7c, -0xafa00010, 0xafa00014, 0x8f860220, 0x34a50403, 0xc0028eb, 0x3821, -0x3c021000, 0x2221024, 0x10400009, 0x3c050008, 0x3c040001, 0x24842f7c, -0xafa00010, 0xafa00014, 0x8f860220, 0x34a50401, 0xc0028eb, 0x3821, -0x3c022000, 0x2221024, 0x10400009, 0x3c050008, 0x3c040001, 0x24842f7c, -0xafa00010, 0xafa00014, 0x8f860220, 0x34a50402, 0xc0028eb, 0x3821, -0x6210009, 0x3c050008, 0x3c040001, 0x24842f7c, 0xafa00010, 0xafa00014, -0x8f860220, 0x34a50404, 0xc0028eb, 0x3821, 0x8fbf0020, 0x8fb3001c, -0x8fb10018, 0x3e00008, 0x27bd0028, 0x3e00008, 0x0, 0x3c020001, -0x8c4232bc, 0x27bdffc0, 0xafbf0038, 0xafbe0034, 0xafb50030, 0xafb3002c, -0x1040000f, 0xafb10028, 0x3c040001, 0x24842fa0, 0x3c050008, 0xafa00010, -0xafa00014, 0x8f860220, 0x34a50498, 0x24020001, 0x3c010001, 0xac2032bc, -0x3c010001, 0xac2232b0, 0xc0028eb, 0x3821, 0x3c037fff, 0x8f420268, -0x3463ffff, 0x3c04fdff, 0x431024, 0xaf420268, 0x8ee204a8, 0x3484ffff, -0x30420002, 0x10400091, 0x284a024, 0x3c040600, 0x8ee204a8, 0x34842000, -0x2403fffd, 0x431024, 0xaee204a8, 0xafa40020, 0x8ec3002c, 0x240200ff, -0x10620004, 0x27a70020, 0x8ec2002c, 0x10000002, 0x24530001, 0x9821, -0x8f420228, 0x1662000f, 0x0, 0x3c040001, 0x24842f58, 0xafa00010, -0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f00f, -0x8ec202a0, 0x24420001, 0xaec202a0, 0x1000006d, 0x8ec202a0, 0x8ec2002c, -0x210c0, 0x571021, 0x8ce30000, 0x8ce40004, 0xac4304c0, 0xac4404c4, -0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 0x1040001e, -0xa821, 0x241e000c, 0x8ec8002c, 0x8ee40428, 0x8ee5042c, 0x8ec6002c, -0x24070008, 0xafbe0010, 0xafb30014, 0x840c0, 0x1001821, 0x1021, -0x8ec80008, 0xa32821, 0xa3482b, 0x822021, 0x892021, 0x630c0, -0xafa80018, 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 0x54400006, -0x24150001, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffe5, 0x0, -0x32a200ff, 0x54400011, 0xaed3002c, 0x3c040001, 0x24842f64, 0xafa00010, -0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0x10000030, 0x34a5f010, -0x8ec2026c, 0x24150001, 0x24420001, 0xaec2026c, 0x8ec2026c, 0x1000001f, -0x32a200ff, 0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, -0x10400017, 0xa821, 0x3c1e0020, 0x24130011, 0x8ec20008, 0x8ee40488, -0x8ee5048c, 0x8ec3002c, 0x8f860120, 0xafb30010, 0x5e1025, 0xafa30014, -0xafa20018, 0x8ec200a8, 0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe2, -0x0, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffed, 0x0, -0x32a200ff, 0x1440000f, 0x0, 0x3c040001, 0x24842f70, 0xafa00010, -0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f011, 0xc0028eb, -0x0, 0x8ec202d0, 0x24420001, 0xaec202d0, 0x8ec202d0, 0x8ec20250, -0x24420001, 0xaec20250, 0x8ec20250, 0x8fbf0038, 0x8fbe0034, 0x8fb50030, -0x8fb3002c, 0x8fb10028, 0x3e00008, 0x27bd0040, 0x3c020001, 0x8c4232bc, -0x27bdffe0, 0x1440000d, 0xafbf0018, 0x3c040001, 0x24842fac, 0x3c050008, -0xafa00010, 0xafa00014, 0x8f860220, 0x34a50499, 0x24020001, 0x3c010001, -0xac2232bc, 0xc0028eb, 0x3821, 0x92c2011d, 0x10400008, 0x24040001, -0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420008, 0xaf820220, -0x24040001, 0xc004785, 0x24050004, 0xaf420268, 0x8fbf0018, 0x3e00008, -0x27bd0020, 0x0, 0x86102b, 0x50400001, 0x872023, 0xc41023, -0x24843, 0x125102b, 0x1040001b, 0x91040, 0x824021, 0x88102b, -0x10400007, 0x1821, 0x94820000, 0x24840002, 0x621821, 0x88102b, -0x1440fffb, 0x0, 0x602021, 0xc73023, 0xa91023, 0x21040, -0xc22821, 0xc5102b, 0x10400007, 0x1821, 0x94c20000, 0x24c60002, -0x621821, 0xc5102b, 0x1440fffb, 0x0, 0x1000000d, 0x832021, -0x51040, 0x822821, 0x85102b, 0x10400007, 0x1821, 0x94820000, -0x24840002, 0x621821, 0x85102b, 0x1440fffb, 0x0, 0x602021, -0x41c02, 0x3082ffff, 0x622021, 0x41c02, 0x3082ffff, 0x622021, -0x3e00008, 0x3082ffff, 0x3e00008, 0x0, 0x8f820220, 0x34420002, -0xaf820220, 0x3c020001, 0x8c4254b8, 0x30424000, 0x10400054, 0x24040001, -0x8f820200, 0x24067fff, 0x8f830200, 0x30450002, 0x2402fffd, 0x621824, -0xaf830200, 0xaf840204, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, -0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820224, -0x1444004d, 0x42040, 0xc4102b, 0x1040fff1, 0x0, 0x8f820200, -0x451025, 0xaf820200, 0x8f820220, 0x34428000, 0xaf820220, 0x8f830054, -0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, -0x1440fffc, 0x0, 0x8f820220, 0x3c030004, 0x431024, 0x1440000f, -0x0, 0x8f820220, 0x3c03ffff, 0x34637fff, 0x431024, 0xaf820220, +0x44102b, 0x10400003, 0x3c030100, 0x10000034, 0x1003821, 0x8ca20004, +0x431025, 0xaca20004, 0x8f8200e4, 0x24450008, 0xaf8500e4, 0x8f8500e4, +0x10a60025, 0x3c080100, 0x8ec20174, 0x24420001, 0xaec20174, 0x8ca20004, +0x8ec30174, 0x481024, 0x1440000e, 0x0, 0x8ca30000, 0x8ec20540, +0x692023, 0x44102b, 0x10400003, 0x0, 0x8ec20540, 0x822021, +0x8ec20544, 0x44102b, 0x10400006, 0x0, 0x603821, 0x8ec20544, +0x44102b, 0x1440000a, 0x0, 0x8ca20004, 0x481025, 0xaca20004, +0x8f8200e4, 0x24450008, 0xaf8500e4, 0x8f8500e4, 0x14a6ffdf, 0x0, +0x14a60005, 0x0, 0x1403821, 0xaf8600e4, 0x10000003, 0xaf8600e8, +0xaf8500e4, 0xaf8500e8, 0x8f8300c8, 0x8ec20540, 0x692023, 0x44102b, +0x10400003, 0x0, 0x8ec20540, 0x822021, 0x8ec20544, 0x82102b, +0x50400008, 0x5821, 0x8ec20540, 0xe92023, 0x44102b, 0x10400003, +0x0, 0x8ec20540, 0x822021, 0x8ec20544, 0x82102b, 0x10400006, +0x316200ff, 0x1440001c, 0x3c02fdff, 0x92c200ed, 0x14400019, 0x3c02fdff, +0xaf8700c8, 0x8f8400c8, 0x8f8300c4, 0x8ec20540, 0x832023, 0x44102b, +0x10400003, 0x0, 0x8ec20540, 0x822021, 0x8ec20544, 0x2c830001, +0x44102b, 0x431025, 0x10400009, 0x3c02fdff, 0x8f820220, 0x3c0308ff, +0x3463fffb, 0x431024, 0x3c034000, 0x431025, 0x10000075, 0xaf820220, +0x3442ffff, 0x8ec30324, 0x282a024, 0x24020001, 0xa2c200ec, 0x24630001, +0xaec30324, 0x1000006c, 0x8ec20324, 0x2241024, 0x10400013, 0x3c130200, +0x8ec20300, 0x24420001, 0xaec20300, 0x8ec20300, 0x8f820220, 0x3c0308ff, +0x3463ffff, 0x431024, 0x441025, 0xaf820220, 0x3c020004, 0x2221024, +0x14400005, 0x3c130200, 0xc003ab1, 0x0, 0x10000057, 0x0, +0x2331024, 0x50400008, 0x3c130400, 0x8ec20304, 0x24420001, 0xaec20304, +0xc003ab1, 0x8ec20304, 0x10000019, 0x0, 0x2331024, 0x1040001d, +0x3c020800, 0x8f830224, 0x24021402, 0x14620009, 0x3c050008, 0x3c040001, +0x248430f4, 0xafa00010, 0xafa00014, 0x8f860224, 0x34a5ffff, 0xc00290f, +0x3821, 0x8ec20308, 0x24420001, 0xaec20308, 0x8ec20308, 0x8f820220, +0x2202021, 0x34420002, 0xc00447c, 0xaf820220, 0x8f820220, 0x3c0308ff, +0x3463ffff, 0x431024, 0x531025, 0x1000002e, 0xaf820220, 0x2221024, +0x10400009, 0x3c050008, 0x3c040001, 0x248430dc, 0xafa00010, 0xafa00014, +0x8f860220, 0x34a50403, 0xc00290f, 0x3821, 0x3c021000, 0x2221024, +0x10400009, 0x3c050008, 0x3c040001, 0x248430dc, 0xafa00010, 0xafa00014, +0x8f860220, 0x34a50401, 0xc00290f, 0x3821, 0x3c022000, 0x2221024, +0x10400009, 0x3c050008, 0x3c040001, 0x248430dc, 0xafa00010, 0xafa00014, +0x8f860220, 0x34a50402, 0xc00290f, 0x3821, 0x6210009, 0x3c050008, +0x3c040001, 0x248430dc, 0xafa00010, 0xafa00014, 0x8f860220, 0x34a50404, +0xc00290f, 0x3821, 0x8fbf0020, 0x8fb3001c, 0x8fb10018, 0x3e00008, +0x27bd0028, 0x3e00008, 0x0, 0x3c020001, 0x8c42341c, 0x27bdffc0, +0xafbf0038, 0xafbe0034, 0xafb50030, 0xafb3002c, 0x1040000f, 0xafb10028, +0x3c040001, 0x24843100, 0x3c050008, 0xafa00010, 0xafa00014, 0x8f860220, +0x34a50498, 0x24020001, 0x3c010001, 0xac20341c, 0x3c010001, 0xac223410, +0xc00290f, 0x3821, 0x3c037fff, 0x8f420268, 0x3463ffff, 0x3c04fdff, +0x431024, 0xaf420268, 0x8ee204a8, 0x3484ffff, 0x30420002, 0x10400091, +0x284a024, 0x3c040600, 0x8ee204a8, 0x34842000, 0x2403fffd, 0x431024, +0xaee204a8, 0xafa40020, 0x8ec3002c, 0x240200ff, 0x10620004, 0x27a70020, +0x8ec2002c, 0x10000002, 0x24530001, 0x9821, 0x8f420228, 0x1662000f, +0x0, 0x3c040001, 0x248430b8, 0xafa00010, 0xafa00014, 0x8ec6002c, +0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f00f, 0x8ec202a0, 0x24420001, +0xaec202a0, 0x1000006d, 0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021, +0x8ce30000, 0x8ce40004, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, +0x247103e8, 0x2221023, 0x2c4203e9, 0x1040001e, 0xa821, 0x241e000c, +0x8ec8002c, 0x8ee40428, 0x8ee5042c, 0x8ec6002c, 0x24070008, 0xafbe0010, +0xafb30014, 0x840c0, 0x1001821, 0x1021, 0x8ec80008, 0xa32821, +0xa3482b, 0x822021, 0x892021, 0x630c0, 0xafa80018, 0x8ec200a8, +0x24c604c0, 0x40f809, 0x2e63021, 0x54400006, 0x24150001, 0x8f820054, +0x2221023, 0x2c4203e9, 0x1440ffe5, 0x0, 0x32a200ff, 0x54400011, +0xaed3002c, 0x3c040001, 0x248430c4, 0xafa00010, 0xafa00014, 0x8f860120, +0x8f870124, 0x3c050009, 0x10000030, 0x34a5f010, 0x8ec2026c, 0x24150001, +0x24420001, 0xaec2026c, 0x8ec2026c, 0x1000001f, 0x32a200ff, 0x8f830054, +0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 0x10400017, 0xa821, +0x3c1e0020, 0x24130011, 0x8ec20008, 0x8ee40488, 0x8ee5048c, 0x8ec3002c, +0x8f860120, 0xafb30010, 0x5e1025, 0xafa30014, 0xafa20018, 0x8ec200a8, +0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe2, 0x0, 0x8f820054, +0x2221023, 0x2c4203e9, 0x1440ffed, 0x0, 0x32a200ff, 0x1440000f, +0x0, 0x3c040001, 0x248430d0, 0xafa00010, 0xafa00014, 0x8f860120, +0x8f870124, 0x3c050009, 0x34a5f011, 0xc00290f, 0x0, 0x8ec202d0, +0x24420001, 0xaec202d0, 0x8ec202d0, 0x8ec20250, 0x24420001, 0xaec20250, +0x8ec20250, 0x8fbf0038, 0x8fbe0034, 0x8fb50030, 0x8fb3002c, 0x8fb10028, +0x3e00008, 0x27bd0040, 0x3c020001, 0x8c42341c, 0x27bdffe0, 0x1440000d, +0xafbf0018, 0x3c040001, 0x2484310c, 0x3c050008, 0xafa00010, 0xafa00014, +0x8f860220, 0x34a50499, 0x24020001, 0x3c010001, 0xac22341c, 0xc00290f, +0x3821, 0x92c2011d, 0x10400008, 0x24040001, 0x8f820220, 0x3c0308ff, +0x3463ffff, 0x431024, 0x34420008, 0xaf820220, 0x24040001, 0xc0047d1, +0x24050004, 0xaf420268, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0, +0x86102b, 0x50400001, 0x872023, 0xc41023, 0x24843, 0x125102b, +0x1040001b, 0x91040, 0x824021, 0x88102b, 0x10400007, 0x1821, +0x94820000, 0x24840002, 0x621821, 0x88102b, 0x1440fffb, 0x0, +0x602021, 0xc73023, 0xa91023, 0x21040, 0xc22821, 0xc5102b, +0x10400007, 0x1821, 0x94c20000, 0x24c60002, 0x621821, 0xc5102b, +0x1440fffb, 0x0, 0x1000000d, 0x832021, 0x51040, 0x822821, +0x85102b, 0x10400007, 0x1821, 0x94820000, 0x24840002, 0x621821, +0x85102b, 0x1440fffb, 0x0, 0x602021, 0x41c02, 0x3082ffff, +0x622021, 0x41c02, 0x3082ffff, 0x622021, 0x3e00008, 0x3082ffff, +0x3e00008, 0x0, 0x8f820220, 0x34420002, 0xaf820220, 0x3c020001, +0x8c425618, 0x30424000, 0x10400054, 0x24040001, 0x8f820200, 0x24067fff, +0x8f830200, 0x30450002, 0x2402fffd, 0x621824, 0xaf830200, 0xaf840204, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, -0x2c420002, 0x1440fffc, 0x0, 0x8f820220, 0x3c030004, 0x431024, -0x1440000d, 0x0, 0x8f820220, 0x34428000, 0xaf820220, 0x8f830054, -0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, -0x1440fffc, 0x0, 0x8f820220, 0x3c030004, 0x431024, 0x1040001b, -0x1021, 0x8f830220, 0x24020001, 0x10000015, 0x3c04f700, 0x8f820220, -0x3c04f700, 0x441025, 0xaf820220, 0x8f820220, 0x2403fffd, 0x431024, -0xaf820220, 0x8f820220, 0x3c030300, 0x431024, 0x14400003, 0x0, -0x10000008, 0x1021, 0x8f820220, 0x34420002, 0xaf820220, 0x8f830220, -0x24020001, 0x641825, 0xaf830220, 0x3e00008, 0x0, 0x2021, -0x3c050100, 0x24020001, 0xaf80021c, 0xaf820200, 0xaf820220, 0x27625000, -0xaf8200c0, 0x27625000, 0xaf8200c4, 0x27625000, 0xaf8200c8, 0x27625000, -0xaf8200d0, 0x27625000, 0xaf8200d4, 0x27625000, 0xaf8200d8, 0x27623000, -0xaf8200e0, 0x27623000, 0xaf8200e4, 0x27623000, 0xaf8200e8, 0x27622800, -0xaf8200f0, 0x27622800, 0xaf8200f4, 0x27622800, 0xaf8200f8, 0x418c0, -0x24840001, 0x3631021, 0xac453004, 0x3631021, 0xac403000, 0x28820200, -0x1440fff9, 0x418c0, 0x2021, 0x418c0, 0x24840001, 0x3631021, -0xac402804, 0x3631021, 0xac402800, 0x28820100, 0x1440fff9, 0x418c0, -0xaf80023c, 0x24030080, 0x24040100, 0xac600000, 0x24630004, 0x64102b, -0x5440fffd, 0xac600000, 0x8f830040, 0x3c02f000, 0x621824, 0x3c025000, -0x1062000c, 0x43102b, 0x14400006, 0x3c026000, 0x3c024000, 0x10620008, -0x24020800, 0x10000008, 0x0, 0x10620004, 0x24020800, 0x10000004, -0x0, 0x24020700, 0x3c010001, 0xac2232c0, 0x3e00008, 0x0, -0x27bdffc8, 0xafbf0034, 0xafb50030, 0xafb3002c, 0xafb10028, 0x3c010001, -0xc00440d, 0xac2032a8, 0x24040001, 0x2821, 0x27a60020, 0x34028000, -0xc00402a, 0xa7a20020, 0x8f830054, 0x8f820054, 0x10000002, 0x24630064, -0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050001, -0xc003fe8, 0x27a60020, 0x8f830054, 0x8f820054, 0x10000002, 0x24630064, -0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050001, -0xc003fe8, 0x27a60020, 0x8f830054, 0x8f820054, 0x10000002, 0x24630064, -0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050002, -0xc003fe8, 0x27a60018, 0x8f830054, 0x8f820054, 0x10000002, 0x24630064, -0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050003, -0xc003fe8, 0x27a6001a, 0x97a20020, 0x10400024, 0x24020001, 0x3c020001, -0x8c4232a8, 0x97a30018, 0x34420001, 0x3c010001, 0xac2232a8, 0x24020015, -0x14620004, 0x3402f423, 0x97a3001a, 0x10620018, 0x24020003, 0x97a30018, -0x24027810, 0x14620014, 0x24020002, 0x97a3001a, 0x24020001, 0x14620010, -0x24020002, 0x1000000e, 0x24020004, 0x3c020001, 0x8c4232a8, 0x34420008, -0x3c010001, 0xac2232a8, 0x10000058, 0x24020004, 0x3c020001, 0x8c4232a8, -0x34420004, 0x3c010001, 0x100000a8, 0xac2232a8, 0x3c010001, 0xac2233dc, -0x24020e00, 0xaf820238, 0x8f840054, 0x8f820054, 0x24030008, 0x3c010001, -0xac2332ac, 0x10000002, 0x248401f4, 0x8f820054, 0x821023, 0x2c4201f5, -0x1440fffc, 0x3c0200c8, 0x344201fb, 0xaf820238, 0x8f830054, 0x8f820054, +0x2c420002, 0x1440fffc, 0x0, 0x8f820224, 0x1444004d, 0x42040, +0xc4102b, 0x1040fff1, 0x0, 0x8f820200, 0x451025, 0xaf820200, +0x8f820220, 0x34428000, 0xaf820220, 0x8f830054, 0x8f820054, 0x10000002, +0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, +0x8f820220, 0x3c030004, 0x431024, 0x1440000f, 0x0, 0x8f820220, +0x3c03ffff, 0x34637fff, 0x431024, 0xaf820220, 0x8f830054, 0x8f820054, +0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, +0x0, 0x8f820220, 0x3c030004, 0x431024, 0x1440000d, 0x0, +0x8f820220, 0x34428000, 0xaf820220, 0x8f830054, 0x8f820054, 0x10000002, +0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, +0x8f820220, 0x3c030004, 0x431024, 0x1040001b, 0x1021, 0x8f830220, +0x24020001, 0x10000015, 0x3c04f700, 0x8f820220, 0x3c04f700, 0x441025, +0xaf820220, 0x8f820220, 0x2403fffd, 0x431024, 0xaf820220, 0x8f820220, +0x3c030300, 0x431024, 0x14400003, 0x0, 0x10000008, 0x1021, +0x8f820220, 0x34420002, 0xaf820220, 0x8f830220, 0x24020001, 0x641825, +0xaf830220, 0x3e00008, 0x0, 0x2021, 0x3c050100, 0x24020001, +0xaf80021c, 0xaf820200, 0xaf820220, 0x27625000, 0xaf8200c0, 0x27625000, +0xaf8200c4, 0x27625000, 0xaf8200c8, 0x27625000, 0xaf8200d0, 0x27625000, +0xaf8200d4, 0x27625000, 0xaf8200d8, 0x27623000, 0xaf8200e0, 0x27623000, +0xaf8200e4, 0x27623000, 0xaf8200e8, 0x27622800, 0xaf8200f0, 0x27622800, +0xaf8200f4, 0x27622800, 0xaf8200f8, 0x418c0, 0x24840001, 0x3631021, +0xac453004, 0x3631021, 0xac403000, 0x28820200, 0x1440fff9, 0x418c0, +0x2021, 0x418c0, 0x24840001, 0x3631021, 0xac402804, 0x3631021, +0xac402800, 0x28820100, 0x1440fff9, 0x418c0, 0xaf80023c, 0x24030080, +0x24040100, 0xac600000, 0x24630004, 0x64102b, 0x5440fffd, 0xac600000, +0x8f830040, 0x3c02f000, 0x621824, 0x3c025000, 0x1062000c, 0x43102b, +0x14400006, 0x3c026000, 0x3c024000, 0x10620008, 0x24020800, 0x10000008, +0x0, 0x10620004, 0x24020800, 0x10000004, 0x0, 0x24020700, +0x3c010001, 0xac223420, 0x3e00008, 0x0, 0x27bdffc8, 0xafbf0034, +0xafb50030, 0xafb3002c, 0xafb10028, 0x3c010001, 0xc004459, 0xac203408, +0x24040001, 0x2821, 0x27a60020, 0x34028000, 0xc004076, 0xa7a20020, +0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 0x621023, +0x2c420065, 0x1440fffc, 0x24040001, 0x24050001, 0xc004034, 0x27a60020, +0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 0x621023, +0x2c420065, 0x1440fffc, 0x24040001, 0x24050001, 0xc004034, 0x27a60020, +0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 0x621023, +0x2c420065, 0x1440fffc, 0x24040001, 0x24050002, 0xc004034, 0x27a60018, +0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 0x621023, +0x2c420065, 0x1440fffc, 0x24040001, 0x24050003, 0xc004034, 0x27a6001a, +0x97a20020, 0x10400024, 0x24020001, 0x3c020001, 0x8c423408, 0x97a30018, +0x34420001, 0x3c010001, 0xac223408, 0x24020015, 0x14620004, 0x3402f423, +0x97a3001a, 0x10620018, 0x24020003, 0x97a30018, 0x24027810, 0x14620014, +0x24020002, 0x97a3001a, 0x24020001, 0x14620010, 0x24020002, 0x1000000e, +0x24020004, 0x3c020001, 0x8c423408, 0x34420008, 0x3c010001, 0xac223408, +0x10000058, 0x24020004, 0x3c020001, 0x8c423408, 0x34420004, 0x3c010001, +0x100000a8, 0xac223408, 0x3c010001, 0xac22353c, 0x24020e00, 0xaf820238, +0x8f840054, 0x8f820054, 0x24030008, 0x3c010001, 0xac23340c, 0x10000002, +0x248401f4, 0x8f820054, 0x821023, 0x2c4201f5, 0x1440fffc, 0x3c0200c8, +0x344201fb, 0xaf820238, 0x8f830054, 0x8f820054, 0x10000002, 0x246301f4, +0x8f820054, 0x621023, 0x2c4201f5, 0x1440fffc, 0x8821, 0x3c1300c8, +0x367301f6, 0x2415fffd, 0xc003f77, 0x0, 0x8f830054, 0x8f820054, 0x10000002, 0x246301f4, 0x8f820054, 0x621023, 0x2c4201f5, 0x1440fffc, -0x8821, 0x3c1300c8, 0x367301f6, 0x2415fffd, 0xc003f2b, 0x0, -0x8f830054, 0x8f820054, 0x10000002, 0x246301f4, 0x8f820054, 0x621023, -0x2c4201f5, 0x1440fffc, 0x0, 0xaf930238, 0x8f830054, 0x8f820054, -0x10000002, 0x2463000a, 0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc, -0x0, 0x8f820220, 0x34420002, 0xaf820220, 0x8f820200, 0x24040001, -0x24057fff, 0x551024, 0xaf820200, 0xaf840204, 0x8f830054, 0x8f820054, +0x0, 0xaf930238, 0x8f830054, 0x8f820054, 0x10000002, 0x2463000a, +0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc, 0x0, 0x8f820220, +0x34420002, 0xaf820220, 0x8f820200, 0x24040001, 0x24057fff, 0x551024, +0xaf820200, 0xaf840204, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, +0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820224, +0x14440005, 0x34028000, 0x42040, 0xa4102b, 0x1040fff0, 0x34028000, +0x1082ffa6, 0x26310001, 0x2e220014, 0x1440ffce, 0x24020004, 0x3c010001, +0xac22340c, 0x8821, 0x3c13ffff, 0x36733f7f, 0xc003f77, 0x0, +0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, +0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x531024, 0x34425080, +0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 0x2463000a, 0x8f820054, +0x621023, 0x2c42000b, 0x1440fffc, 0x0, 0x8f820044, 0x531024, +0x3442f080, 0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 0x2463000a, +0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc, 0x0, 0x8f820220, +0x3c03f700, 0x431025, 0xaf820220, 0x8f830054, 0x8f820054, 0x10000002, +0x24630064, 0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x0, +0x8f820220, 0x24040001, 0x34420002, 0xaf820220, 0x8f830200, 0x24057fff, +0x2402fffd, 0x621824, 0xaf830200, 0xaf840204, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820224, 0x14440005, 0x34028000, 0x42040, 0xa4102b, -0x1040fff0, 0x34028000, 0x1082ffa6, 0x26310001, 0x2e220014, 0x1440ffce, -0x24020004, 0x3c010001, 0xac2232ac, 0x8821, 0x3c13ffff, 0x36733f7f, -0xc003f2b, 0x0, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, -0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820044, -0x531024, 0x34425080, 0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, -0x2463000a, 0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc, 0x0, -0x8f820044, 0x531024, 0x3442f080, 0xaf820044, 0x8f830054, 0x8f820054, -0x10000002, 0x2463000a, 0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc, -0x0, 0x8f820220, 0x3c03f700, 0x431025, 0xaf820220, 0x8f830054, -0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 0x621023, 0x2c420065, -0x1440fffc, 0x0, 0x8f820220, 0x24040001, 0x34420002, 0xaf820220, -0x8f830200, 0x24057fff, 0x2402fffd, 0x621824, 0xaf830200, 0xaf840204, -0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, -0x2c420002, 0x1440fffc, 0x0, 0x8f820224, 0x14440005, 0x34028000, -0x42040, 0xa4102b, 0x1040fff0, 0x34028000, 0x1082ff57, 0x26310001, -0x2e220064, 0x1440ffb0, 0x0, 0x3c020001, 0x8c4232a8, 0x30420004, -0x14400007, 0x3c08fff0, 0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024, -0xaf820044, 0x3c08fff0, 0x3508bdc0, 0x8f830054, 0x97a60018, 0x3c070001, -0x8ce733dc, 0x3c040001, 0x24843080, 0x24020001, 0x3c010001, 0xac2232b0, -0xafa60010, 0x3c060001, 0x8cc632a8, 0x97a2001a, 0x3c05000d, 0x34a50100, -0x3c010001, 0xac2032ac, 0x681821, 0x3c010001, 0xac2333d4, 0xc0028eb, -0xafa20014, 0x8fbf0034, 0x8fb50030, 0x8fb3002c, 0x8fb10028, 0x3e00008, -0x27bd0038, 0x27bdffe8, 0x24070004, 0x3c040001, 0x8c8432ac, 0x3021, -0x24020001, 0x1482000a, 0xafbf0010, 0x3c020001, 0x8c4254bc, 0x3c050004, -0x30428000, 0x1040000c, 0x34a593e0, 0x3c05000f, 0x10000009, 0x34a54240, -0x3c020001, 0x8c4254bc, 0x3c05000f, 0x30428000, 0x10400003, 0x34a54240, -0x3c05001e, 0x34a58480, 0x3c020001, 0x8c4233d4, 0x8f830054, 0x451021, -0x431023, 0x45102b, 0x1440002e, 0x0, 0x3c020001, 0x8c4232b4, -0x1440002a, 0x2cc20001, 0x7182b, 0x431024, 0x1040001d, 0x0, -0x3c090001, 0x8d2932a8, 0x240b0001, 0x3c054000, 0x3c080001, 0x250854bc, -0x250afffc, 0x42042, 0x14800002, 0x24e7ffff, 0x24040008, 0x891024, -0x5040000b, 0x2cc20001, 0x148b0004, 0x0, 0x8d020000, 0x10000003, -0x451024, 0x8d420000, 0x451024, 0x54400001, 0x24060001, 0x2cc20001, -0x7182b, 0x431024, 0x5440ffed, 0x42042, 0x3c010001, 0x10c00020, -0xac2432ac, 0x8f830054, 0x24020001, 0x3c010001, 0xac2232b0, 0x3c010001, -0xac2333d4, 0x3c020001, 0x8c4232b0, 0x10400004, 0x24020001, 0x3c010001, -0xac2032b0, 0xaee279c8, 0x8ee379c8, 0x24020008, 0x10620005, 0x24020001, -0xc003dd7, 0x0, 0x1000000b, 0x0, 0x3c030001, 0x8c6332ac, -0x10620007, 0x2402000e, 0x3c030001, 0x8c635430, 0x10620003, 0x0, -0xc004430, 0x8f840220, 0x8fbf0010, 0x3e00008, 0x27bd0018, 0x27bdffe0, -0x3c03fdff, 0x3c040001, 0x8c8432ac, 0x3c020001, 0x8c4232c4, 0x3463ffff, -0x283a024, 0x14820006, 0xafbf0018, 0x8ee379c8, 0x3c020001, 0x8c4232c8, -0x10620006, 0x0, 0x8ee279c8, 0x3c010001, 0xac2432c4, 0x3c010001, -0xac2232c8, 0x3c030001, 0x8c6332ac, 0x24020002, 0x10620139, 0x2c620003, -0x10400005, 0x24020001, 0x1062000a, 0x0, 0x10000131, 0x0, -0x24020004, 0x10620070, 0x24020008, 0x106200ac, 0x24020001, 0x1000012a, -0x0, 0x8ee279c8, 0x2443ffff, 0x2c620008, 0x10400127, 0x31080, -0x3c010001, 0x220821, 0x8c223098, 0x400008, 0x0, 0xc003f2b, -0x0, 0x3c020001, 0x8c4232b8, 0x3c010001, 0xac203240, 0x104000e8, -0x24020002, 0xaee279c8, 0x3c010001, 0x10000116, 0xac2032b8, 0xc00406b, -0x0, 0x3c030001, 0x8c6332d0, 0x24020011, 0x1462010f, 0x24020003, -0x100000aa, 0x0, 0x3c050001, 0x8ca532ac, 0x3c060001, 0x8cc654bc, -0xc004680, 0x24040001, 0x24020005, 0x3c010001, 0xac2032b8, 0x10000102, -0xaee279c8, 0x3c040001, 0x2484308c, 0x3c05000f, 0x34a50100, 0x3021, -0x3821, 0xafa00010, 0xc0028eb, 0xafa00014, 0x100000f7, 0x0, -0x8f820220, 0x3c03f700, 0x431025, 0x100000ae, 0xaf820220, 0x8f820220, -0x3c030004, 0x431024, 0x144000bc, 0x24020007, 0x8f830054, 0x3c020001, -0x8c4233d0, 0x2463d8f0, 0x431023, 0x2c422710, 0x144000e5, 0x24020001, -0x100000e1, 0x0, 0x3c050001, 0x8ca532ac, 0xc004785, 0x24040001, -0xc00484d, 0x24040001, 0x3c030001, 0x8c6354b4, 0x46100d7, 0x24020001, -0x3c020008, 0x621024, 0x10400006, 0x0, 0x8f820214, 0x3c03ffff, -0x431024, 0x10000005, 0x3442251f, 0x8f820214, 0x3c03ffff, 0x431024, -0x3442241f, 0xaf820214, 0x8f820220, 0x3c030200, 0x283a025, 0x34420002, -0xaf820220, 0x24020008, 0xc003b1e, 0xaee279c8, 0x100000c1, 0x0, -0x8ee279c8, 0x2443ffff, 0x2c620008, 0x104000bc, 0x31080, 0x3c010001, -0x220821, 0x8c2230b8, 0x400008, 0x0, 0xc003a65, 0x0, -0x3c010001, 0xac2032b0, 0xaf800204, 0x3c010001, 0xc003f2b, 0xac205480, -0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024, 0x34425080, 0xaf820044, -0x8f830054, 0x3c010001, 0xac203240, 0x10000062, 0x24020002, 0x3c020001, -0x8c4254b8, 0x30424000, 0x10400004, 0x0, 0x8f820044, 0x10000006, -0x3442f080, 0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024, 0x3442a080, -0xaf820044, 0x8f830054, 0x10000051, 0x24020004, 0xc003b78, 0x0, -0x1040008d, 0x24020001, 0x8f820214, 0x3c03ffff, 0x3c040001, 0x8c8433c8, -0x431024, 0x3442251f, 0xaf820214, 0x24020008, 0x14800067, 0xaee279c8, -0x1000006c, 0x0, 0x8ee279c8, 0x2443ffff, 0x2c620007, 0x1040007e, -0x31080, 0x3c010001, 0x220821, 0x8c2230d8, 0x400008, 0x0, -0xc003a65, 0x0, 0x3c010001, 0xac2032b0, 0xaf800204, 0x3c010001, -0xc003f2b, 0xac205480, 0x8f830054, 0x3c010001, 0xac203240, 0x1000002a, -0x24020002, 0x8f830054, 0x3c020001, 0x8c4233d0, 0x2463d8f0, 0x431023, -0x2c422710, 0x14400064, 0x24020003, 0x10000062, 0xaee279c8, 0x3c020001, -0x8c4254b8, 0x30424000, 0x10400003, 0x3c0200c8, 0x10000002, 0x344201f6, -0x344201fe, 0xaf820238, 0x8f830054, 0x10000014, 0x24020004, 0x8f830054, -0x3c020001, 0x8c4233d0, 0x2463d8f0, 0x431023, 0x2c422710, 0x1440004e, -0x24020005, 0x1000004c, 0xaee279c8, 0x8f820220, 0x3c03f700, 0x431025, -0xaf820220, 0xaf800204, 0x3c010001, 0xac205480, 0x8f830054, 0x24020006, -0xaee279c8, 0x3c010001, 0x1000003f, 0xac2333d0, 0x3c05fffe, 0x34a57960, -0x3c040001, 0x8f820054, 0x3c030001, 0x8c6333d0, 0x3484869f, 0x451021, -0x621823, 0x83202b, 0x10800033, 0x0, 0x24020007, 0x10000030, -0xaee279c8, 0xc003b78, 0x0, 0x1040002a, 0x24020001, 0x8f820214, -0x3c03ffff, 0x3c040001, 0x8c8433c8, 0x431024, 0x3442251f, 0xaf820214, -0x24020008, 0x1080000b, 0xaee279c8, 0x8f820220, 0x34420002, 0xaf820220, -0x24020001, 0x3c010001, 0xac225430, 0xc004430, 0x8f840220, 0x10000018, -0x0, 0x8f820220, 0x3c030008, 0x431024, 0x14400013, 0x3c020200, -0x282a025, 0x2402000e, 0x3c010001, 0xac225430, 0xc00484d, 0x24040001, -0x8f820220, 0x34420002, 0xc003b1e, 0xaf820220, 0x3c050001, 0x8ca532ac, -0xc004785, 0x24040001, 0x10000003, 0x0, 0x3c010001, 0xac2232b0, -0x8fbf0018, 0x3e00008, 0x27bd0020, 0x8f820200, 0x8f820220, 0x8f820220, -0x34420004, 0xaf820220, 0x8f820200, 0x3c040001, 0x8c8432ac, 0x34420004, -0xaf820200, 0x24020002, 0x1082003a, 0x2c820003, 0x10400005, 0x24020001, -0x1082000a, 0x3c03f0ff, 0x100000a8, 0x0, 0x24020004, 0x10820055, -0x24020008, 0x10820074, 0x3c02f0ff, 0x100000a1, 0x0, 0x8f820050, -0x3463ffff, 0x3c05ffff, 0x34a53f7f, 0x431024, 0x3c030700, 0x431025, -0xaf820050, 0x24020e00, 0xaf840200, 0xaf840220, 0xaf820238, 0x8f820044, -0x3c030001, 0x8c633298, 0x3c040001, 0x8c8433dc, 0x451024, 0x34630022, -0xaf820044, 0x24020004, 0x1082000c, 0xaf830200, 0x3c020001, 0x8c4232c0, -0x3c030001, 0x8c6332a4, 0x3c040001, 0x8c84329c, 0x34428000, 0x621825, -0x641825, 0x1000007e, 0x34620002, 0x3c020001, 0x8c4232a4, 0x3c030001, -0x8c6332c0, 0x3c040001, 0x8c84329c, 0x431025, 0x441025, 0x10000074, -0x34420002, 0x8f830050, 0x3c02f0ff, 0x3442ffff, 0x3c040001, 0x8c8433c8, -0x621824, 0x3c020d00, 0x621825, 0x24020001, 0xaf830050, 0xaf820200, -0xaf820220, 0x24020e00, 0xaf820238, 0x10800005, 0x3c033f00, 0x3c020001, -0x8c423290, 0x10000004, 0x34630070, 0x3c020001, 0x8c423290, 0x34630072, -0x431025, 0xaf820200, 0x3c030001, 0x8c633294, 0x3c04f700, 0x3c020001, -0x8c4232a4, 0x3c050001, 0x8ca532c0, 0x641825, 0x431025, 0x10000050, -0x451025, 0x3c03f0ff, 0x8f820050, 0x3463ffff, 0x3c04ffff, 0x431024, -0x3c030a00, 0x431025, 0xaf820050, 0x24020001, 0xaf820200, 0xaf820220, -0x24020e01, 0xaf820238, 0x8f820044, 0x34843f7f, 0x3c030001, 0x8c6333c8, -0x441024, 0x34420080, 0xaf820044, 0x10600005, 0x3c033f00, 0x3c020001, -0x8c423290, 0x10000004, 0x346300e0, 0x3c020001, 0x8c423290, 0x346300e2, -0x431025, 0xaf820200, 0x10000025, 0x3c05f700, 0x8f830050, 0x3c040001, -0x8c8433c8, 0x3442ffff, 0x621824, 0xaf830050, 0x10800013, 0x3c0500c8, -0x34a501fb, 0x3c063f00, 0x3c030001, 0x8c6332a0, 0x3c040001, 0x8c843290, -0x34c600e0, 0x24020001, 0xaf820200, 0xaf820220, 0xaf850238, 0x24630001, -0x862025, 0x3c010001, 0xac2332a0, 0xaf840200, 0x1000000b, 0x3c05f700, -0x3c0200c8, 0x344201fb, 0x3c030001, 0x8c633290, 0x3c043f00, 0x348400e2, -0xaf820238, 0x641825, 0xaf830200, 0x3c05f700, 0x34a58000, 0x3c030001, -0x8c633294, 0x3c020001, 0x8c4232a4, 0x3c040001, 0x8c8432c0, 0x651825, -0x431025, 0x441025, 0xaf820220, 0x3e00008, 0x0, 0x0, -0x27bdffd8, 0xafb50018, 0x80a821, 0xafbe001c, 0xa0f021, 0xafb30014, -0xc09821, 0xafb10010, 0x8821, 0xafbf0020, 0xa6600000, 0xc0043e7, -0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc0043e7, -0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, 0x24040001, 0xc0043e7, -0x2021, 0x24110010, 0x2b11024, 0x10400002, 0x2021, 0x24040001, -0xc0043e7, 0x118842, 0x1620fffa, 0x2b11024, 0x24110010, 0x3d11024, -0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, -0x3d11024, 0xc00440d, 0x34118000, 0xc00440d, 0x0, 0xc0043c7, -0x0, 0x50400005, 0x118842, 0x96620000, 0x511025, 0xa6620000, -0x118842, 0x1620fff7, 0x0, 0xc00440d, 0x0, 0x8fbf0020, -0x8fbe001c, 0x8fb50018, 0x8fb30014, 0x8fb10010, 0x3e00008, 0x27bd0028, -0x27bdffd8, 0xafb30014, 0x809821, 0xafb50018, 0xa0a821, 0xafbe001c, -0xc0f021, 0xafb10010, 0x8821, 0xafbf0020, 0xc0043e7, 0x24040001, -0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc0043e7, 0x2021, -0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, -0x24110010, 0x2711024, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, -0x118842, 0x1620fffa, 0x2711024, 0x24110010, 0x2b11024, 0x10400002, -0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x2b11024, -0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0x34118000, 0x97c20000, -0x511024, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, -0x1620fff8, 0x0, 0xc00440d, 0x0, 0x8fbf0020, 0x8fbe001c, -0x8fb50018, 0x8fb30014, 0x8fb10010, 0x3e00008, 0x27bd0028, 0x3c030001, -0x8c6332d0, 0x3c020001, 0x8c423314, 0x27bdffd8, 0xafbf0020, 0xafb3001c, -0x10620003, 0xafb10018, 0x3c010001, 0xac233314, 0x2463ffff, 0x2c620013, -0x10400349, 0x31080, 0x3c010001, 0x220821, 0x8c223100, 0x400008, -0x0, 0xc00440d, 0x8821, 0x34028000, 0xa7a20010, 0x27b30010, -0xc0043e7, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, -0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, -0xc0043e7, 0x24040001, 0x24110010, 0x32220001, 0x10400002, 0x2021, -0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, -0xc0043e7, 0x2021, 0x118842, 0x1620fffc, 0x0, 0xc0043e7, -0x24040001, 0xc0043e7, 0x2021, 0x34118000, 0x96620000, 0x511024, -0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fff8, -0x0, 0xc00440d, 0x0, 0x1000030e, 0x24020002, 0x27b30010, -0xa7a00010, 0x8821, 0xc0043e7, 0x24040001, 0x26310001, 0x2e220020, -0x1440fffb, 0x0, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, -0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0x24110010, 0x32220001, -0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, -0x32220001, 0x24110010, 0xc0043e7, 0x2021, 0x118842, 0x1620fffc, -0x0, 0xc00440d, 0x34118000, 0xc00440d, 0x0, 0xc0043c7, -0x0, 0x50400005, 0x118842, 0x96620000, 0x511025, 0xa6620000, -0x118842, 0x1620fff7, 0x0, 0xc00440d, 0x0, 0x97a20010, -0x30428000, 0x144002dc, 0x24020003, 0x100002d8, 0x0, 0x24021200, -0xa7a20010, 0x27b30010, 0x8821, 0xc0043e7, 0x24040001, 0x26310001, -0x2e220020, 0x1440fffb, 0x0, 0xc0043e7, 0x2021, 0xc0043e7, -0x24040001, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0x24110010, -0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, -0x1620fffa, 0x32220001, 0x24110010, 0xc0043e7, 0x2021, 0x118842, -0x1620fffc, 0x0, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, -0x34118000, 0x96620000, 0x511024, 0x10400002, 0x2021, 0x24040001, -0xc0043e7, 0x118842, 0x1620fff8, 0x0, 0xc00440d, 0x0, -0x8f830054, 0x10000296, 0x24020004, 0x8f830054, 0x3c020001, 0x8c4233d8, -0x2463ff9c, 0x431023, 0x2c420064, 0x1440029e, 0x24020002, 0x3c030001, -0x8c6333dc, 0x10620297, 0x2c620003, 0x14400296, 0x24020011, 0x24020003, -0x10620005, 0x24020004, 0x10620291, 0x2402000f, 0x1000028f, 0x24020011, -0x1000028d, 0x24020005, 0x24020014, 0xa7a20010, 0x27b30010, 0x8821, -0xc0043e7, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, -0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, -0xc0043e7, 0x24040001, 0x24110010, 0x32220001, 0x10400002, 0x2021, -0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, -0x32220012, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, -0x1620fffa, 0x32220012, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, -0x34118000, 0x96620000, 0x511024, 0x10400002, 0x2021, 0x24040001, -0xc0043e7, 0x118842, 0x1620fff8, 0x0, 0xc00440d, 0x0, -0x8f830054, 0x10000248, 0x24020006, 0x8f830054, 0x3c020001, 0x8c4233d8, -0x2463ff9c, 0x431023, 0x2c420064, 0x14400250, 0x24020007, 0x1000024c, -0x0, 0x24020006, 0xa7a20010, 0x27b30010, 0x8821, 0xc0043e7, -0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc0043e7, -0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0xc0043e7, +0x1040fff0, 0x34028000, 0x1082ff57, 0x26310001, 0x2e220064, 0x1440ffb0, +0x0, 0x3c020001, 0x8c423408, 0x30420004, 0x14400007, 0x3c08fff0, +0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024, 0xaf820044, 0x3c08fff0, +0x3508bdc0, 0x8f830054, 0x97a60018, 0x3c070001, 0x8ce7353c, 0x3c040001, +0x248431e0, 0x24020001, 0x3c010001, 0xac223410, 0xafa60010, 0x3c060001, +0x8cc63408, 0x97a2001a, 0x3c05000d, 0x34a50100, 0x3c010001, 0xac20340c, +0x681821, 0x3c010001, 0xac233534, 0xc00290f, 0xafa20014, 0x8fbf0034, +0x8fb50030, 0x8fb3002c, 0x8fb10028, 0x3e00008, 0x27bd0038, 0x27bdffe8, +0x24070004, 0x3c040001, 0x8c84340c, 0x3021, 0x24020001, 0x1482000a, +0xafbf0010, 0x3c020001, 0x8c42561c, 0x3c050004, 0x30428000, 0x1040000c, +0x34a593e0, 0x3c05000f, 0x10000009, 0x34a54240, 0x3c020001, 0x8c42561c, +0x3c05000f, 0x30428000, 0x10400003, 0x34a54240, 0x3c05001e, 0x34a58480, +0x3c020001, 0x8c423534, 0x8f830054, 0x451021, 0x431023, 0x45102b, +0x1440002e, 0x0, 0x3c020001, 0x8c423414, 0x1440002a, 0x2cc20001, +0x7182b, 0x431024, 0x1040001d, 0x0, 0x3c090001, 0x8d293408, +0x240b0001, 0x3c054000, 0x3c080001, 0x2508561c, 0x250afffc, 0x42042, +0x14800002, 0x24e7ffff, 0x24040008, 0x891024, 0x5040000b, 0x2cc20001, +0x148b0004, 0x0, 0x8d020000, 0x10000003, 0x451024, 0x8d420000, +0x451024, 0x54400001, 0x24060001, 0x2cc20001, 0x7182b, 0x431024, +0x5440ffed, 0x42042, 0x3c010001, 0x10c00020, 0xac24340c, 0x8f830054, +0x24020001, 0x3c010001, 0xac223410, 0x3c010001, 0xac233534, 0x3c020001, +0x8c423410, 0x10400004, 0x24020001, 0x3c010001, 0xac203410, 0xaee279c8, +0x8ee379c8, 0x24020008, 0x10620005, 0x24020001, 0xc003e23, 0x0, +0x1000000b, 0x0, 0x3c030001, 0x8c63340c, 0x10620007, 0x2402000e, +0x3c030001, 0x8c635590, 0x10620003, 0x0, 0xc00447c, 0x8f840220, +0x8fbf0010, 0x3e00008, 0x27bd0018, 0x27bdffe0, 0x3c03fdff, 0x3c040001, +0x8c84340c, 0x3c020001, 0x8c423424, 0x3463ffff, 0x283a024, 0x14820006, +0xafbf0018, 0x8ee379c8, 0x3c020001, 0x8c423428, 0x10620006, 0x0, +0x8ee279c8, 0x3c010001, 0xac243424, 0x3c010001, 0xac223428, 0x3c030001, +0x8c63340c, 0x24020002, 0x10620139, 0x2c620003, 0x10400005, 0x24020001, +0x1062000a, 0x0, 0x10000131, 0x0, 0x24020004, 0x10620070, +0x24020008, 0x106200ac, 0x24020001, 0x1000012a, 0x0, 0x8ee279c8, +0x2443ffff, 0x2c620008, 0x10400127, 0x31080, 0x3c010001, 0x220821, +0x8c2231f8, 0x400008, 0x0, 0xc003f77, 0x0, 0x3c020001, +0x8c423418, 0x3c010001, 0xac2033a0, 0x104000e8, 0x24020002, 0xaee279c8, +0x3c010001, 0x10000116, 0xac203418, 0xc0040b7, 0x0, 0x3c030001, +0x8c633430, 0x24020011, 0x1462010f, 0x24020003, 0x100000aa, 0x0, +0x3c050001, 0x8ca5340c, 0x3c060001, 0x8cc6561c, 0xc0046cc, 0x24040001, +0x24020005, 0x3c010001, 0xac203418, 0x10000102, 0xaee279c8, 0x3c040001, +0x248431ec, 0x3c05000f, 0x34a50100, 0x3021, 0x3821, 0xafa00010, +0xc00290f, 0xafa00014, 0x100000f7, 0x0, 0x8f820220, 0x3c03f700, +0x431025, 0x100000ae, 0xaf820220, 0x8f820220, 0x3c030004, 0x431024, +0x144000bc, 0x24020007, 0x8f830054, 0x3c020001, 0x8c423530, 0x2463d8f0, +0x431023, 0x2c422710, 0x144000e5, 0x24020001, 0x100000e1, 0x0, +0x3c050001, 0x8ca5340c, 0xc0047d1, 0x24040001, 0xc004899, 0x24040001, +0x3c030001, 0x8c635614, 0x46100d7, 0x24020001, 0x3c020008, 0x621024, +0x10400006, 0x0, 0x8f820214, 0x3c03ffff, 0x431024, 0x10000005, +0x3442251f, 0x8f820214, 0x3c03ffff, 0x431024, 0x3442241f, 0xaf820214, +0x8f820220, 0x3c030200, 0x283a025, 0x34420002, 0xaf820220, 0x24020008, +0xc003b6a, 0xaee279c8, 0x100000c1, 0x0, 0x8ee279c8, 0x2443ffff, +0x2c620008, 0x104000bc, 0x31080, 0x3c010001, 0x220821, 0x8c223218, +0x400008, 0x0, 0xc003ab1, 0x0, 0x3c010001, 0xac203410, +0xaf800204, 0x3c010001, 0xc003f77, 0xac2055e0, 0x8f820044, 0x3c03ffff, +0x34633f7f, 0x431024, 0x34425080, 0xaf820044, 0x8f830054, 0x3c010001, +0xac2033a0, 0x10000062, 0x24020002, 0x3c020001, 0x8c425618, 0x30424000, +0x10400004, 0x0, 0x8f820044, 0x10000006, 0x3442f080, 0x8f820044, +0x3c03ffff, 0x34633f7f, 0x431024, 0x3442a080, 0xaf820044, 0x8f830054, +0x10000051, 0x24020004, 0xc003bc4, 0x0, 0x1040008d, 0x24020001, +0x8f820214, 0x3c03ffff, 0x3c040001, 0x8c843528, 0x431024, 0x3442251f, +0xaf820214, 0x24020008, 0x14800067, 0xaee279c8, 0x1000006c, 0x0, +0x8ee279c8, 0x2443ffff, 0x2c620007, 0x1040007e, 0x31080, 0x3c010001, +0x220821, 0x8c223238, 0x400008, 0x0, 0xc003ab1, 0x0, +0x3c010001, 0xac203410, 0xaf800204, 0x3c010001, 0xc003f77, 0xac2055e0, +0x8f830054, 0x3c010001, 0xac2033a0, 0x1000002a, 0x24020002, 0x8f830054, +0x3c020001, 0x8c423530, 0x2463d8f0, 0x431023, 0x2c422710, 0x14400064, +0x24020003, 0x10000062, 0xaee279c8, 0x3c020001, 0x8c425618, 0x30424000, +0x10400003, 0x3c0200c8, 0x10000002, 0x344201f6, 0x344201fe, 0xaf820238, +0x8f830054, 0x10000014, 0x24020004, 0x8f830054, 0x3c020001, 0x8c423530, +0x2463d8f0, 0x431023, 0x2c422710, 0x1440004e, 0x24020005, 0x1000004c, +0xaee279c8, 0x8f820220, 0x3c03f700, 0x431025, 0xaf820220, 0xaf800204, +0x3c010001, 0xac2055e0, 0x8f830054, 0x24020006, 0xaee279c8, 0x3c010001, +0x1000003f, 0xac233530, 0x3c05fffe, 0x34a57960, 0x3c040001, 0x8f820054, +0x3c030001, 0x8c633530, 0x3484869f, 0x451021, 0x621823, 0x83202b, +0x10800033, 0x0, 0x24020007, 0x10000030, 0xaee279c8, 0xc003bc4, +0x0, 0x1040002a, 0x24020001, 0x8f820214, 0x3c03ffff, 0x3c040001, +0x8c843528, 0x431024, 0x3442251f, 0xaf820214, 0x24020008, 0x1080000b, +0xaee279c8, 0x8f820220, 0x34420002, 0xaf820220, 0x24020001, 0x3c010001, +0xac225590, 0xc00447c, 0x8f840220, 0x10000018, 0x0, 0x8f820220, +0x3c030008, 0x431024, 0x14400013, 0x3c020200, 0x282a025, 0x2402000e, +0x3c010001, 0xac225590, 0xc004899, 0x24040001, 0x8f820220, 0x34420002, +0xc003b6a, 0xaf820220, 0x3c050001, 0x8ca5340c, 0xc0047d1, 0x24040001, +0x10000003, 0x0, 0x3c010001, 0xac223410, 0x8fbf0018, 0x3e00008, +0x27bd0020, 0x8f820200, 0x8f820220, 0x8f820220, 0x34420004, 0xaf820220, +0x8f820200, 0x3c040001, 0x8c84340c, 0x34420004, 0xaf820200, 0x24020002, +0x1082003a, 0x2c820003, 0x10400005, 0x24020001, 0x1082000a, 0x3c03f0ff, +0x100000a8, 0x0, 0x24020004, 0x10820055, 0x24020008, 0x10820074, +0x3c02f0ff, 0x100000a1, 0x0, 0x8f820050, 0x3463ffff, 0x3c05ffff, +0x34a53f7f, 0x431024, 0x3c030700, 0x431025, 0xaf820050, 0x24020e00, +0xaf840200, 0xaf840220, 0xaf820238, 0x8f820044, 0x3c030001, 0x8c6333f8, +0x3c040001, 0x8c84353c, 0x451024, 0x34630022, 0xaf820044, 0x24020004, +0x1082000c, 0xaf830200, 0x3c020001, 0x8c423420, 0x3c030001, 0x8c633404, +0x3c040001, 0x8c8433fc, 0x34428000, 0x621825, 0x641825, 0x1000007e, +0x34620002, 0x3c020001, 0x8c423404, 0x3c030001, 0x8c633420, 0x3c040001, +0x8c8433fc, 0x431025, 0x441025, 0x10000074, 0x34420002, 0x8f830050, +0x3c02f0ff, 0x3442ffff, 0x3c040001, 0x8c843528, 0x621824, 0x3c020d00, +0x621825, 0x24020001, 0xaf830050, 0xaf820200, 0xaf820220, 0x24020e00, +0xaf820238, 0x10800005, 0x3c033f00, 0x3c020001, 0x8c4233f0, 0x10000004, +0x34630070, 0x3c020001, 0x8c4233f0, 0x34630072, 0x431025, 0xaf820200, +0x3c030001, 0x8c6333f4, 0x3c04f700, 0x3c020001, 0x8c423404, 0x3c050001, +0x8ca53420, 0x641825, 0x431025, 0x10000050, 0x451025, 0x3c03f0ff, +0x8f820050, 0x3463ffff, 0x3c04ffff, 0x431024, 0x3c030a00, 0x431025, +0xaf820050, 0x24020001, 0xaf820200, 0xaf820220, 0x24020e01, 0xaf820238, +0x8f820044, 0x34843f7f, 0x3c030001, 0x8c633528, 0x441024, 0x34420080, +0xaf820044, 0x10600005, 0x3c033f00, 0x3c020001, 0x8c4233f0, 0x10000004, +0x346300e0, 0x3c020001, 0x8c4233f0, 0x346300e2, 0x431025, 0xaf820200, +0x10000025, 0x3c05f700, 0x8f830050, 0x3c040001, 0x8c843528, 0x3442ffff, +0x621824, 0xaf830050, 0x10800013, 0x3c0500c8, 0x34a501fb, 0x3c063f00, +0x3c030001, 0x8c633400, 0x3c040001, 0x8c8433f0, 0x34c600e0, 0x24020001, +0xaf820200, 0xaf820220, 0xaf850238, 0x24630001, 0x862025, 0x3c010001, +0xac233400, 0xaf840200, 0x1000000b, 0x3c05f700, 0x3c0200c8, 0x344201fb, +0x3c030001, 0x8c6333f0, 0x3c043f00, 0x348400e2, 0xaf820238, 0x641825, +0xaf830200, 0x3c05f700, 0x34a58000, 0x3c030001, 0x8c6333f4, 0x3c020001, +0x8c423404, 0x3c040001, 0x8c843420, 0x651825, 0x431025, 0x441025, +0xaf820220, 0x3e00008, 0x0, 0x0, 0x27bdffd8, 0xafb50018, +0x80a821, 0xafbe001c, 0xa0f021, 0xafb30014, 0xc09821, 0xafb10010, +0x8821, 0xafbf0020, 0xa6600000, 0xc004433, 0x24040001, 0x26310001, +0x2e220020, 0x1440fffb, 0x0, 0xc004433, 0x2021, 0xc004433, +0x24040001, 0xc004433, 0x24040001, 0xc004433, 0x2021, 0x24110010, +0x2b11024, 0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, +0x1620fffa, 0x2b11024, 0x24110010, 0x3d11024, 0x10400002, 0x2021, +0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x3d11024, 0xc004459, +0x34118000, 0xc004459, 0x0, 0xc004413, 0x0, 0x50400005, +0x118842, 0x96620000, 0x511025, 0xa6620000, 0x118842, 0x1620fff7, +0x0, 0xc004459, 0x0, 0x8fbf0020, 0x8fbe001c, 0x8fb50018, +0x8fb30014, 0x8fb10010, 0x3e00008, 0x27bd0028, 0x27bdffd8, 0xafb30014, +0x809821, 0xafb50018, 0xa0a821, 0xafbe001c, 0xc0f021, 0xafb10010, +0x8821, 0xafbf0020, 0xc004433, 0x24040001, 0x26310001, 0x2e220020, +0x1440fffb, 0x0, 0xc004433, 0x2021, 0xc004433, 0x24040001, +0xc004433, 0x2021, 0xc004433, 0x24040001, 0x24110010, 0x2711024, +0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa, +0x2711024, 0x24110010, 0x2b11024, 0x10400002, 0x2021, 0x24040001, +0xc004433, 0x118842, 0x1620fffa, 0x2b11024, 0xc004433, 0x24040001, +0xc004433, 0x2021, 0x34118000, 0x97c20000, 0x511024, 0x10400002, +0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fff8, 0x0, +0xc004459, 0x0, 0x8fbf0020, 0x8fbe001c, 0x8fb50018, 0x8fb30014, +0x8fb10010, 0x3e00008, 0x27bd0028, 0x3c030001, 0x8c633430, 0x3c020001, +0x8c423474, 0x27bdffd8, 0xafbf0020, 0xafb3001c, 0x10620003, 0xafb10018, +0x3c010001, 0xac233474, 0x2463ffff, 0x2c620013, 0x10400349, 0x31080, +0x3c010001, 0x220821, 0x8c223260, 0x400008, 0x0, 0xc004459, +0x8821, 0x34028000, 0xa7a20010, 0x27b30010, 0xc004433, 0x24040001, +0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc004433, 0x2021, +0xc004433, 0x24040001, 0xc004433, 0x2021, 0xc004433, 0x24040001, +0x24110010, 0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc004433, +0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0xc004433, 0x2021, +0x118842, 0x1620fffc, 0x0, 0xc004433, 0x24040001, 0xc004433, +0x2021, 0x34118000, 0x96620000, 0x511024, 0x10400002, 0x2021, +0x24040001, 0xc004433, 0x118842, 0x1620fff8, 0x0, 0xc004459, +0x0, 0x1000030e, 0x24020002, 0x27b30010, 0xa7a00010, 0x8821, +0xc004433, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, +0xc004433, 0x2021, 0xc004433, 0x24040001, 0xc004433, 0x24040001, +0xc004433, 0x2021, 0x24110010, 0x32220001, 0x10400002, 0x2021, +0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, +0xc004433, 0x2021, 0x118842, 0x1620fffc, 0x0, 0xc004459, +0x34118000, 0xc004459, 0x0, 0xc004413, 0x0, 0x50400005, +0x118842, 0x96620000, 0x511025, 0xa6620000, 0x118842, 0x1620fff7, +0x0, 0xc004459, 0x0, 0x97a20010, 0x30428000, 0x144002dc, +0x24020003, 0x100002d8, 0x0, 0x24021200, 0xa7a20010, 0x27b30010, +0x8821, 0xc004433, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, +0x0, 0xc004433, 0x2021, 0xc004433, 0x24040001, 0xc004433, +0x2021, 0xc004433, 0x24040001, 0x24110010, 0x32220001, 0x10400002, +0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220001, +0x24110010, 0xc004433, 0x2021, 0x118842, 0x1620fffc, 0x0, +0xc004433, 0x24040001, 0xc004433, 0x2021, 0x34118000, 0x96620000, +0x511024, 0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, +0x1620fff8, 0x0, 0xc004459, 0x0, 0x8f830054, 0x10000296, +0x24020004, 0x8f830054, 0x3c020001, 0x8c423538, 0x2463ff9c, 0x431023, +0x2c420064, 0x1440029e, 0x24020002, 0x3c030001, 0x8c63353c, 0x10620297, +0x2c620003, 0x14400296, 0x24020011, 0x24020003, 0x10620005, 0x24020004, +0x10620291, 0x2402000f, 0x1000028f, 0x24020011, 0x1000028d, 0x24020005, +0x24020014, 0xa7a20010, 0x27b30010, 0x8821, 0xc004433, 0x24040001, +0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc004433, 0x2021, +0xc004433, 0x24040001, 0xc004433, 0x2021, 0xc004433, 0x24040001, +0x24110010, 0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc004433, +0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0x32220012, 0x10400002, +0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220012, +0xc004433, 0x24040001, 0xc004433, 0x2021, 0x34118000, 0x96620000, +0x511024, 0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, +0x1620fff8, 0x0, 0xc004459, 0x0, 0x8f830054, 0x10000248, +0x24020006, 0x8f830054, 0x3c020001, 0x8c423538, 0x2463ff9c, 0x431023, +0x2c420064, 0x14400250, 0x24020007, 0x1000024c, 0x0, 0x24020006, +0xa7a20010, 0x27b30010, 0x8821, 0xc004433, 0x24040001, 0x26310001, +0x2e220020, 0x1440fffb, 0x0, 0xc004433, 0x2021, 0xc004433, +0x24040001, 0xc004433, 0x2021, 0xc004433, 0x24040001, 0x24110010, +0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, +0x1620fffa, 0x32220001, 0x24110010, 0x32220013, 0x10400002, 0x2021, +0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220013, 0xc004433, +0x24040001, 0xc004433, 0x2021, 0x34118000, 0x96620000, 0x511024, +0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fff8, +0x0, 0xc004459, 0x0, 0x8f830054, 0x10000207, 0x24020008, +0x8f830054, 0x3c020001, 0x8c423538, 0x2463ff9c, 0x431023, 0x2c420064, +0x1440020f, 0x24020009, 0x1000020b, 0x0, 0x27b30010, 0xa7a00010, +0x8821, 0xc004433, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, +0x0, 0xc004433, 0x2021, 0xc004433, 0x24040001, 0xc004433, +0x24040001, 0xc004433, 0x2021, 0x24110010, 0x32220001, 0x10400002, +0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220001, +0x24110010, 0x32220018, 0x10400002, 0x2021, 0x24040001, 0xc004433, +0x118842, 0x1620fffa, 0x32220018, 0xc004459, 0x34118000, 0xc004459, +0x0, 0xc004413, 0x0, 0x50400005, 0x118842, 0x96620000, +0x511025, 0xa6620000, 0x118842, 0x1620fff7, 0x0, 0xc004459, +0x8821, 0x97a20010, 0x27b30010, 0x34420001, 0xa7a20010, 0xc004433, +0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc004433, +0x2021, 0xc004433, 0x24040001, 0xc004433, 0x2021, 0xc004433, 0x24040001, 0x24110010, 0x32220001, 0x10400002, 0x2021, 0x24040001, -0xc0043e7, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0x32220013, -0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, -0x32220013, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0x34118000, -0x96620000, 0x511024, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, -0x118842, 0x1620fff8, 0x0, 0xc00440d, 0x0, 0x8f830054, -0x10000207, 0x24020008, 0x8f830054, 0x3c020001, 0x8c4233d8, 0x2463ff9c, -0x431023, 0x2c420064, 0x1440020f, 0x24020009, 0x1000020b, 0x0, -0x27b30010, 0xa7a00010, 0x8821, 0xc0043e7, 0x24040001, 0x26310001, -0x2e220020, 0x1440fffb, 0x0, 0xc0043e7, 0x2021, 0xc0043e7, -0x24040001, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0x24110010, -0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, -0x1620fffa, 0x32220001, 0x24110010, 0x32220018, 0x10400002, 0x2021, -0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220018, 0xc00440d, -0x34118000, 0xc00440d, 0x0, 0xc0043c7, 0x0, 0x50400005, +0xc004433, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0x32220018, +0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa, +0x32220018, 0xc004433, 0x24040001, 0xc004433, 0x2021, 0x34118000, +0x96620000, 0x511024, 0x10400002, 0x2021, 0x24040001, 0xc004433, +0x118842, 0x1620fff8, 0x0, 0xc004459, 0x0, 0x8f830054, +0x10000193, 0x2402000a, 0x8f830054, 0x3c020001, 0x8c423538, 0x2463ff9c, +0x431023, 0x2c420064, 0x1440019b, 0x2402000b, 0x10000197, 0x0, +0x27b30010, 0xa7a00010, 0x8821, 0xc004433, 0x24040001, 0x26310001, +0x2e220020, 0x1440fffb, 0x0, 0xc004433, 0x2021, 0xc004433, +0x24040001, 0xc004433, 0x24040001, 0xc004433, 0x2021, 0x24110010, +0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, +0x1620fffa, 0x32220001, 0x24110010, 0x32220017, 0x10400002, 0x2021, +0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220017, 0xc004459, +0x34118000, 0xc004459, 0x0, 0xc004413, 0x0, 0x50400005, 0x118842, 0x96620000, 0x511025, 0xa6620000, 0x118842, 0x1620fff7, -0x0, 0xc00440d, 0x8821, 0x97a20010, 0x27b30010, 0x34420001, -0xa7a20010, 0xc0043e7, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, -0x0, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, -0x2021, 0xc0043e7, 0x24040001, 0x24110010, 0x32220001, 0x10400002, -0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220001, -0x24110010, 0x32220018, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, -0x118842, 0x1620fffa, 0x32220018, 0xc0043e7, 0x24040001, 0xc0043e7, +0x0, 0xc004459, 0x8821, 0x97a20010, 0x27b30010, 0x34420700, +0xa7a20010, 0xc004433, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, +0x0, 0xc004433, 0x2021, 0xc004433, 0x24040001, 0xc004433, +0x2021, 0xc004433, 0x24040001, 0x24110010, 0x32220001, 0x10400002, +0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220001, +0x24110010, 0x32220017, 0x10400002, 0x2021, 0x24040001, 0xc004433, +0x118842, 0x1620fffa, 0x32220017, 0xc004433, 0x24040001, 0xc004433, 0x2021, 0x34118000, 0x96620000, 0x511024, 0x10400002, 0x2021, -0x24040001, 0xc0043e7, 0x118842, 0x1620fff8, 0x0, 0xc00440d, -0x0, 0x8f830054, 0x10000193, 0x2402000a, 0x8f830054, 0x3c020001, -0x8c4233d8, 0x2463ff9c, 0x431023, 0x2c420064, 0x1440019b, 0x2402000b, -0x10000197, 0x0, 0x27b30010, 0xa7a00010, 0x8821, 0xc0043e7, -0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc0043e7, -0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, 0x24040001, 0xc0043e7, +0x24040001, 0xc004433, 0x118842, 0x1620fff8, 0x0, 0xc004459, +0x0, 0x8f830054, 0x1000011f, 0x2402000c, 0x8f830054, 0x3c020001, +0x8c423538, 0x2463ff9c, 0x431023, 0x2c420064, 0x14400127, 0x24020012, +0x10000123, 0x0, 0x27b30010, 0xa7a00010, 0x8821, 0xc004433, +0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc004433, +0x2021, 0xc004433, 0x24040001, 0xc004433, 0x24040001, 0xc004433, 0x2021, 0x24110010, 0x32220001, 0x10400002, 0x2021, 0x24040001, -0xc0043e7, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0x32220017, -0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, -0x32220017, 0xc00440d, 0x34118000, 0xc00440d, 0x0, 0xc0043c7, +0xc004433, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0x32220014, +0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa, +0x32220014, 0xc004459, 0x34118000, 0xc004459, 0x0, 0xc004413, 0x0, 0x50400005, 0x118842, 0x96620000, 0x511025, 0xa6620000, -0x118842, 0x1620fff7, 0x0, 0xc00440d, 0x8821, 0x97a20010, -0x27b30010, 0x34420700, 0xa7a20010, 0xc0043e7, 0x24040001, 0x26310001, -0x2e220020, 0x1440fffb, 0x0, 0xc0043e7, 0x2021, 0xc0043e7, -0x24040001, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0x24110010, -0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, -0x1620fffa, 0x32220001, 0x24110010, 0x32220017, 0x10400002, 0x2021, -0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220017, 0xc0043e7, -0x24040001, 0xc0043e7, 0x2021, 0x34118000, 0x96620000, 0x511024, -0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fff8, -0x0, 0xc00440d, 0x0, 0x8f830054, 0x1000011f, 0x2402000c, -0x8f830054, 0x3c020001, 0x8c4233d8, 0x2463ff9c, 0x431023, 0x2c420064, -0x14400127, 0x24020012, 0x10000123, 0x0, 0x27b30010, 0xa7a00010, -0x8821, 0xc0043e7, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, -0x0, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, -0x24040001, 0xc0043e7, 0x2021, 0x24110010, 0x32220001, 0x10400002, -0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220001, -0x24110010, 0x32220014, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, -0x118842, 0x1620fffa, 0x32220014, 0xc00440d, 0x34118000, 0xc00440d, -0x0, 0xc0043c7, 0x0, 0x50400005, 0x118842, 0x96620000, -0x511025, 0xa6620000, 0x118842, 0x1620fff7, 0x0, 0xc00440d, -0x8821, 0x97a20010, 0x27b30010, 0x34420010, 0xa7a20010, 0xc0043e7, -0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc0043e7, -0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0xc0043e7, +0x118842, 0x1620fff7, 0x0, 0xc004459, 0x8821, 0x97a20010, +0x27b30010, 0x34420010, 0xa7a20010, 0xc004433, 0x24040001, 0x26310001, +0x2e220020, 0x1440fffb, 0x0, 0xc004433, 0x2021, 0xc004433, +0x24040001, 0xc004433, 0x2021, 0xc004433, 0x24040001, 0x24110010, +0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, +0x1620fffa, 0x32220001, 0x24110010, 0x32220014, 0x10400002, 0x2021, +0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220014, 0xc004433, +0x24040001, 0xc004433, 0x2021, 0x34118000, 0x96620000, 0x511024, +0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fff8, +0x0, 0xc004459, 0x0, 0x8f830054, 0x100000ab, 0x24020013, +0x8f830054, 0x3c020001, 0x8c423538, 0x2463ff9c, 0x431023, 0x2c420064, +0x144000b3, 0x2402000d, 0x100000af, 0x0, 0x27b30010, 0xa7a00010, +0x8821, 0xc004433, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, +0x0, 0xc004433, 0x2021, 0xc004433, 0x24040001, 0xc004433, +0x24040001, 0xc004433, 0x2021, 0x24110010, 0x32220001, 0x10400002, +0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220001, +0x24110010, 0x32220018, 0x10400002, 0x2021, 0x24040001, 0xc004433, +0x118842, 0x1620fffa, 0x32220018, 0xc004459, 0x34118000, 0xc004459, +0x0, 0xc004413, 0x0, 0x50400005, 0x118842, 0x96620000, +0x511025, 0xa6620000, 0x118842, 0x1620fff7, 0x0, 0xc004459, +0x8821, 0x97a20010, 0x27b30010, 0x3042fffe, 0xa7a20010, 0xc004433, +0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc004433, +0x2021, 0xc004433, 0x24040001, 0xc004433, 0x2021, 0xc004433, 0x24040001, 0x24110010, 0x32220001, 0x10400002, 0x2021, 0x24040001, -0xc0043e7, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0x32220014, -0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, -0x32220014, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0x34118000, -0x96620000, 0x511024, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, -0x118842, 0x1620fff8, 0x0, 0xc00440d, 0x0, 0x8f830054, -0x100000ab, 0x24020013, 0x8f830054, 0x3c020001, 0x8c4233d8, 0x2463ff9c, -0x431023, 0x2c420064, 0x144000b3, 0x2402000d, 0x100000af, 0x0, -0x27b30010, 0xa7a00010, 0x8821, 0xc0043e7, 0x24040001, 0x26310001, -0x2e220020, 0x1440fffb, 0x0, 0xc0043e7, 0x2021, 0xc0043e7, -0x24040001, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0x24110010, -0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, -0x1620fffa, 0x32220001, 0x24110010, 0x32220018, 0x10400002, 0x2021, -0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220018, 0xc00440d, -0x34118000, 0xc00440d, 0x0, 0xc0043c7, 0x0, 0x50400005, -0x118842, 0x96620000, 0x511025, 0xa6620000, 0x118842, 0x1620fff7, -0x0, 0xc00440d, 0x8821, 0x97a20010, 0x27b30010, 0x3042fffe, -0xa7a20010, 0xc0043e7, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, -0x0, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, -0x2021, 0xc0043e7, 0x24040001, 0x24110010, 0x32220001, 0x10400002, -0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220001, -0x24110010, 0x32220018, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, -0x118842, 0x1620fffa, 0x32220018, 0xc0043e7, 0x24040001, 0xc0043e7, -0x2021, 0x34118000, 0x96620000, 0x511024, 0x10400002, 0x2021, -0x24040001, 0xc0043e7, 0x118842, 0x1620fff8, 0x0, 0xc00440d, -0x0, 0x8f830054, 0x10000037, 0x2402000e, 0x24020840, 0xa7a20010, -0x27b30010, 0x8821, 0xc0043e7, 0x24040001, 0x26310001, 0x2e220020, -0x1440fffb, 0x0, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, -0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0x24110010, 0x32220001, -0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, -0x32220001, 0x24110010, 0x32220013, 0x10400002, 0x2021, 0x24040001, -0xc0043e7, 0x118842, 0x1620fffa, 0x32220013, 0xc0043e7, 0x24040001, -0xc0043e7, 0x2021, 0x34118000, 0x96620000, 0x511024, 0x10400002, -0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fff8, 0x0, -0xc00440d, 0x0, 0x8f830054, 0x24020010, 0x3c010001, 0xac2232d0, -0x3c010001, 0x1000000c, 0xac2333d8, 0x8f830054, 0x3c020001, 0x8c4233d8, -0x2463ff9c, 0x431023, 0x2c420064, 0x14400004, 0x0, 0x24020011, -0x3c010001, 0xac2232d0, 0x8fbf0020, 0x8fb3001c, 0x8fb10018, 0x3e00008, -0x27bd0028, 0x8f850044, 0x8f820044, 0x3c030001, 0x431025, 0x3c030008, -0xaf820044, 0x8f840054, 0x8f820054, 0xa32824, 0x10000002, 0x24840001, -0x8f820054, 0x821023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820044, -0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, 0x8f830054, 0x8f820054, -0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, -0x0, 0x3e00008, 0xa01021, 0x8f830044, 0x3c02fff0, 0x3442ffff, -0x42480, 0x621824, 0x3c020002, 0x822025, 0x641825, 0xaf830044, -0x8f820044, 0x3c030001, 0x431025, 0xaf820044, 0x8f830054, 0x8f820054, -0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, -0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, -0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, -0x2c420002, 0x1440fffc, 0x0, 0x3e00008, 0x0, 0x8f820044, -0x3c03fff0, 0x3463ffff, 0x431024, 0xaf820044, 0x8f820044, 0x3c030001, +0xc004433, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0x32220018, +0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa, +0x32220018, 0xc004433, 0x24040001, 0xc004433, 0x2021, 0x34118000, +0x96620000, 0x511024, 0x10400002, 0x2021, 0x24040001, 0xc004433, +0x118842, 0x1620fff8, 0x0, 0xc004459, 0x0, 0x8f830054, +0x10000037, 0x2402000e, 0x24020840, 0xa7a20010, 0x27b30010, 0x8821, +0xc004433, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, +0xc004433, 0x2021, 0xc004433, 0x24040001, 0xc004433, 0x2021, +0xc004433, 0x24040001, 0x24110010, 0x32220001, 0x10400002, 0x2021, +0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, +0x32220013, 0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, +0x1620fffa, 0x32220013, 0xc004433, 0x24040001, 0xc004433, 0x2021, +0x34118000, 0x96620000, 0x511024, 0x10400002, 0x2021, 0x24040001, +0xc004433, 0x118842, 0x1620fff8, 0x0, 0xc004459, 0x0, +0x8f830054, 0x24020010, 0x3c010001, 0xac223430, 0x3c010001, 0x1000000c, +0xac233538, 0x8f830054, 0x3c020001, 0x8c423538, 0x2463ff9c, 0x431023, +0x2c420064, 0x14400004, 0x0, 0x24020011, 0x3c010001, 0xac223430, +0x8fbf0020, 0x8fb3001c, 0x8fb10018, 0x3e00008, 0x27bd0028, 0x8f850044, +0x8f820044, 0x3c030001, 0x431025, 0x3c030008, 0xaf820044, 0x8f840054, +0x8f820054, 0xa32824, 0x10000002, 0x24840001, 0x8f820054, 0x821023, +0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, +0x431024, 0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, +0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x3e00008, +0xa01021, 0x8f830044, 0x3c02fff0, 0x3442ffff, 0x42480, 0x621824, +0x3c020002, 0x822025, 0x641825, 0xaf830044, 0x8f820044, 0x3c030001, 0x431025, 0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, -0x0, 0x3e00008, 0x0, 0x0, 0x27bdffe8, 0xafbf0010, -0x8ee379c8, 0x24020008, 0x146201ca, 0x0, 0x3c020001, 0x8c4233c8, -0x14400005, 0x0, 0xc003a65, 0x8f840224, 0x100001c2, 0x0, -0x8f820220, 0x3c030008, 0x431024, 0x10400026, 0x24020001, 0x8f840224, -0x8f820220, 0x3c030400, 0x431024, 0x10400006, 0x0, 0x3c010001, -0xac205440, 0x3c010001, 0x1000000b, 0xac205460, 0x3c030001, 0x24635440, -0x8c620000, 0x24420001, 0xac620000, 0x2c420002, 0x14400003, 0x24020001, -0x3c010001, 0xac225460, 0x3c020001, 0x8c425460, 0x10400006, 0x30820040, -0x10400004, 0x24020001, 0x3c010001, 0x10000003, 0xac225464, 0x3c010001, -0xac205464, 0x3c010001, 0xac24543c, 0x3c010001, 0x1000000b, 0xac205470, -0x3c010001, 0xac225470, 0x3c010001, 0xac205460, 0x3c010001, 0xac205440, -0x3c010001, 0xac205464, 0x3c010001, 0xac20543c, 0x3c030001, 0x8c635430, -0x3c020001, 0x8c425434, 0x50620004, 0x2463ffff, 0x3c010001, 0xac235434, -0x2463ffff, 0x2c62000e, 0x1040017e, 0x31080, 0x3c010001, 0x220821, -0x8c223150, 0x400008, 0x0, 0x3c02fdff, 0x3442ffff, 0x282a024, -0x24020002, 0x3c010001, 0xac205460, 0x3c010001, 0xac205440, 0x3c010001, -0xac205470, 0x3c010001, 0xac20543c, 0x3c010001, 0xac205464, 0x3c010001, -0xac205458, 0x3c010001, 0xac205450, 0xaf800224, 0x3c010001, 0xac225430, -0xc003a65, 0x0, 0xaf800204, 0x8f820200, 0x2403fffd, 0x431024, -0xaf820200, 0x3c010001, 0xac205480, 0x8f830054, 0x3c020001, 0x8c425458, -0x24040001, 0x3c010001, 0xac24546c, 0x24420001, 0x3c010001, 0xac225458, -0x2c420004, 0x3c010001, 0xac235454, 0x14400006, 0x24020003, 0x3c010001, -0xac2432b0, 0x3c010001, 0x10000148, 0xac205458, 0x3c010001, 0x10000145, -0xac225430, 0x8f830054, 0x3c020001, 0x8c425454, 0x2463d8f0, 0x431023, -0x2c422710, 0x1440013d, 0x24020004, 0x3c010001, 0x1000013a, 0xac225430, -0x3c040001, 0x8c8433cc, 0x3c010001, 0xc004602, 0xac205448, 0x3c020001, -0x8c42547c, 0xaf820204, 0x8f820204, 0x30420030, 0x14400125, 0x24020002, -0x3c030001, 0x8c63547c, 0x24020005, 0x3c010001, 0xac225430, 0x3c010001, -0x10000126, 0xac235480, 0x3c020001, 0x8c425460, 0x10400122, 0x0, -0x3c020001, 0x8c42543c, 0x1040011e, 0x0, 0x3c010001, 0xac225468, -0x24020003, 0x3c010001, 0xac225440, 0x100000c1, 0x24020006, 0x3c010001, -0xac205448, 0x8f820204, 0x34420040, 0xaf820204, 0x3c020001, 0x8c425480, -0x24030007, 0x3c010001, 0xac235430, 0x34420040, 0x3c010001, 0xac225480, -0x3c020001, 0x8c425460, 0x10400005, 0x0, 0x3c020001, 0x8c42543c, -0x104000f9, 0x24020002, 0x3c050001, 0x24a55440, 0x8ca20000, 0x2c424e21, -0x104000f3, 0x24020002, 0x3c020001, 0x8c425464, 0x104000f8, 0x2404ffbf, -0x3c020001, 0x8c42543c, 0x3c030001, 0x8c635468, 0x441024, 0x641824, -0x14430007, 0x24020001, 0x24020003, 0xaca20000, 0x24020008, 0x3c010001, -0x100000ea, 0xac225430, 0x3c010001, 0x100000e7, 0xac225430, 0x3c020001, -0x8c42546c, 0x1040000c, 0x24020001, 0x3c040001, 0xc00460f, 0x8c84543c, -0x3c020001, 0x8c425488, 0x14400005, 0x24020001, 0x3c020001, 0x8c425484, -0x10400006, 0x24020001, 0x3c010001, 0xac2232b0, 0x3c010001, 0x100000d3, -0xac205458, 0x8f820204, 0x34420040, 0xaf820204, 0x3c020001, 0x8c425480, -0x3c030001, 0x8c635450, 0x34420040, 0x3c010001, 0xac225480, 0x3c020001, -0x8c42543c, 0x2c630001, 0x318c0, 0x3c010001, 0xac235450, 0x30420008, -0x3c010001, 0xac22544c, 0x8f830054, 0x24020009, 0x3c010001, 0xac225430, -0x3c010001, 0x100000b9, 0xac235454, 0x8f830054, 0x3c020001, 0x8c425454, -0x2463d8f0, 0x431023, 0x2c422710, 0x1440009f, 0x0, 0x3c020001, -0x8c425460, 0x10400005, 0x0, 0x3c020001, 0x8c42543c, 0x104000a0, -0x24020002, 0x3c030001, 0x24635440, 0x8c620000, 0x2c424e21, 0x1040009a, -0x24020002, 0x3c020001, 0x8c42546c, 0x1040000e, 0x0, 0x3c020001, -0x8c42543c, 0x3c010001, 0xac20546c, 0x30420080, 0x1040002f, 0x2402000c, -0x8f820204, 0x30420080, 0x1440000c, 0x24020003, 0x10000029, 0x2402000c, -0x3c020001, 0x8c42543c, 0x30420080, 0x14400005, 0x24020003, 0x8f820204, -0x30420080, 0x1040001f, 0x24020003, 0xac620000, 0x2402000a, 0x3c010001, -0xac225430, 0x3c040001, 0x24845478, 0x8c820000, 0x3c030001, 0x8c635450, -0x431025, 0xaf820204, 0x8c830000, 0x3c040001, 0x8c845450, 0x2402000b, -0x3c010001, 0xac225430, 0x641825, 0x3c010001, 0xac235480, 0x3c050001, -0x24a55440, 0x8ca20000, 0x2c424e21, 0x10400066, 0x24020002, 0x3c020001, -0x8c425470, 0x10400005, 0x0, 0x2402000c, 0x3c010001, 0x10000067, -0xac225430, 0x3c020001, 0x8c425460, 0x10400063, 0x0, 0x3c040001, -0x8c84543c, 0x10800055, 0x30820008, 0x3c030001, 0x8c63544c, 0x1062005b, -0x24020003, 0x3c010001, 0xac245468, 0xaca20000, 0x24020006, 0x3c010001, -0x10000054, 0xac225430, 0x8f820200, 0x34420002, 0xaf820200, 0x8f830054, -0x2402000d, 0x3c010001, 0xac225430, 0x3c010001, 0xac235454, 0x8f830054, -0x3c020001, 0x8c425454, 0x2463d8f0, 0x431023, 0x2c422710, 0x14400031, -0x0, 0x3c020001, 0x8c425470, 0x10400020, 0x2402000e, 0x3c030001, -0x8c635484, 0x3c010001, 0x14600015, 0xac225430, 0xc003b1e, 0x0, -0x3c050001, 0x8ca532ac, 0xc004785, 0x24040001, 0x3c030001, 0x8c6332ac, -0x24020004, 0x14620005, 0x2403fffb, 0x3c020001, 0x8c4232a8, 0x10000003, -0x2403fff7, 0x3c020001, 0x8c4232a8, 0x431024, 0x3c010001, 0xac2232a8, -0x8f830224, 0x3c020200, 0x3c010001, 0xac23548c, 0x10000020, 0x282a025, -0x3c020001, 0x8c425460, 0x10400005, 0x0, 0x3c020001, 0x8c42543c, -0x1040000f, 0x24020002, 0x3c020001, 0x8c425440, 0x2c424e21, 0x1040000a, -0x24020002, 0x3c020001, 0x8c425460, 0x1040000f, 0x0, 0x3c020001, -0x8c42543c, 0x1440000b, 0x0, 0x24020002, 0x3c010001, 0x10000007, -0xac225430, 0x3c020001, 0x8c425460, 0x10400003, 0x0, 0xc003a65, -0x0, 0x8f820220, 0x3c03f700, 0x431025, 0xaf820220, 0x8fbf0010, -0x3e00008, 0x27bd0018, 0x3c030001, 0x24635488, 0x8c620000, 0x10400005, -0x34422000, 0x3c010001, 0xac22547c, 0x10000003, 0xac600000, 0x3c010001, -0xac24547c, 0x3e00008, 0x0, 0x27bdffe0, 0x30820030, 0xafbf0018, -0x3c010001, 0xac225484, 0x14400067, 0x3c02ffff, 0x34421f0e, 0x821024, -0x14400061, 0x24020030, 0x30822000, 0x1040005d, 0x30838000, 0x31a02, -0x30820001, 0x21200, 0x3c040001, 0x8c8433cc, 0x621825, 0x331c2, -0x3c030001, 0x2463332c, 0x30828000, 0x21202, 0x30840001, 0x42200, -0x441025, 0x239c2, 0x61080, 0x431021, 0x471021, 0x90430000, -0x24020001, 0x10620025, 0x0, 0x10600007, 0x24020002, 0x10620013, -0x24020003, 0x1062002c, 0x3c05000f, 0x10000037, 0x0, 0x8f820200, -0x2403feff, 0x431024, 0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, -0x431024, 0xaf820220, 0x3c010001, 0xac2054c4, 0x3c010001, 0x10000034, -0xac2054cc, 0x8f820200, 0x34420100, 0xaf820200, 0x8f820220, 0x3c03fffe, -0x3463ffff, 0x431024, 0xaf820220, 0x24020100, 0x3c010001, 0xac2254c4, -0x3c010001, 0x10000026, 0xac2054cc, 0x8f820200, 0x2403feff, 0x431024, -0xaf820200, 0x8f820220, 0x3c030001, 0x431025, 0xaf820220, 0x3c010001, -0xac2054c4, 0x3c010001, 0x10000019, 0xac2354cc, 0x8f820200, 0x34420100, -0xaf820200, 0x8f820220, 0x3c030001, 0x431025, 0xaf820220, 0x24020100, -0x3c010001, 0xac2254c4, 0x3c010001, 0x1000000c, 0xac2354cc, 0x34a5ffff, -0x3c040001, 0x24843188, 0xafa30010, 0xc0028eb, 0xafa00014, 0x10000004, -0x0, 0x24020030, 0x3c010001, 0xac225488, 0x8fbf0018, 0x3e00008, -0x27bd0020, 0x0, 0x27bdffc8, 0xafb30024, 0x809821, 0xafbe002c, -0xa0f021, 0xafb10020, 0xc08821, 0x3c040001, 0x248431a0, 0x3c050009, -0x3c020001, 0x8c4232ac, 0x34a59001, 0x2603021, 0x3c03821, 0xafbf0030, -0xafb50028, 0xa7a0001a, 0xafb10014, 0xc0028eb, 0xafa20010, 0x24020002, -0x13c200e7, 0x2fc20003, 0x10400005, 0x24020001, 0x13c2000a, 0x3c02fffb, -0x100000e1, 0x0, 0x24020004, 0x13c2006d, 0x24020008, 0x13c2006c, -0x3c02ffec, 0x100000da, 0x0, 0x3442ffff, 0x2228824, 0x13a940, -0x3c010001, 0x350821, 0xac31549c, 0x3c024000, 0x2221024, 0x10400046, -0x1123c2, 0x30840030, 0x111382, 0x3042000c, 0x3c030001, 0x246332d4, -0x431021, 0x823821, 0x3c020020, 0x2221024, 0x10400006, 0x24020100, -0x3c010001, 0x350821, 0xac2254a0, 0x10000005, 0x3c020080, 0x3c010001, -0x350821, 0xac2054a0, 0x3c020080, 0x2221024, 0x10400006, 0x131940, -0x3c020001, 0x3c010001, 0x230821, 0x10000005, 0xac2254a8, 0x131140, -0x3c010001, 0x220821, 0xac2054a8, 0x94e30000, 0x32224000, 0x10400003, -0xa7a30018, 0x34624000, 0xa7a20018, 0x24040001, 0x94e20002, 0x24050004, -0x24e60002, 0x34420001, 0xc00402a, 0xa4e20002, 0x24040001, 0x2821, -0xc00402a, 0x27a60018, 0x3c020001, 0x8c4232ac, 0x24130001, 0x3c010001, -0xac3332b8, 0x145e0004, 0x32228000, 0xc003a65, 0x0, 0x32228000, -0x10400093, 0x0, 0xc003a65, 0x0, 0x24020002, 0x3c010001, -0xac3332b0, 0x3c010001, 0x1000008b, 0xac2232ac, 0x24040001, 0x24050004, -0x27b1001a, 0xc00402a, 0x2203021, 0x24040001, 0x2821, 0xc00402a, -0x2203021, 0x3c020001, 0x551021, 0x8c425494, 0x3c040001, 0x8c8432ac, -0x3c03bfff, 0x3463ffff, 0x3c010001, 0xac3e32b8, 0x431024, 0x3c010001, -0x350821, 0x109e0072, 0xac225494, 0x10000072, 0x0, 0x3c02ffec, -0x3442ffff, 0x2228824, 0x3c020008, 0x2228825, 0x131140, 0x3c010001, -0x220821, 0xac315498, 0x3c022000, 0x2221024, 0x10400005, 0x24020001, -0x3c010001, 0xac2233c8, 0x10000004, 0x3c024000, 0x3c010001, 0xac2033c8, -0x3c024000, 0x2221024, 0x1440001a, 0x0, 0x3c020001, 0x8c4233c8, -0x10400005, 0x24022020, 0x3c010001, 0xac2233cc, 0x24020001, 0xaee279c8, -0x3c04bfff, 0x131940, 0x3c020001, 0x431021, 0x8c425490, 0x3c050001, -0x8ca532ac, 0x3484ffff, 0x441024, 0x3c010001, 0x230821, 0xac225490, -0x24020001, 0x10a20044, 0x0, 0x10000040, 0x0, 0x3c020001, -0x8c4233c8, 0x1040001c, 0x24022000, 0x3c010001, 0xac2233cc, 0x3c0300a0, -0x2231024, 0x14430005, 0x131140, 0x3402a000, 0x3c010001, 0x1000002d, -0xac2233cc, 0x3c030001, 0x621821, 0x8c635498, 0x3c020020, 0x621024, -0x10400004, 0x24022001, 0x3c010001, 0x10000023, 0xac2233cc, 0x3c020080, -0x621024, 0x1040001f, 0x3402a001, 0x3c010001, 0x1000001c, 0xac2233cc, -0x3c020020, 0x2221024, 0x10400007, 0x131940, 0x24020100, 0x3c010001, -0x230821, 0xac2254a4, 0x10000006, 0x3c020080, 0x131140, 0x3c010001, -0x220821, 0xac2054a4, 0x3c020080, 0x2221024, 0x10400006, 0x131940, -0x3c020001, 0x3c010001, 0x230821, 0x10000005, 0xac2254ac, 0x131140, -0x3c010001, 0x220821, 0xac2054ac, 0x3c030001, 0x8c6332ac, 0x24020001, -0x10620003, 0x0, 0xc003a65, 0x0, 0x8fbf0030, 0x8fbe002c, -0x8fb50028, 0x8fb30024, 0x8fb10020, 0x3e00008, 0x27bd0038, 0x27bdffc8, -0xafb50028, 0xa821, 0xafbe002c, 0xf021, 0xafb30024, 0x9821, -0x24020002, 0xafbf0030, 0xafb10020, 0xafa4001c, 0xa7a00012, 0x10a2006a, -0xa7a00010, 0x2ca20003, 0x10400005, 0x24020001, 0x10a2000a, 0x3c024000, -0x100000ad, 0x2601021, 0x24020004, 0x10a20060, 0x24020008, 0x10a2005e, -0x2601021, 0x100000a6, 0x0, 0x8fa7001c, 0x78940, 0x3c030001, -0x711821, 0x8c63549c, 0x621024, 0x14400009, 0x24040001, 0x3c027fff, -0x3442ffff, 0x629824, 0x3c010001, 0x310821, 0xac335494, 0x10000096, -0x2601021, 0x24050001, 0xc003fe8, 0x27a60010, 0x24040001, 0x24050001, -0xc003fe8, 0x27a60010, 0x97a20010, 0x30420004, 0x10400034, 0x3c134000, -0x3c030001, 0x8c6333dc, 0x24020003, 0x10620008, 0x2c620004, 0x14400029, -0x3c028000, 0x24020004, 0x10620014, 0x24040001, 0x10000024, 0x3c028000, -0x24040001, 0x24050011, 0x27b10012, 0xc003fe8, 0x2203021, 0x24040001, -0x24050011, 0xc003fe8, 0x2203021, 0x97a30012, 0x30624000, 0x10400002, -0x3c1e0010, 0x3c1e0008, 0x3c150001, 0x10000010, 0x30628000, 0x24050014, -0x27b10012, 0xc003fe8, 0x2203021, 0x24040001, 0x24050014, 0xc003fe8, -0x2203021, 0x97a30012, 0x30621000, 0x10400002, 0x3c1e0010, 0x3c1e0008, -0x3c150001, 0x30620800, 0x54400001, 0x3c150002, 0x3c028000, 0x2621025, -0x2be1825, 0x10000007, 0x439825, 0x3c130001, 0x2719821, 0x8e73549c, -0x3c027fff, 0x3442ffff, 0x2629824, 0x8fa7001c, 0x71140, 0x3c010001, -0x220821, 0xac335494, 0x1000004b, 0x2601021, 0x8fa7001c, 0x72140, -0x3c030001, 0x641821, 0x8c635498, 0x3c024000, 0x621024, 0x14400008, -0x3c027fff, 0x3442ffff, 0x629824, 0x3c010001, 0x240821, 0xac335490, -0x1000003b, 0x2601021, 0x3c020001, 0x8c4232bc, 0x1040002e, 0x3c13c00c, -0x3c020001, 0x8c4233c8, 0x3c03e00c, 0x3c010001, 0x240821, 0x8c2454a4, -0x2102b, 0x21023, 0x431024, 0x10800004, 0x539825, 0x3c020020, -0x10000004, 0x2629825, 0x3c02ffdf, 0x3442ffff, 0x2629824, 0x8fa7001c, -0x71140, 0x3c010001, 0x220821, 0x8c2254ac, 0x10400003, 0x3c020080, -0x10000004, 0x2629825, 0x3c02ff7f, 0x3442ffff, 0x2629824, 0x3c020001, -0x8c423320, 0x10400002, 0x3c020800, 0x2629825, 0x3c020001, 0x8c423324, -0x10400002, 0x3c020400, 0x2629825, 0x3c020001, 0x8c423328, 0x10400006, -0x3c020100, 0x10000004, 0x2629825, 0x3c027fff, 0x3442ffff, 0x629824, -0x8fa7001c, 0x71140, 0x3c010001, 0x220821, 0xac335490, 0x2601021, -0x8fbf0030, 0x8fbe002c, 0x8fb50028, 0x8fb30024, 0x8fb10020, 0x3e00008, -0x27bd0038, 0x27bdffe0, 0xafb50018, 0x80a821, 0xafbf001c, 0xafb30014, -0xafb10010, 0x8f840200, 0x3c030001, 0x8c6332ac, 0x8f860220, 0x24020002, -0x106200a3, 0x2c620003, 0x10400005, 0x24020001, 0x1062000a, 0x151940, -0x1000009d, 0x0, 0x24020004, 0x10620053, 0x24020008, 0x10620052, -0x159940, 0x10000096, 0x0, 0x3c050001, 0xa32821, 0x8ca5549c, -0x3c110001, 0x2238821, 0x8e315494, 0x3c024000, 0xa21024, 0x10400038, -0x3c020008, 0x2221024, 0x10400020, 0x34840002, 0x3c020001, 0x431021, -0x8c4254a0, 0x10400005, 0x34840020, 0x34840100, 0x3c020020, 0x10000006, -0x2228825, 0x2402feff, 0x822024, 0x3c02ffdf, 0x3442ffff, 0x2228824, -0x151140, 0x3c010001, 0x220821, 0x8c2254a8, 0x10400005, 0x3c020001, -0xc23025, 0x3c020080, 0x10000016, 0x2228825, 0x3c02fffe, 0x3442ffff, -0xc23024, 0x3c02ff7f, 0x3442ffff, 0x1000000f, 0x2228824, 0x2402fedf, -0x822024, 0x3c02fffe, 0x3442ffff, 0xc23024, 0x3c02ff5f, 0x3442ffff, -0x2228824, 0x3c010001, 0x230821, 0xac2054a0, 0x3c010001, 0x230821, -0xac2054a8, 0xaf840200, 0xaf860220, 0x8f820220, 0x34420002, 0xaf820220, -0x1000000a, 0x151140, 0x3c02bfff, 0x3442ffff, 0x8f830200, 0x2228824, -0x2402fffd, 0x621824, 0xc003a65, 0xaf830200, 0x151140, 0x3c010001, -0x220821, 0x10000048, 0xac315494, 0x159940, 0x3c050001, 0xb32821, -0x8ca55498, 0x3c110001, 0x2338821, 0x8e315490, 0x3c024000, 0xa21024, -0x14400010, 0x0, 0x3c020001, 0x8c4233c8, 0x14400005, 0x3c02bfff, -0x8f820200, 0x34420002, 0xaf820200, 0x3c02bfff, 0x3442ffff, 0xc003a65, -0x2228824, 0x3c010001, 0x330821, 0x1000002e, 0xac315490, 0x3c020001, -0x8c4233c8, 0x14400027, 0x151140, 0x3c020020, 0xa21024, 0x10400007, -0x34840020, 0x24020100, 0x3c010001, 0x330821, 0xac2254a4, 0x10000006, -0x34840100, 0x3c010001, 0x330821, 0xac2054a4, 0x2402feff, 0x822024, -0x3c020080, 0xa21024, 0x10400007, 0x151940, 0x3c020001, 0x3c010001, -0x230821, 0xac2254ac, 0x10000008, 0xc23025, 0x151140, 0x3c010001, -0x220821, 0xac2054ac, 0x3c02fffe, 0x3442ffff, 0xc23024, 0xaf840200, -0xaf860220, 0x8f820220, 0x34420002, 0xaf820220, 0x151140, 0x3c010001, -0x220821, 0xac315490, 0x8fbf001c, 0x8fb50018, 0x8fb30014, 0x8fb10010, -0x3e00008, 0x27bd0020, 0x0, 0x0, 0x1821, 0x308400ff, -0x2405ffdf, 0x2406ffbf, 0x641007, 0x30420001, 0x10400004, 0x0, -0x8f820044, 0x10000003, 0x34420040, 0x8f820044, 0x461024, 0xaf820044, -0x8f820044, 0x34420020, 0xaf820044, 0x8f820044, 0x451024, 0xaf820044, -0x24630001, 0x28620008, 0x5440ffee, 0x641007, 0x3e00008, 0x0, -0x0, 0x0, 0x0 }; -u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] = { +0x0, 0x3e00008, 0x0, 0x8f820044, 0x3c03fff0, 0x3463ffff, +0x431024, 0xaf820044, 0x8f820044, 0x3c030001, 0x431025, 0xaf820044, +0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, +0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, +0x431024, 0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, +0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x3e00008, +0x0, 0x0, 0x27bdffe8, 0xafbf0010, 0x8ee379c8, 0x24020008, +0x146201ca, 0x0, 0x3c020001, 0x8c423528, 0x14400005, 0x0, +0xc003ab1, 0x8f840224, 0x100001c2, 0x0, 0x8f820220, 0x3c030008, +0x431024, 0x10400026, 0x24020001, 0x8f840224, 0x8f820220, 0x3c030400, +0x431024, 0x10400006, 0x0, 0x3c010001, 0xac2055a0, 0x3c010001, +0x1000000b, 0xac2055c0, 0x3c030001, 0x246355a0, 0x8c620000, 0x24420001, +0xac620000, 0x2c420002, 0x14400003, 0x24020001, 0x3c010001, 0xac2255c0, +0x3c020001, 0x8c4255c0, 0x10400006, 0x30820040, 0x10400004, 0x24020001, +0x3c010001, 0x10000003, 0xac2255c4, 0x3c010001, 0xac2055c4, 0x3c010001, +0xac24559c, 0x3c010001, 0x1000000b, 0xac2055d0, 0x3c010001, 0xac2255d0, +0x3c010001, 0xac2055c0, 0x3c010001, 0xac2055a0, 0x3c010001, 0xac2055c4, +0x3c010001, 0xac20559c, 0x3c030001, 0x8c635590, 0x3c020001, 0x8c425594, +0x50620004, 0x2463ffff, 0x3c010001, 0xac235594, 0x2463ffff, 0x2c62000e, +0x1040017e, 0x31080, 0x3c010001, 0x220821, 0x8c2232b0, 0x400008, +0x0, 0x3c02fdff, 0x3442ffff, 0x282a024, 0x24020002, 0x3c010001, +0xac2055c0, 0x3c010001, 0xac2055a0, 0x3c010001, 0xac2055d0, 0x3c010001, +0xac20559c, 0x3c010001, 0xac2055c4, 0x3c010001, 0xac2055b8, 0x3c010001, +0xac2055b0, 0xaf800224, 0x3c010001, 0xac225590, 0xc003ab1, 0x0, +0xaf800204, 0x8f820200, 0x2403fffd, 0x431024, 0xaf820200, 0x3c010001, +0xac2055e0, 0x8f830054, 0x3c020001, 0x8c4255b8, 0x24040001, 0x3c010001, +0xac2455cc, 0x24420001, 0x3c010001, 0xac2255b8, 0x2c420004, 0x3c010001, +0xac2355b4, 0x14400006, 0x24020003, 0x3c010001, 0xac243410, 0x3c010001, +0x10000148, 0xac2055b8, 0x3c010001, 0x10000145, 0xac225590, 0x8f830054, +0x3c020001, 0x8c4255b4, 0x2463d8f0, 0x431023, 0x2c422710, 0x1440013d, +0x24020004, 0x3c010001, 0x1000013a, 0xac225590, 0x3c040001, 0x8c84352c, +0x3c010001, 0xc00464e, 0xac2055a8, 0x3c020001, 0x8c4255dc, 0xaf820204, +0x8f820204, 0x30420030, 0x14400125, 0x24020002, 0x3c030001, 0x8c6355dc, +0x24020005, 0x3c010001, 0xac225590, 0x3c010001, 0x10000126, 0xac2355e0, +0x3c020001, 0x8c4255c0, 0x10400122, 0x0, 0x3c020001, 0x8c42559c, +0x1040011e, 0x0, 0x3c010001, 0xac2255c8, 0x24020003, 0x3c010001, +0xac2255a0, 0x100000c1, 0x24020006, 0x3c010001, 0xac2055a8, 0x8f820204, +0x34420040, 0xaf820204, 0x3c020001, 0x8c4255e0, 0x24030007, 0x3c010001, +0xac235590, 0x34420040, 0x3c010001, 0xac2255e0, 0x3c020001, 0x8c4255c0, +0x10400005, 0x0, 0x3c020001, 0x8c42559c, 0x104000f9, 0x24020002, +0x3c050001, 0x24a555a0, 0x8ca20000, 0x2c424e21, 0x104000f3, 0x24020002, +0x3c020001, 0x8c4255c4, 0x104000f8, 0x2404ffbf, 0x3c020001, 0x8c42559c, +0x3c030001, 0x8c6355c8, 0x441024, 0x641824, 0x14430007, 0x24020001, +0x24020003, 0xaca20000, 0x24020008, 0x3c010001, 0x100000ea, 0xac225590, +0x3c010001, 0x100000e7, 0xac225590, 0x3c020001, 0x8c4255cc, 0x1040000c, +0x24020001, 0x3c040001, 0xc00465b, 0x8c84559c, 0x3c020001, 0x8c4255e8, +0x14400005, 0x24020001, 0x3c020001, 0x8c4255e4, 0x10400006, 0x24020001, +0x3c010001, 0xac223410, 0x3c010001, 0x100000d3, 0xac2055b8, 0x8f820204, +0x34420040, 0xaf820204, 0x3c020001, 0x8c4255e0, 0x3c030001, 0x8c6355b0, +0x34420040, 0x3c010001, 0xac2255e0, 0x3c020001, 0x8c42559c, 0x2c630001, +0x318c0, 0x3c010001, 0xac2355b0, 0x30420008, 0x3c010001, 0xac2255ac, +0x8f830054, 0x24020009, 0x3c010001, 0xac225590, 0x3c010001, 0x100000b9, +0xac2355b4, 0x8f830054, 0x3c020001, 0x8c4255b4, 0x2463d8f0, 0x431023, +0x2c422710, 0x1440009f, 0x0, 0x3c020001, 0x8c4255c0, 0x10400005, +0x0, 0x3c020001, 0x8c42559c, 0x104000a0, 0x24020002, 0x3c030001, +0x246355a0, 0x8c620000, 0x2c424e21, 0x1040009a, 0x24020002, 0x3c020001, +0x8c4255cc, 0x1040000e, 0x0, 0x3c020001, 0x8c42559c, 0x3c010001, +0xac2055cc, 0x30420080, 0x1040002f, 0x2402000c, 0x8f820204, 0x30420080, +0x1440000c, 0x24020003, 0x10000029, 0x2402000c, 0x3c020001, 0x8c42559c, +0x30420080, 0x14400005, 0x24020003, 0x8f820204, 0x30420080, 0x1040001f, +0x24020003, 0xac620000, 0x2402000a, 0x3c010001, 0xac225590, 0x3c040001, +0x248455d8, 0x8c820000, 0x3c030001, 0x8c6355b0, 0x431025, 0xaf820204, +0x8c830000, 0x3c040001, 0x8c8455b0, 0x2402000b, 0x3c010001, 0xac225590, +0x641825, 0x3c010001, 0xac2355e0, 0x3c050001, 0x24a555a0, 0x8ca20000, +0x2c424e21, 0x10400066, 0x24020002, 0x3c020001, 0x8c4255d0, 0x10400005, +0x0, 0x2402000c, 0x3c010001, 0x10000067, 0xac225590, 0x3c020001, +0x8c4255c0, 0x10400063, 0x0, 0x3c040001, 0x8c84559c, 0x10800055, +0x30820008, 0x3c030001, 0x8c6355ac, 0x1062005b, 0x24020003, 0x3c010001, +0xac2455c8, 0xaca20000, 0x24020006, 0x3c010001, 0x10000054, 0xac225590, +0x8f820200, 0x34420002, 0xaf820200, 0x8f830054, 0x2402000d, 0x3c010001, +0xac225590, 0x3c010001, 0xac2355b4, 0x8f830054, 0x3c020001, 0x8c4255b4, +0x2463d8f0, 0x431023, 0x2c422710, 0x14400031, 0x0, 0x3c020001, +0x8c4255d0, 0x10400020, 0x2402000e, 0x3c030001, 0x8c6355e4, 0x3c010001, +0x14600015, 0xac225590, 0xc003b6a, 0x0, 0x3c050001, 0x8ca5340c, +0xc0047d1, 0x24040001, 0x3c030001, 0x8c63340c, 0x24020004, 0x14620005, +0x2403fffb, 0x3c020001, 0x8c423408, 0x10000003, 0x2403fff7, 0x3c020001, +0x8c423408, 0x431024, 0x3c010001, 0xac223408, 0x8f830224, 0x3c020200, +0x3c010001, 0xac2355ec, 0x10000020, 0x282a025, 0x3c020001, 0x8c4255c0, +0x10400005, 0x0, 0x3c020001, 0x8c42559c, 0x1040000f, 0x24020002, +0x3c020001, 0x8c4255a0, 0x2c424e21, 0x1040000a, 0x24020002, 0x3c020001, +0x8c4255c0, 0x1040000f, 0x0, 0x3c020001, 0x8c42559c, 0x1440000b, +0x0, 0x24020002, 0x3c010001, 0x10000007, 0xac225590, 0x3c020001, +0x8c4255c0, 0x10400003, 0x0, 0xc003ab1, 0x0, 0x8f820220, +0x3c03f700, 0x431025, 0xaf820220, 0x8fbf0010, 0x3e00008, 0x27bd0018, +0x3c030001, 0x246355e8, 0x8c620000, 0x10400005, 0x34422000, 0x3c010001, +0xac2255dc, 0x10000003, 0xac600000, 0x3c010001, 0xac2455dc, 0x3e00008, +0x0, 0x27bdffe0, 0x30820030, 0xafbf0018, 0x3c010001, 0xac2255e4, +0x14400067, 0x3c02ffff, 0x34421f0e, 0x821024, 0x14400061, 0x24020030, +0x30822000, 0x1040005d, 0x30838000, 0x31a02, 0x30820001, 0x21200, +0x3c040001, 0x8c84352c, 0x621825, 0x331c2, 0x3c030001, 0x2463348c, +0x30828000, 0x21202, 0x30840001, 0x42200, 0x441025, 0x239c2, +0x61080, 0x431021, 0x471021, 0x90430000, 0x24020001, 0x10620025, +0x0, 0x10600007, 0x24020002, 0x10620013, 0x24020003, 0x1062002c, +0x3c05000f, 0x10000037, 0x0, 0x8f820200, 0x2403feff, 0x431024, +0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220, +0x3c010001, 0xac205624, 0x3c010001, 0x10000034, 0xac20562c, 0x8f820200, +0x34420100, 0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, +0xaf820220, 0x24020100, 0x3c010001, 0xac225624, 0x3c010001, 0x10000026, +0xac20562c, 0x8f820200, 0x2403feff, 0x431024, 0xaf820200, 0x8f820220, +0x3c030001, 0x431025, 0xaf820220, 0x3c010001, 0xac205624, 0x3c010001, +0x10000019, 0xac23562c, 0x8f820200, 0x34420100, 0xaf820200, 0x8f820220, +0x3c030001, 0x431025, 0xaf820220, 0x24020100, 0x3c010001, 0xac225624, +0x3c010001, 0x1000000c, 0xac23562c, 0x34a5ffff, 0x3c040001, 0x248432e8, +0xafa30010, 0xc00290f, 0xafa00014, 0x10000004, 0x0, 0x24020030, +0x3c010001, 0xac2255e8, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0, +0x27bdffc8, 0xafb30024, 0x809821, 0xafbe002c, 0xa0f021, 0xafb10020, +0xc08821, 0x3c040001, 0x24843300, 0x3c050009, 0x3c020001, 0x8c42340c, +0x34a59001, 0x2603021, 0x3c03821, 0xafbf0030, 0xafb50028, 0xa7a0001a, +0xafb10014, 0xc00290f, 0xafa20010, 0x24020002, 0x13c200e7, 0x2fc20003, +0x10400005, 0x24020001, 0x13c2000a, 0x3c02fffb, 0x100000e1, 0x0, +0x24020004, 0x13c2006d, 0x24020008, 0x13c2006c, 0x3c02ffec, 0x100000da, +0x0, 0x3442ffff, 0x2228824, 0x13a940, 0x3c010001, 0x350821, +0xac3155fc, 0x3c024000, 0x2221024, 0x10400046, 0x1123c2, 0x30840030, +0x111382, 0x3042000c, 0x3c030001, 0x24633434, 0x431021, 0x823821, +0x3c020020, 0x2221024, 0x10400006, 0x24020100, 0x3c010001, 0x350821, +0xac225600, 0x10000005, 0x3c020080, 0x3c010001, 0x350821, 0xac205600, +0x3c020080, 0x2221024, 0x10400006, 0x131940, 0x3c020001, 0x3c010001, +0x230821, 0x10000005, 0xac225608, 0x131140, 0x3c010001, 0x220821, +0xac205608, 0x94e30000, 0x32224000, 0x10400003, 0xa7a30018, 0x34624000, +0xa7a20018, 0x24040001, 0x94e20002, 0x24050004, 0x24e60002, 0x34420001, +0xc004076, 0xa4e20002, 0x24040001, 0x2821, 0xc004076, 0x27a60018, +0x3c020001, 0x8c42340c, 0x24130001, 0x3c010001, 0xac333418, 0x145e0004, +0x32228000, 0xc003ab1, 0x0, 0x32228000, 0x10400093, 0x0, +0xc003ab1, 0x0, 0x24020002, 0x3c010001, 0xac333410, 0x3c010001, +0x1000008b, 0xac22340c, 0x24040001, 0x24050004, 0x27b1001a, 0xc004076, +0x2203021, 0x24040001, 0x2821, 0xc004076, 0x2203021, 0x3c020001, +0x551021, 0x8c4255f4, 0x3c040001, 0x8c84340c, 0x3c03bfff, 0x3463ffff, +0x3c010001, 0xac3e3418, 0x431024, 0x3c010001, 0x350821, 0x109e0072, +0xac2255f4, 0x10000072, 0x0, 0x3c02ffec, 0x3442ffff, 0x2228824, +0x3c020008, 0x2228825, 0x131140, 0x3c010001, 0x220821, 0xac3155f8, +0x3c022000, 0x2221024, 0x10400005, 0x24020001, 0x3c010001, 0xac223528, +0x10000004, 0x3c024000, 0x3c010001, 0xac203528, 0x3c024000, 0x2221024, +0x1440001a, 0x0, 0x3c020001, 0x8c423528, 0x10400005, 0x24022020, +0x3c010001, 0xac22352c, 0x24020001, 0xaee279c8, 0x3c04bfff, 0x131940, +0x3c020001, 0x431021, 0x8c4255f0, 0x3c050001, 0x8ca5340c, 0x3484ffff, +0x441024, 0x3c010001, 0x230821, 0xac2255f0, 0x24020001, 0x10a20044, +0x0, 0x10000040, 0x0, 0x3c020001, 0x8c423528, 0x1040001c, +0x24022000, 0x3c010001, 0xac22352c, 0x3c0300a0, 0x2231024, 0x14430005, +0x131140, 0x3402a000, 0x3c010001, 0x1000002d, 0xac22352c, 0x3c030001, +0x621821, 0x8c6355f8, 0x3c020020, 0x621024, 0x10400004, 0x24022001, +0x3c010001, 0x10000023, 0xac22352c, 0x3c020080, 0x621024, 0x1040001f, +0x3402a001, 0x3c010001, 0x1000001c, 0xac22352c, 0x3c020020, 0x2221024, +0x10400007, 0x131940, 0x24020100, 0x3c010001, 0x230821, 0xac225604, +0x10000006, 0x3c020080, 0x131140, 0x3c010001, 0x220821, 0xac205604, +0x3c020080, 0x2221024, 0x10400006, 0x131940, 0x3c020001, 0x3c010001, +0x230821, 0x10000005, 0xac22560c, 0x131140, 0x3c010001, 0x220821, +0xac20560c, 0x3c030001, 0x8c63340c, 0x24020001, 0x10620003, 0x0, +0xc003ab1, 0x0, 0x8fbf0030, 0x8fbe002c, 0x8fb50028, 0x8fb30024, +0x8fb10020, 0x3e00008, 0x27bd0038, 0x27bdffc8, 0xafb50028, 0xa821, +0xafbe002c, 0xf021, 0xafb30024, 0x9821, 0x24020002, 0xafbf0030, +0xafb10020, 0xafa4001c, 0xa7a00012, 0x10a2006a, 0xa7a00010, 0x2ca20003, +0x10400005, 0x24020001, 0x10a2000a, 0x3c024000, 0x100000ad, 0x2601021, +0x24020004, 0x10a20060, 0x24020008, 0x10a2005e, 0x2601021, 0x100000a6, +0x0, 0x8fa7001c, 0x78940, 0x3c030001, 0x711821, 0x8c6355fc, +0x621024, 0x14400009, 0x24040001, 0x3c027fff, 0x3442ffff, 0x629824, +0x3c010001, 0x310821, 0xac3355f4, 0x10000096, 0x2601021, 0x24050001, +0xc004034, 0x27a60010, 0x24040001, 0x24050001, 0xc004034, 0x27a60010, +0x97a20010, 0x30420004, 0x10400034, 0x3c134000, 0x3c030001, 0x8c63353c, +0x24020003, 0x10620008, 0x2c620004, 0x14400029, 0x3c028000, 0x24020004, +0x10620014, 0x24040001, 0x10000024, 0x3c028000, 0x24040001, 0x24050011, +0x27b10012, 0xc004034, 0x2203021, 0x24040001, 0x24050011, 0xc004034, +0x2203021, 0x97a30012, 0x30624000, 0x10400002, 0x3c1e0010, 0x3c1e0008, +0x3c150001, 0x10000010, 0x30628000, 0x24050014, 0x27b10012, 0xc004034, +0x2203021, 0x24040001, 0x24050014, 0xc004034, 0x2203021, 0x97a30012, +0x30621000, 0x10400002, 0x3c1e0010, 0x3c1e0008, 0x3c150001, 0x30620800, +0x54400001, 0x3c150002, 0x3c028000, 0x2621025, 0x2be1825, 0x10000007, +0x439825, 0x3c130001, 0x2719821, 0x8e7355fc, 0x3c027fff, 0x3442ffff, +0x2629824, 0x8fa7001c, 0x71140, 0x3c010001, 0x220821, 0xac3355f4, +0x1000004b, 0x2601021, 0x8fa7001c, 0x72140, 0x3c030001, 0x641821, +0x8c6355f8, 0x3c024000, 0x621024, 0x14400008, 0x3c027fff, 0x3442ffff, +0x629824, 0x3c010001, 0x240821, 0xac3355f0, 0x1000003b, 0x2601021, +0x3c020001, 0x8c42341c, 0x1040002e, 0x3c13c00c, 0x3c020001, 0x8c423528, +0x3c03e00c, 0x3c010001, 0x240821, 0x8c245604, 0x2102b, 0x21023, +0x431024, 0x10800004, 0x539825, 0x3c020020, 0x10000004, 0x2629825, +0x3c02ffdf, 0x3442ffff, 0x2629824, 0x8fa7001c, 0x71140, 0x3c010001, +0x220821, 0x8c22560c, 0x10400003, 0x3c020080, 0x10000004, 0x2629825, +0x3c02ff7f, 0x3442ffff, 0x2629824, 0x3c020001, 0x8c423480, 0x10400002, +0x3c020800, 0x2629825, 0x3c020001, 0x8c423484, 0x10400002, 0x3c020400, +0x2629825, 0x3c020001, 0x8c423488, 0x10400006, 0x3c020100, 0x10000004, +0x2629825, 0x3c027fff, 0x3442ffff, 0x629824, 0x8fa7001c, 0x71140, +0x3c010001, 0x220821, 0xac3355f0, 0x2601021, 0x8fbf0030, 0x8fbe002c, +0x8fb50028, 0x8fb30024, 0x8fb10020, 0x3e00008, 0x27bd0038, 0x27bdffe0, +0xafb50018, 0x80a821, 0xafbf001c, 0xafb30014, 0xafb10010, 0x8f840200, +0x3c030001, 0x8c63340c, 0x8f860220, 0x24020002, 0x106200a3, 0x2c620003, +0x10400005, 0x24020001, 0x1062000a, 0x151940, 0x1000009d, 0x0, +0x24020004, 0x10620053, 0x24020008, 0x10620052, 0x159940, 0x10000096, +0x0, 0x3c050001, 0xa32821, 0x8ca555fc, 0x3c110001, 0x2238821, +0x8e3155f4, 0x3c024000, 0xa21024, 0x10400038, 0x3c020008, 0x2221024, +0x10400020, 0x34840002, 0x3c020001, 0x431021, 0x8c425600, 0x10400005, +0x34840020, 0x34840100, 0x3c020020, 0x10000006, 0x2228825, 0x2402feff, +0x822024, 0x3c02ffdf, 0x3442ffff, 0x2228824, 0x151140, 0x3c010001, +0x220821, 0x8c225608, 0x10400005, 0x3c020001, 0xc23025, 0x3c020080, +0x10000016, 0x2228825, 0x3c02fffe, 0x3442ffff, 0xc23024, 0x3c02ff7f, +0x3442ffff, 0x1000000f, 0x2228824, 0x2402fedf, 0x822024, 0x3c02fffe, +0x3442ffff, 0xc23024, 0x3c02ff5f, 0x3442ffff, 0x2228824, 0x3c010001, +0x230821, 0xac205600, 0x3c010001, 0x230821, 0xac205608, 0xaf840200, +0xaf860220, 0x8f820220, 0x34420002, 0xaf820220, 0x1000000a, 0x151140, +0x3c02bfff, 0x3442ffff, 0x8f830200, 0x2228824, 0x2402fffd, 0x621824, +0xc003ab1, 0xaf830200, 0x151140, 0x3c010001, 0x220821, 0x10000048, +0xac3155f4, 0x159940, 0x3c050001, 0xb32821, 0x8ca555f8, 0x3c110001, +0x2338821, 0x8e3155f0, 0x3c024000, 0xa21024, 0x14400010, 0x0, +0x3c020001, 0x8c423528, 0x14400005, 0x3c02bfff, 0x8f820200, 0x34420002, +0xaf820200, 0x3c02bfff, 0x3442ffff, 0xc003ab1, 0x2228824, 0x3c010001, +0x330821, 0x1000002e, 0xac3155f0, 0x3c020001, 0x8c423528, 0x14400027, +0x151140, 0x3c020020, 0xa21024, 0x10400007, 0x34840020, 0x24020100, +0x3c010001, 0x330821, 0xac225604, 0x10000006, 0x34840100, 0x3c010001, +0x330821, 0xac205604, 0x2402feff, 0x822024, 0x3c020080, 0xa21024, +0x10400007, 0x151940, 0x3c020001, 0x3c010001, 0x230821, 0xac22560c, +0x10000008, 0xc23025, 0x151140, 0x3c010001, 0x220821, 0xac20560c, +0x3c02fffe, 0x3442ffff, 0xc23024, 0xaf840200, 0xaf860220, 0x8f820220, +0x34420002, 0xaf820220, 0x151140, 0x3c010001, 0x220821, 0xac3155f0, +0x8fbf001c, 0x8fb50018, 0x8fb30014, 0x8fb10010, 0x3e00008, 0x27bd0020, +0x0, 0x0, 0x1821, 0x308400ff, 0x2405ffdf, 0x2406ffbf, +0x641007, 0x30420001, 0x10400004, 0x0, 0x8f820044, 0x10000003, +0x34420040, 0x8f820044, 0x461024, 0xaf820044, 0x8f820044, 0x34420020, +0xaf820044, 0x8f820044, 0x451024, 0xaf820044, 0x24630001, 0x28620008, +0x5440ffee, 0x641007, 0x3e00008, 0x0, 0x0, 0x0, +0x0 }; +u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] __init = { 0x1, 0x1, 0x1, 0xc001fc, 0x3ffc, 0xc00000, 0x416c7465, 0x6f6e2041, 0x63654e49, 0x43205600, 0x0, 0x0, 0x416c7465, 0x6f6e2041, 0x63654e49, 0x43205600, 0x42424242, 0x0, @@ -5373,7 +5408,7 @@ u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] = { 0x12000060, 0x12000180, 0x120001e0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30001, 0x1, 0x30201, 0x0, 0x0 }; -u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] = { +u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __init = { 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f667732, 0x2f636f6d, 0x6d6f6e2f, 0x66776d61, 0x696e2e63, 0x2c762031, 0x2e312e34, 0x372e3420, 0x31393938, 0x2f31302f, @@ -5429,12 +5464,14 @@ u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] = { 0x0, 0x4d634465, 0x6c4e6f45, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f667732, 0x2f636f6d, 0x6d6f6e2f, 0x646d612e, 0x632c7620, 0x312e312e, -0x31322e31, 0x20313939, 0x382f3038, 0x2f303420, 0x32313a35, 0x343a3339, +0x31322e33, 0x20313939, 0x382f3132, 0x2f303420, 0x32323a35, 0x313a3135, 0x20736875, 0x616e6720, 0x45787020, 0x24000000, 0x3f6e6f51, 0x64547845, 0x0, 0x3f6e6f51, 0x64527845, 0x0, 0x6576526e, 0x6746756c, 0x6c000000, 0x3f456e71, 0x45767400, 0x3f6e6f51, 0x64457650, 0x0, 0x6661696c, 0x456e454d, 0x0, 0x656e714d, 0x45764661, 0x696c0000, 0x656e714d, 0x45765046, 0x61696c00, 0x646d6172, 0x6441544e, 0x0, +0x2a50414e, 0x49432a00, 0x2e2e2f2e, 0x2e2f2e2e, 0x2f2e2e2f, 0x2e2e2f73, +0x72632f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 0x6e2f646d, 0x612e6300, 0x646d6177, 0x7241544e, 0x0, 0x0, 0x0, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f667732, 0x2f636f6d, 0x6d6f6e2f, 0x74726163, @@ -5444,9 +5481,9 @@ u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] = { 0x772f6765, 0x2f6e6963, 0x2f667732, 0x2f636f6d, 0x6d6f6e2f, 0x64617461, 0x2e632c76, 0x20312e31, 0x2e322e34, 0x20313939, 0x382f3036, 0x2f323320, 0x30313a32, 0x393a3330, 0x20736875, 0x616e6720, 0x45787020, 0x24000000, -0x46575f56, 0x45525349, 0x4f4e3a20, 0x23312046, 0x7269204f, 0x63742031, -0x36203130, 0x3a31353a, 0x30362050, 0x44542031, 0x39393800, 0x46575f43, -0x4f4d5049, 0x4c455f54, 0x494d453a, 0x2031303a, 0x31353a30, 0x36000000, +0x46575f56, 0x45525349, 0x4f4e3a20, 0x2331204d, 0x6f6e2044, 0x65632037, +0x2031343a, 0x35383a32, 0x34205053, 0x54203139, 0x39380000, 0x46575f43, +0x4f4d5049, 0x4c455f54, 0x494d453a, 0x2031343a, 0x35383a32, 0x34000000, 0x46575f43, 0x4f4d5049, 0x4c455f42, 0x593a2064, 0x65767263, 0x73000000, 0x46575f43, 0x4f4d5049, 0x4c455f48, 0x4f53543a, 0x20636f6d, 0x70757465, 0x0, 0x46575f43, 0x4f4d5049, 0x4c455f44, 0x4f4d4149, 0x4e3a2065, @@ -5469,20 +5506,20 @@ u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] = { 0x756e6b72, 0x64747970, 0x65000000, 0x3f546370, 0x436b7375, 0x6d000000, 0x0, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f667732, 0x2f636f6d, -0x6d6f6e2f, 0x72656376, 0x2e632c76, 0x20312e31, 0x2e322e33, 0x35203139, -0x39382f30, 0x372f3239, 0x2030303a, 0x30373a32, 0x37207368, 0x75616e67, +0x6d6f6e2f, 0x72656376, 0x2e632c76, 0x20312e31, 0x2e34322e, 0x33203139, +0x39382f31, 0x322f3034, 0x2030303a, 0x31303a33, 0x38207368, 0x75616e67, 0x20457870, 0x20240000, 0x3f6e6f51, 0x64547845, 0x0, 0x3f6e6f51, 0x64527845, 0x0, 0x6576526e, 0x6746756c, 0x6c000000, 0x3f456e71, 0x45767400, 0x3f6e6f51, 0x64457650, 0x0, 0x6661696c, 0x456e454d, 0x0, 0x656e714d, 0x45764661, 0x696c0000, 0x656e714d, 0x45765046, 0x61696c00, 0x66726d32, 0x4c617267, 0x65000000, 0x72784e6f, 0x52784264, -0x0, 0x72785144, 0x6d614446, 0x0, 0x72785144, 0x6d614246, -0x0, 0x3f724264, 0x446d6146, 0x0, 0x3f724a42, 0x64446d46, -0x0, 0x0, 0xdabc, 0xdabc, 0xdabc, 0xdabc, -0xdabc, 0xdabc, 0xdabc, 0xdabc, 0xdabc, 0xdabc, -0xdabc, 0xdabc, 0xdabc, 0xdabc, 0xdabc, 0xdaac, -0xdaac, 0xdaac, 0xdabc, 0xdabc, 0xdabc, 0xdabc, -0xdabc, 0xdabc, 0x572d444d, 0x41456e46, 0x0, 0x0, +0x0, 0x72785144, 0x6d447446, 0x0, 0x72785144, 0x6d614446, +0x0, 0x72785144, 0x6d614246, 0x0, 0x3f724264, 0x446d6146, +0x0, 0x3f724a42, 0x64446d46, 0x0, 0xdbe8, 0xdbe8, +0xdbe8, 0xdbe8, 0xdbe8, 0xdbe8, 0xdbe8, 0xdbe8, +0xdbe8, 0xdbe8, 0xdbe8, 0xdbe8, 0xdbe8, 0xdbe8, +0xdbe8, 0xdbd8, 0xdbd8, 0xdbd8, 0xdbe8, 0xdbe8, +0xdbe8, 0xdbe8, 0xdbe8, 0xdbe8, 0x572d444d, 0x41456e46, 0x0, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f667732, 0x2f636f6d, 0x6d6f6e2f, 0x6d61632e, 0x632c7620, 0x312e312e, 0x31372e31, 0x20313939, @@ -5503,15 +5540,15 @@ u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] = { 0x64457650, 0x0, 0x6661696c, 0x456e454d, 0x0, 0x656e714d, 0x45764661, 0x696c0000, 0x656e714d, 0x45765046, 0x61696c00, 0x0, 0x50726f62, 0x65506879, 0x0, 0x6c6e6b41, 0x53535254, 0x0, -0xf81c, 0xf84c, 0xf870, 0xf89c, 0xf8c8, 0xf8dc, -0xf918, 0xfca0, 0xf9c8, 0xfaf4, 0xfa14, 0xfb4c, -0xfb74, 0xfba8, 0xfa58, 0xfca0, 0xfac0, 0xfaf4, -0xfb1c, 0xfb4c, 0xfb74, 0xfba8, 0xfbe4, 0x0, -0x0, 0x0, 0x101fc, 0x102cc, 0x103a4, 0x10474, -0x104d0, 0x105ac, 0x105d4, 0x106b0, 0x106d8, 0x10880, -0x108a8, 0x10a50, 0x10c48, 0x10edc, 0x10df0, 0x10edc, -0x10f08, 0x10a78, 0x10c20, 0x0, 0x1120c, 0x11260, -0x112dc, 0x11308, 0x11358, 0x11394, 0x113c8, 0x11454, -0x1150c, 0x115dc, 0x1161c, 0x116a0, 0x116c4, 0x117d4, +0xf94c, 0xf97c, 0xf9a0, 0xf9cc, 0xf9f8, 0xfa0c, +0xfa48, 0xfdd0, 0xfaf8, 0xfc24, 0xfb44, 0xfc7c, +0xfca4, 0xfcd8, 0xfb88, 0xfdd0, 0xfbf0, 0xfc24, +0xfc4c, 0xfc7c, 0xfca4, 0xfcd8, 0xfd14, 0x0, +0x0, 0x0, 0x1032c, 0x103fc, 0x104d4, 0x105a4, +0x10600, 0x106dc, 0x10704, 0x107e0, 0x10808, 0x109b0, +0x109d8, 0x10b80, 0x10d78, 0x1100c, 0x10f20, 0x1100c, +0x11038, 0x10ba8, 0x10d50, 0x0, 0x1133c, 0x11390, +0x1140c, 0x11438, 0x11488, 0x114c4, 0x114f8, 0x11584, +0x1163c, 0x1170c, 0x1174c, 0x117d0, 0x117f4, 0x11904, 0x646f4261, 0x73655067, 0x0, 0x0, 0x0, 0x0, 0x73746d61, 0x634c4e4b, 0x0, 0x0, 0x0 }; diff --git a/drivers/net/apne.c b/drivers/net/apne.c index d3578f5daa71..f4e682f4d473 100644 --- a/drivers/net/apne.c +++ b/drivers/net/apne.c @@ -119,22 +119,26 @@ static int init_pcmcia(void); static const char *version = "apne.c:v1.1 7/10/98 Alain Malek (Alain.Malek@cryogen.ch)\n"; +static int apne_owned = 0; /* signal if card already owned */ __initfunc(int apne_probe(struct device *dev)) { #ifndef MANUAL_CONFIG char tuple[8]; #endif + + if (apne_owned) + return -ENODEV; if ( !(AMIGAHW_PRESENT(PCMCIA)) ) - return (ENODEV); + return (-ENODEV); printk("Looking for PCMCIA ethernet card : "); /* check if a card is inserted */ if (!(PCMCIA_INSERTED)) { printk("NO PCMCIA card inserted\n"); - return (ENODEV); + return (-ENODEV); } /* disable pcmcia irq for readtuple */ @@ -144,7 +148,7 @@ __initfunc(int apne_probe(struct device *dev)) if ((pcmcia_copy_tuple(CISTPL_FUNCID, tuple, 8) < 3) || (tuple[2] != CISTPL_FUNCID_NETWORK)) { printk("not an ethernet card\n"); - return (ENODEV); + return (-ENODEV); } #endif @@ -153,7 +157,7 @@ __initfunc(int apne_probe(struct device *dev)) if (init_pcmcia()) return apne_probe1(dev, IOBASE+GAYLE_IO); else - return (ENODEV); + return (-ENODEV); } @@ -169,7 +173,7 @@ __initfunc(static int apne_probe1(struct device *dev, int ioaddr)) int neX000, ctron; #endif static unsigned version_printed = 0; - static int pcmcia_offsets[16]={ + static u32 pcmcia_offsets[16]={ 0, 1+GAYLE_ODD, 2, 3+GAYLE_ODD, 4, 5+GAYLE_ODD, 6, 7+GAYLE_ODD, 8, 9+GAYLE_ODD, 0xa, 0xb+GAYLE_ODD, @@ -197,7 +201,7 @@ __initfunc(static int apne_probe1(struct device *dev, int ioaddr)) while ((readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0) if (jiffies - reset_start_time > 2*HZ/100) { printk(" not found (no reset ack).\n"); - return ENODEV; + return -ENODEV; } writeb(0xff, ioaddr + NE_EN0_ISR); /* Ack all intr. */ @@ -328,6 +332,8 @@ __initfunc(static int apne_probe1(struct device *dev, int ioaddr)) pcmcia_ack_int(pcmcia_get_intreq()); /* ack PCMCIA int req */ pcmcia_enable_irq(); + apne_owned = 1; + return 0; } @@ -390,7 +396,7 @@ apne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page) /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { printk("%s: DMAing conflict in ne_get_8390_hdr " - "[DMAstat:%d][irqlock:%d][intr:%d].\n", + "[DMAstat:%d][irqlock:%d][intr:%ld].\n", dev->name, ei_status.dmaing, ei_status.irqlock, dev->interrupt); return; @@ -439,7 +445,7 @@ apne_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_of /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { printk("%s: DMAing conflict in ne_block_input " - "[DMAstat:%d][irqlock:%d][intr:%d].\n", + "[DMAstat:%d][irqlock:%d][intr:%ld].\n", dev->name, ei_status.dmaing, ei_status.irqlock, dev->interrupt); return; @@ -488,7 +494,7 @@ apne_block_output(struct device *dev, int count, /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { printk("%s: DMAing conflict in ne_block_output." - "[DMAstat:%d][irqlock:%d][intr:%d]\n", + "[DMAstat:%d][irqlock:%d][intr:%ld]\n", dev->name, ei_status.dmaing, ei_status.irqlock, dev->interrupt); return; @@ -577,15 +583,17 @@ int init_module(void) void cleanup_module(void) { + unregister_netdev(&apne_dev); + pcmcia_disable_irq(); free_irq(IRQ_AMIGA_PORTS, &apne_dev); pcmcia_reset(); - unregister_netdev(&apne_dev); - unlock_8390_module(); + + apne_owned = 0; } #endif diff --git a/drivers/net/ariadne2.c b/drivers/net/ariadne2.c index 0b71b5987088..f73d491e1c6f 100644 --- a/drivers/net/ariadne2.c +++ b/drivers/net/ariadne2.c @@ -107,7 +107,7 @@ __initfunc(static int ariadne2_init(struct device *dev, unsigned int key, unsigned char SA_prom[32]; const char *name = NULL; int start_page, stop_page; - static int ariadne2_offsets[16] = { + static u32 ariadne2_offsets[16] = { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, }; diff --git a/drivers/net/cosa.c b/drivers/net/cosa.c new file mode 100644 index 000000000000..28f1901029b5 --- /dev/null +++ b/drivers/net/cosa.c @@ -0,0 +1,1890 @@ +/* $Id: cosa.c,v 1.9 1998/12/08 02:24:23 kas Exp $ */ + +/* + * Copyright (C) 1995-1997 Jan "Yenya" Kasprzak + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * The driver for the SRP and COSA synchronous serial cards. + * + * HARDWARE INFO + * + * Both cards are developed at the Institute of Computer Science, + * Masaryk University (http://www.ics.muni.cz/). The hardware is + * developed by Jiri Novotny . More information + * and the photo of both cards is available at + * http://www.kozakmartin.cz/cosa.html. The card documentation, firmwares + * and other goods can be downloaded from ftp://ftp.ics.muni.cz/pub/cosa/. + * For Linux-specific utilities, see below in the "Software info" section. + * If you want to order the card, contact Jiri Novotny. + * + * The SRP (serial port?, the Czech word "srp" means "sickle") card + * is a 2-port intelligent (with its own 8-bit CPU) synchronous serial card + * with V.24 interfaces up to 80kb/s each. + * + * The COSA (communication serial adapter?, the Czech word "kosa" means + * "scythe") is a next-generation sync/async board with two interfaces + * - currently any of V.24, X.21, V.35 and V.36 can be selected. + * It has a 16-bit SAB80166 CPU and can do up to 10 Mb/s per channel. + * The 8-channels version is in development. + * + * Both types have downloadable firmware and communicate via ISA DMA. + * COSA can be also a bus-mastering device. + * + * SOFTWARE INFO + * + * The homepage of the Linux driver is at http://www.fi.muni.cz/~kas/cosa/. + * The CVS tree of Linux driver can be viewed there, as well as the + * firmware binaries and user-space utilities for downloading the firmware + * into the card and setting up the card. + * + * The Linux driver (unlike the present *BSD drivers :-) can work even + * for the COSA and SRP in one computer and allows each channel to work + * in one of the three modes (character device, Cisco HDLC, Sync PPP). + * + * AUTHOR + * + * The Linux driver was written by Jan "Yenya" Kasprzak . + * + * You can mail me bugfixes and even success reports. I am especially + * interested in the SMP and/or muliti-channel success/failure reports + * (I wonder if I did the locking properly :-). + * + * THE AUTHOR USED THE FOLLOWING SOURCES WHEN PROGRAMMING THE DRIVER + * + * The COSA/SRP NetBSD driver by Zdenek Salvet and Ivos Cernohlavek + * The skeleton.c by Donald Becker + * The SDL Riscom/N2 driver by Mike Natale + * The Comtrol Hostess SV11 driver by Alan Cox + * The Sync PPP/Cisco HDLC layer (syncppp.c) ported to Linux by Alan Cox + */ + +/* ---------- Headers, macros, data structures ---------- */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef COSA_SLOW_IO /* for testing purposes only */ +#undef REALLY_SLOW_IO + +#include +#include +#include +#include + +#include "syncppp.h" +#include "cosa.h" + +/* Maximum length of the identification string. */ +#define COSA_MAX_ID_STRING 128 + +/* Maximum length of the channel name */ +#define COSA_MAX_NAME (sizeof("cosaXXXcXXX")+1) + +/* Per-channel data structure */ + +struct channel_data { + int usage; /* Usage count; >0 for chrdev, -1 for netdev */ + int num; /* Number of the channel */ + struct cosa_data *cosa; /* Pointer to the per-card structure */ + int txsize; /* Size of transmitted data */ + char *txbuf; /* Transmit buffer */ + char name[COSA_MAX_NAME]; /* channel name */ + + /* The HW layer interface */ + /* routine called from the RX interrupt */ + char *(*setup_rx)(struct channel_data *channel, int size); + /* routine called when the RX is done (from the EOT interrupt) */ + int (*rx_done)(struct channel_data *channel); + /* routine called when the TX is done (from the EOT interrupt) */ + int (*tx_done)(struct channel_data *channel, int size); + + /* Character device parts */ + struct semaphore rsem, wsem; + char *rxdata; + int rxsize; + struct wait_queue *txwaitq, *rxwaitq; + int tx_status, rx_status; + + /* SPPP/HDLC device parts */ + struct ppp_device pppdev; + struct sk_buff *rx_skb, *tx_skb; + struct net_device_stats stats; +}; + +struct cosa_data { + int num; /* Card number */ + char name[COSA_MAX_NAME]; /* Card name - e.g "cosa0" */ + unsigned int datareg, statusreg; /* I/O ports */ + unsigned short irq, dma; /* IRQ and DMA number */ + unsigned short startaddr; /* Firmware start address */ + int nchannels; /* # of channels on this card */ + int driver_status; /* For communicating with firware */ + int firmware_status; /* Downloaded, reseted, etc. */ + int rxbitmap, txbitmap; /* Bitmap of channels who are willing to send/receive data */ + int rxtx; /* RX or TX in progress? */ + int usage; /* usage count */ + int txchan, txsize, rxsize; + struct channel_data *rxchan; + char *bouncebuf; + char *txbuf, *rxbuf; + struct channel_data *chan; + spinlock_t lock; /* For exclusive operations on this structure */ + char id_string[COSA_MAX_ID_STRING]; /* ROM monitor ID string */ + char *type; /* card type */ +}; + +/* + * Define this if you want all the possible ports to be autoprobed. + * It is here but it probably is not a good idea to use this. + */ +/* #define COSA_ISA_AUTOPROBE 1 */ + +/* + * Character device major number. 117 was allocated for us. + * The value of 0 means to allocate a first free one. + */ +static int cosa_major = 117; + +/* + * Encoding of the minor numbers: + * The lowest CARD_MINOR_BITS bits means the channel on the single card, + * the highest bits means the card number. + */ +#define CARD_MINOR_BITS 4 /* How many bits in minor number are reserved + * for the single card */ +/* + * The following depends on CARD_MINOR_BITS. Unfortunately, the "MODULE_STRING" + * macro doesn't like anything other than the raw number as an argument :-( + */ +#define MAX_CARDS 16 +/* #define MAX_CARDS (1 << (8-CARD_MINOR_BITS)) */ + +#define DRIVER_RX_READY 0x0001 +#define DRIVER_TX_READY 0x0002 +#define DRIVER_TXMAP_SHIFT 2 +#define DRIVER_TXMAP_MASK 0x0c /* FIXME: 0xfc for 8-channel version */ + +/* + * for cosa->rxtx - indicates whether either transmit or receive is + * in progress. These values are mean number of the bit. + */ +#define TXBIT 0 +#define RXBIT 1 +#define IRQBIT 2 + +#define COSA_MTU 2000 /* FIXME: I don't know this exactly */ + +#undef DEBUG_DATA 1 /* Dump the data read or written to the channel */ +#undef DEBUG_IRQS 1 /* Print the message when the IRQ is received */ +#undef DEBUG_IO 1 /* Dump the I/O traffic */ + +/* Maybe the following should be allocated dynamically */ +static struct cosa_data cosa_cards[MAX_CARDS]; +static int nr_cards = 0; + +#ifdef COSA_ISA_AUTOPROBE +static int io[MAX_CARDS+1] = { 0x220, 0x228, 0x210, 0x218, 0, }; +/* NOTE: DMA is not autoprobed!!! */ +static int dma[MAX_CARDS+1] = { 1, 7, 1, 7, 1, 7, 1, 7, 0, }; +#else +int io[MAX_CARDS+1] = { 0, }; +int dma[MAX_CARDS+1] = { 0, }; +#endif +/* IRQ can be safely autoprobed */ +static int irq[MAX_CARDS+1] = { -1, -1, -1, -1, -1, -1, 0, }; + +#ifdef MODULE +MODULE_PARM(io, "1-" __MODULE_STRING(MAX_CARDS) "i"); +MODULE_PARM_DESC(io, "The I/O bases of the COSA or SRP cards"); +MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_CARDS) "i"); +MODULE_PARM_DESC(irq, "The IRQ lines of the COSA or SRP cards"); +MODULE_PARM(dma, "1-" __MODULE_STRING(MAX_CARDS) "i"); +MODULE_PARM_DESC(dma, "The DMA channels of the COSA or SRP cards"); + +MODULE_AUTHOR("Jan \"Yenya\" Kasprzak, "); +MODULE_DESCRIPTION("Modular driver for the COSA or SRP synchronous card"); +#endif + +/* I use this mainly for testing purposes */ +#ifdef COSA_SLOW_IO +#define cosa_outb outb_p +#define cosa_outw outw_p +#define cosa_inb inb_p +#define cosa_inw inw_p +#else +#define cosa_outb outb +#define cosa_outw outw +#define cosa_inb inb +#define cosa_inw inw +#endif + +#define is_8bit(cosa) (!(cosa->datareg & 0x08)) + +#define cosa_getstatus(cosa) (cosa_inb(cosa->statusreg)) +#define cosa_putstatus(cosa, stat) (cosa_outb(stat, cosa->statusreg)) +#define cosa_getdata16(cosa) (cosa_inw(cosa->datareg)) +#define cosa_getdata8(cosa) (cosa_inb(cosa->datareg)) +#define cosa_putdata16(cosa, dt) (cosa_outw(dt, cosa->datareg)) +#define cosa_putdata8(cosa, dt) (cosa_outb(dt, cosa->datareg)) + +/* Initialization stuff */ +static int cosa_probe(int ioaddr, int irq, int dma); + +/* HW interface */ +static void cosa_enable_rx(struct channel_data *chan); +static void cosa_disable_rx(struct channel_data *chan); +static int cosa_start_tx(struct channel_data *channel, char *buf, int size); +static void cosa_kick(struct cosa_data *cosa); +static int cosa_dma_able(struct channel_data *chan, char *buf, int data); + +/* SPPP/HDLC stuff */ +static void sppp_channel_init(struct channel_data *chan); +static void sppp_channel_delete(struct channel_data *chan); +static int cosa_sppp_open(struct device *d); +static int cosa_sppp_close(struct device *d); +static int cosa_sppp_tx(struct sk_buff *skb, struct device *d); +static char *sppp_setup_rx(struct channel_data *channel, int size); +static int sppp_rx_done(struct channel_data *channel); +static int sppp_tx_done(struct channel_data *channel, int size); +static int cosa_sppp_ioctl(struct device *dev, struct ifreq *ifr, int cmd); +static struct net_device_stats *cosa_net_stats(struct device *dev); + +/* Character device */ +static void chardev_channel_init(struct channel_data *chan); +static char *chrdev_setup_rx(struct channel_data *channel, int size); +static int chrdev_rx_done(struct channel_data *channel); +static int chrdev_tx_done(struct channel_data *channel, int size); +static long long cosa_lseek(struct file *file, + long long offset, int origin); +static ssize_t cosa_read(struct file *file, + char *buf, size_t count, loff_t *ppos); +static ssize_t cosa_write(struct file *file, + const char *buf, size_t count, loff_t *ppos); +static unsigned int cosa_poll(struct file *file, poll_table *poll); +static int cosa_open(struct inode *inode, struct file *file); +static int cosa_release(struct inode *inode, struct file *file); +static int cosa_chardev_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); +#ifdef COSA_FASYNC_WORKING +static int cosa_fasync(struct inode *inode, struct file *file, int on); +#endif + +static struct file_operations cosa_fops = { + cosa_lseek, + cosa_read, + cosa_write, + NULL, /* readdir */ + cosa_poll, + cosa_chardev_ioctl, + NULL, /* mmap */ + cosa_open, + NULL, /* flush */ + cosa_release, + NULL, /* fsync */ +#ifdef COSA_FASYNC_WORKING + cosa_fasync, +#else + NULL, +#endif + NULL, /* check media change */ + NULL, /* revalidate */ + NULL /* lock */ +}; + +/* Ioctls */ +static int cosa_start(struct cosa_data *cosa, int address); +static int cosa_reset(struct cosa_data *cosa); +static int cosa_download(struct cosa_data *cosa, struct cosa_download *d); +static int cosa_readmem(struct cosa_data *cosa, struct cosa_download *d); + +/* COSA/SRP ROM monitor */ +static int download(struct cosa_data *cosa, char *data, int addr, int len); +static int startmicrocode(struct cosa_data *cosa, int address); +static int readmem(struct cosa_data *cosa, char *data, int addr, int len); +static int cosa_reset_and_read_id(struct cosa_data *cosa, char *id); + +/* Auxilliary functions */ +static int get_wait_data(struct cosa_data *cosa); +static int put_wait_data(struct cosa_data *cosa, int data); +static int puthexnumber(struct cosa_data *cosa, int number); +static void put_driver_status_common(struct cosa_data *cosa, int nolock); +#define put_driver_status(x) put_driver_status_common((x), 0) +#define put_driver_status_nolock(x) put_driver_status_common((x), 1) + +/* Interrupt handling */ +static void cosa_interrupt(int irq, void *cosa, struct pt_regs *regs); + +/* I/O ops debugging */ +#ifdef DEBUG_IO +static void debug_data_in(struct cosa_data *cosa, int data); +static void debug_data_out(struct cosa_data *cosa, int data); +static void debug_data_cmd(struct cosa_data *cosa, int data); +static void debug_status_in(struct cosa_data *cosa, int status); +static void debug_status_out(struct cosa_data *cosa, int status); +#endif + + +/* ---------- Initialization stuff ---------- */ + +#ifdef MODULE +int init_module(void) +#else +__initfunc(static int cosa_init(void)) +#endif +{ + int i; + printk(KERN_INFO "cosa v1.02 (c) 1997-8 Jan Kasprzak \n"); +#ifdef __SMP__ + printk(KERN_INFO "cosa: SMP found. Please mail any success/failure reports to the author.\n"); +#endif + if (cosa_major > 0) { + if (register_chrdev(cosa_major, "cosa", &cosa_fops)) { + printk(KERN_WARNING "cosa: unable to get major %d\n", + cosa_major); + return -EIO; + } + } else { + if (!(cosa_major=register_chrdev(0, "cosa", &cosa_fops))) { + printk(KERN_WARNING "cosa: unable to register chardev\n"); + return -EIO; + } + } + for (i=0; inchannels; i++) { + /* Chardev driver has no alloc'd per-channel data */ + sppp_channel_delete(cosa->chan+i); + } + /* Clean up the per-card data */ + kfree(cosa->chan); + kfree(cosa->bouncebuf); + free_irq(cosa->irq, cosa); + free_dma(cosa->dma); + release_region(cosa->datareg,is_8bit(cosa)?2:4); + } + unregister_chrdev(cosa_major, "cosa"); +} +#endif + +/* + * This function should register all the net devices needed for the + * single channel. + */ +static __inline__ void channel_init(struct channel_data *chan) +{ + sprintf(chan->name, "cosa%dc%d", chan->cosa->num, chan->num); + + /* Initialize the chardev data structures */ + chardev_channel_init(chan); + + /* Register the sppp interface */ + sppp_channel_init(chan); +} + +static int cosa_probe(int base, int irq, int dma) +{ + struct cosa_data *cosa = cosa_cards+nr_cards; + int i; + + memset(cosa, 0, sizeof(struct cosa_data)); + + /* Checking validity of parameters: */ + /* IRQ should be 2-7 or 10-15; negative IRQ means autoprobe */ + if ((irq >= 0 && irq < 2) || irq > 15 || (irq < 10 && irq > 7)) { + printk (KERN_INFO "cosa_probe: invalid IRQ %d\n", irq); + return -1; + } + /* I/O address should be between 0x100 and 0x3ff and should be + * multiple of 8. */ + if (base < 0x100 || base > 0x3ff || base & 0x7) { + printk (KERN_INFO "cosa_probe: invalid I/O address 0x%x\n", + base); + return -1; + } + /* DMA should be 0,1 or 3-7 */ + if (dma < 0 || dma == 4 || dma > 7) { + printk (KERN_INFO "cosa_probe: invalid DMA %d\n", dma); + return -1; + } + /* and finally, on 16-bit COSA DMA should be 4-7 and + * I/O base should not be multiple of 0x10 */ + if (((base & 0x8) && dma < 4) || (!(base & 0x8) && dma > 3)) { + printk (KERN_INFO "cosa_probe: 8/16 bit base and DMA mismatch" + " (base=0x%x, dma=%d)\n", base, dma); + return -1; + } + + cosa->dma = dma; + cosa->datareg = base; + cosa->statusreg = is_8bit(cosa)?base+1:base+2; + spin_lock_init(&cosa->lock); + + if (check_region(base, is_8bit(cosa)?2:4)) + return -1; + + if (cosa_reset_and_read_id(cosa, cosa->id_string) < 0) { + printk(KERN_DEBUG "cosa: probe at 0x%x failed.\n", base); + return -1; + } + + /* Test the validity of identification string */ + if (!strncmp(cosa->id_string, "SRP", 3)) + cosa->type = "srp"; + else if (!strncmp(cosa->id_string, "COSA", 4)) + cosa->type = is_8bit(cosa)? "cosa8": "cosa16"; + else { +/* Print a warning only if we are not autoprobing */ +#ifndef COSA_ISA_AUTOPROBE + printk(KERN_INFO "cosa: valid signature not found at 0x%x.\n", + base); +#endif + return -1; + } + + /* Now do IRQ autoprobe */ + if (irq < 0) { + unsigned long irqs; +/* printk(KERN_INFO "IRQ autoprobe\n"); */ + sti(); + irqs = probe_irq_on(); + /* + * Enable interrupt on tx buffer empty (it sure is) + * really sure ? + * FIXME: When this code is not used as module, we should + * probably call udelay() instead of the interruptible sleep. + */ + current->state = TASK_INTERRUPTIBLE; + cosa_putstatus(cosa, SR_TX_INT_ENA); + schedule_timeout(30); + current->state = TASK_RUNNING; + irq = probe_irq_off(irqs); + /* Disable all IRQs from the card */ + cosa_putstatus(cosa, 0); + /* Empty the received data register */ + cosa_getdata8(cosa); + + if (irq < 0) { + printk (KERN_INFO "cosa IRQ autoprobe: multiple interrupts obtained (%d, board at 0x%x)\n", + irq, cosa->datareg); + return -1; + } + if (irq == 0) { + printk (KERN_INFO "cosa IRQ autoprobe: no interrupt obtained (board at 0x%x)\n", + cosa->datareg); + /* return -1; */ + } + } + + cosa->irq = irq; + cosa->num = nr_cards; + cosa->usage = 0; + cosa->nchannels = 2; /* FIXME: how to determine this? */ + + request_region(base, is_8bit(cosa)?2:4, cosa->type); + if (request_irq(cosa->irq, cosa_interrupt, 0, cosa->type, cosa)) + goto bad1; + if (request_dma(cosa->dma, cosa->type)) { + free_irq(cosa->irq, cosa); +bad1: release_region(cosa->datareg,is_8bit(cosa)?2:4); + printk(KERN_NOTICE "cosa%d: allocating resources failed\n", + cosa->num); + return -1; + } + + cosa->bouncebuf = kmalloc(COSA_MTU, GFP_KERNEL|GFP_DMA); + sprintf(cosa->name, "cosa%d", cosa->num); + + /* Initialize the per-channel data */ + cosa->chan = kmalloc(sizeof(struct channel_data)*cosa->nchannels, + GFP_KERNEL); + memset(cosa->chan, 0, sizeof(struct channel_data)*cosa->nchannels); + for (i=0; inchannels; i++) { + cosa->chan[i].cosa = cosa; + cosa->chan[i].num = i; + channel_init(cosa->chan+i); + } + + printk (KERN_INFO "cosa%d: %s (%s at 0x%x irq %d dma %d), %d channels\n", + cosa->num, cosa->id_string, cosa->type, + cosa->datareg, cosa->irq, cosa->dma, cosa->nchannels); + + return nr_cards++; +} + + +/*---------- SPPP/HDLC netdevice ---------- */ + +static void sppp_channel_init(struct channel_data *chan) +{ + struct device *d; + sppp_attach(&chan->pppdev); + d=&chan->pppdev.dev; + d->name = chan->name; + d->base_addr = chan->cosa->datareg; + d->irq = chan->cosa->irq; + d->dma = chan->cosa->dma; + d->priv = chan; + d->init = NULL; + d->open = cosa_sppp_open; + d->stop = cosa_sppp_close; + d->hard_start_xmit = cosa_sppp_tx; + d->do_ioctl = cosa_sppp_ioctl; + d->get_stats = cosa_net_stats; + dev_init_buffers(d); + if (register_netdev(d) == -1) { + printk(KERN_WARNING "%s: register_netdev failed.\n", d->name); + sppp_detach(&chan->pppdev.dev); + return; + } +} + +static void sppp_channel_delete(struct channel_data *chan) +{ + sppp_detach(&chan->pppdev.dev); + unregister_netdev(&chan->pppdev.dev); +} + + +static int cosa_sppp_open(struct device *d) +{ + struct channel_data *chan = d->priv; + int err, flags; + + spin_lock_irqsave(&chan->cosa->lock, flags); + if (chan->usage != 0) { + printk(KERN_WARNING "%s: sppp_open called with usage count %d\n", + chan->name, chan->usage); + return -EBUSY; + } + chan->setup_rx = sppp_setup_rx; + chan->tx_done = sppp_tx_done; + chan->rx_done = sppp_rx_done; + chan->usage=-1; + chan->cosa->usage++; + MOD_INC_USE_COUNT; + spin_unlock_irqrestore(&chan->cosa->lock, flags); + + err = sppp_open(d); + if (err) { + spin_lock_irqsave(&chan->cosa->lock, flags); + chan->usage=0; + chan->cosa->usage--; + MOD_DEC_USE_COUNT; + + spin_unlock_irqrestore(&chan->cosa->lock, flags); + return err; + } + + d->tbusy = 0; + cosa_enable_rx(chan); + return 0; +} + +static int cosa_sppp_tx(struct sk_buff *skb, struct device *dev) +{ + struct channel_data *chan = dev->priv; + + if (dev->tbusy) { + if (time_before(jiffies, dev->trans_start+2*HZ)) + return 1; /* Two seconds timeout */ + cosa_kick(chan->cosa); + chan->stats.tx_errors++; + chan->stats.tx_aborted_errors++; + if (chan->tx_skb) { + dev_kfree_skb(chan->tx_skb); + chan->tx_skb = 0; + } + dev->tbusy = 0; + } + if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { + printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name); + return 1; + } + + chan->tx_skb = skb; + dev->trans_start = jiffies; + cosa_start_tx(chan, skb->data, skb->len); + return 0; +} + +static int cosa_sppp_close(struct device *d) +{ + struct channel_data *chan = d->priv; + int flags; + + sppp_close(d); + d->tbusy = 1; + cosa_disable_rx(chan); + spin_lock_irqsave(&chan->cosa->lock, flags); + chan->usage=0; + chan->cosa->usage--; + MOD_DEC_USE_COUNT; + spin_unlock_irqrestore(&chan->cosa->lock, flags); + return 0; +} + +static char *sppp_setup_rx(struct channel_data *chan, int size) +{ + /* + * We can safely fall back to non-dma-able memory, because we have + * the cosa->bouncebuf pre-allocated. + */ + if (chan->rx_skb) + kfree_skb(chan->rx_skb); + chan->rx_skb = dev_alloc_skb(size); + if (chan->rx_skb == NULL) { + printk(KERN_NOTICE "%s: Memory squeeze, dropping packet\n", + chan->name); + chan->stats.rx_dropped++; + return NULL; + } + chan->pppdev.dev.trans_start = jiffies; + return skb_put(chan->rx_skb, size); +} + +static int sppp_rx_done(struct channel_data *chan) +{ + if (!chan->rx_skb) { + printk(KERN_WARNING "%s: rx_done with empty skb!\n", + chan->name); + chan->stats.rx_errors++; + chan->stats.rx_frame_errors++; + return 0; + } + chan->rx_skb->protocol = htons(ETH_P_WAN_PPP); + chan->rx_skb->dev = &chan->pppdev.dev; + chan->rx_skb->mac.raw = chan->rx_skb->data; + chan->stats.rx_packets++; + chan->stats.rx_bytes += chan->cosa->rxsize; + netif_rx(chan->rx_skb); + chan->rx_skb = 0; + chan->pppdev.dev.trans_start = jiffies; + return 0; +} + +/* ARGSUSED */ +static int sppp_tx_done(struct channel_data *chan, int size) +{ + if (!chan->tx_skb) { + printk(KERN_WARNING "%s: tx_done with empty skb!\n", + chan->name); + chan->stats.tx_errors++; + chan->stats.tx_aborted_errors++; + return 1; + } + dev_kfree_skb(chan->tx_skb); + chan->tx_skb = 0; + chan->stats.tx_packets++; + chan->stats.tx_bytes += size; + chan->pppdev.dev.tbusy = 0; + mark_bh(NET_BH); + return 1; +} + +static struct net_device_stats *cosa_net_stats(struct device *dev) +{ + struct channel_data *chan = dev->priv; + return &chan->stats; +} + + +/*---------- Character device ---------- */ + +static void chardev_channel_init(struct channel_data *chan) +{ + chan->rsem = MUTEX; + chan->wsem = MUTEX; +} + +static long long cosa_lseek(struct file * file, + long long offset, int origin) +{ + return -ESPIPE; +} + +static ssize_t cosa_read(struct file *file, + char *buf, size_t count, loff_t *ppos) +{ + struct wait_queue wait = { current, NULL }; + int flags; + struct channel_data *chan = (struct channel_data *)file->private_data; + struct cosa_data *cosa = chan->cosa; + char *kbuf; + + if (down_interruptible(&chan->rsem)) + return -ERESTARTSYS; + + if ((chan->rxdata = kmalloc(COSA_MTU, GFP_DMA|GFP_KERNEL)) == NULL) { + printk(KERN_INFO "%s: cosa_read() - OOM\n", cosa->name); + up(&chan->rsem); + return -ENOMEM; + } + + chan->rx_status = 0; + cosa_enable_rx(chan); + spin_lock_irqsave(&cosa->lock, flags); + add_wait_queue(&chan->rxwaitq, &wait); + while(!chan->rx_status) { + current->state = TASK_INTERRUPTIBLE; + spin_unlock_irqrestore(&cosa->lock, flags); + schedule(); + spin_lock_irqsave(&cosa->lock, flags); + if (signal_pending(current) && chan->rx_status == 0) { + chan->rx_status = 1; + remove_wait_queue(&chan->rxwaitq, &wait); + current->state = TASK_RUNNING; + spin_unlock_irqrestore(&cosa->lock, flags); + up(&chan->rsem); + return -ERESTARTSYS; + } + } + remove_wait_queue(&chan->rxwaitq, &wait); + current->state = TASK_RUNNING; + kbuf = chan->rxdata; + count = chan->rxsize; + spin_unlock_irqrestore(&cosa->lock, flags); + up(&chan->rsem); + + if (copy_to_user(buf, kbuf, count)) { + kfree(buf); + return -EFAULT; + } + kfree(kbuf); + return count; +} + +static char *chrdev_setup_rx(struct channel_data *chan, int size) +{ + /* Expect size <= COSA_MTU */ + chan->rxsize = size; + return chan->rxdata; +} + +static int chrdev_rx_done(struct channel_data *chan) +{ + if (chan->rx_status) { /* Reader has died */ + kfree(chan->rxdata); + up(&chan->wsem); + } + chan->rx_status = 1; + wake_up_interruptible(&chan->rxwaitq); + return 1; +} + + +static ssize_t cosa_write(struct file *file, + const char *buf, size_t count, loff_t *ppos) +{ + struct channel_data *chan = (struct channel_data *)file->private_data; + struct wait_queue wait = { current, NULL }; + struct cosa_data *cosa = chan->cosa; + unsigned int flags; + char *kbuf; + + if (down_interruptible(&chan->wsem)) + return -ERESTARTSYS; + + if (count > COSA_MTU) + count = COSA_MTU; + + /* Allocate the buffer */ + if ((kbuf = kmalloc(count, GFP_KERNEL|GFP_DMA)) == NULL) { + printk(KERN_NOTICE "%s: cosa_write() OOM - dropping packet\n", + cosa->name); + up(&chan->wsem); + return -ENOMEM; + } + if (copy_from_user(kbuf, buf, count)) { + up(&chan->wsem); + kfree(kbuf); + return -EFAULT; + } + chan->tx_status=0; + cosa_start_tx(chan, kbuf, count); + + spin_lock_irqsave(&cosa->lock, flags); + add_wait_queue(&chan->txwaitq, &wait); + while(!chan->tx_status) { + current->state = TASK_INTERRUPTIBLE; + spin_unlock_irqrestore(&cosa->lock, flags); + schedule(); + spin_lock_irqsave(&cosa->lock, flags); + if (signal_pending(current) && chan->tx_status == 0) { + chan->tx_status = 1; + remove_wait_queue(&chan->txwaitq, &wait); + current->state = TASK_RUNNING; + chan->tx_status = 1; + spin_unlock_irqrestore(&cosa->lock, flags); + return -ERESTARTSYS; + } + } + remove_wait_queue(&chan->txwaitq, &wait); + current->state = TASK_RUNNING; + up(&chan->wsem); + spin_unlock_irqrestore(&cosa->lock, flags); + kfree(kbuf); + return count; +} + +static int chrdev_tx_done(struct channel_data *chan, int size) +{ + if (chan->tx_status) { /* Writer was interrupted */ + kfree(chan->txbuf); + up(&chan->wsem); + } + chan->tx_status = 1; + wake_up_interruptible(&chan->txwaitq); + return 1; +} + +static unsigned int cosa_poll(struct file *file, poll_table *poll) +{ + printk(KERN_INFO "cosa_poll is here\n"); + return 0; +} + +static int cosa_open(struct inode *inode, struct file *file) +{ + struct cosa_data *cosa; + struct channel_data *chan; + unsigned long flags; + int n; + + if ((n=MINOR(file->f_dentry->d_inode->i_rdev)>>CARD_MINOR_BITS) + >= nr_cards) + return -ENODEV; + cosa = cosa_cards+n; + + if ((n=MINOR(file->f_dentry->d_inode->i_rdev) + & ((1<= cosa->nchannels) + return -ENODEV; + chan = cosa->chan + n; + + file->private_data = chan; + + spin_lock_irqsave(&cosa->lock, flags); + + if (chan->usage < 0) { /* in netdev mode */ + spin_unlock_irqrestore(&cosa->lock, flags); + return -EBUSY; + } + cosa->usage++; + chan->usage++; + + chan->tx_done = chrdev_tx_done; + chan->setup_rx = chrdev_setup_rx; + chan->rx_done = chrdev_rx_done; +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif + spin_unlock_irqrestore(&cosa->lock, flags); + return 0; +} + +static int cosa_release(struct inode *inode, struct file *file) +{ + struct channel_data *channel = (struct channel_data *)file->private_data; + struct cosa_data *cosa = channel->cosa; + unsigned long flags; + + spin_lock_irqsave(&cosa->lock, flags); + cosa->usage--; + channel->usage--; +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif + spin_unlock_irqrestore(&cosa->lock, flags); + return 0; +} + +#ifdef COSA_FASYNC_WORKING +static struct fasync_struct *fasync[256] = { NULL, }; + +/* To be done ... */ +static int cosa_fasync(struct inode *inode, struct file *file, int on) +{ + int port = MINOR(inode->i_rdev); + int rv = fasync_helper(inode, file, on, &fasync[port]); + return rv < 0 ? rv : 0; +} +#endif + + +/* ---------- Ioctls ---------- */ + +/* + * Ioctl subroutines can safely be made inline, because they are called + * only from cosa_ioctl(). + */ +static inline int cosa_reset(struct cosa_data *cosa) +{ + char idstring[COSA_MAX_ID_STRING]; + if (cosa->usage > 1) + printk(KERN_INFO "cosa%d: WARNING: reset requested with cosa->usage > 1 (%d). Odd things may happen.\n", + cosa->num, cosa->usage); + if (cosa_reset_and_read_id(cosa, idstring) < 0) { + printk(KERN_NOTICE "cosa%d: reset failed\n", cosa->num); + return -EIO; + } + printk(KERN_INFO "cosa%d: resetting device: %s\n", cosa->num, + idstring); + return 0; +} + +/* High-level function to download data into COSA memory. Calls download() */ +static inline int cosa_download(struct cosa_data *cosa, struct cosa_download *d) +{ + int i; + int addr, len; + char *code; + + if (cosa->usage > 1) + printk(KERN_INFO "cosa%d: WARNING: download of microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n", + cosa->num, cosa->usage); +#if 0 + if (cosa->status != CARD_STATUS_RESETED && cosa->status != CARD_STATUS_DOWNLOADED) { + printk(KERN_NOTICE "cosa%d: reset the card first (status %d).\n", + cosa->num, cosa->status); + return -EPERM; + } +#endif + get_user_ret(addr, &(d->addr), -EFAULT); + get_user_ret(len, &(d->len), -EFAULT); + get_user_ret(code, &(d->code), -EFAULT); + + if (d->len < 0) + return -EINVAL; + + if ((i=download(cosa, d->code, len, addr)) < 0) { + printk(KERN_NOTICE "cosa%d: microcode download failed: %d\n", + cosa->num, i); + return -EIO; + } + printk(KERN_INFO "cosa%d: downloading microcode - 0x%04x bytes at 0x%04x\n", + cosa->num, len, addr); + return 0; +} + +/* High-level function to read COSA memory. Calls readmem() */ +static inline int cosa_readmem(struct cosa_data *cosa, struct cosa_download *d) +{ + int i; + int addr, len; + char *code; + + if (cosa->usage > 1) + printk(KERN_INFO "cosa%d: WARNING: readmem requested with " + "cosa->usage > 1 (%d). Odd things may happen.\n", + cosa->num, cosa->usage); +#if 0 + if (cosa->status != CARD_STATUS_RESETED && + cosa->status != CARD_STATUS_DOWNLOADED) { + printk(KERN_NOTICE "cosa%d: reset the card first (status %d).\n", + cosa->num, cosa->status); + return -EPERM; + } +#endif + get_user_ret(addr, &(d->addr), -EFAULT); + get_user_ret(len, &(d->len), -EFAULT); + get_user_ret(code, &(d->code), -EFAULT); + + if ((i=readmem(cosa, d->code, len, addr)) < 0) { + printk(KERN_NOTICE "cosa%d: reading memory failed: %d\n", + cosa->num, i); + return -EIO; + } + printk(KERN_INFO "cosa%d: reading card memory - 0x%04x bytes at 0x%04x\n", + cosa->num, len, addr); + return 0; +} + +/* High-level function to start microcode. Calls startmicrocode(). */ +static inline int cosa_start(struct cosa_data *cosa, int address) +{ + int i; + + if (cosa->usage > 1) + printk(KERN_INFO "cosa%d: WARNING: start microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n", + cosa->num, cosa->usage); +#if 0 + if (cosa->status != CARD_STATUS_DOWNLOADED) { + printk(KERN_NOTICE "cosa%d: download the microcode first (status %d).\n", + cosa->num, cosa->status); + return -EPERM; + } +#endif + if ((i=startmicrocode(cosa, address)) < 0) { + printk(KERN_NOTICE "cosa%d: start microcode at 0x%04x failed: %d\n", + cosa->num, address, i); + return -EIO; + } + printk(KERN_INFO "cosa%d: starting microcode at 0x%04x\n", + cosa->num, address); + cosa->startaddr = address; + return 0; +} + +/* Buffer of size at least COSA_MAX_ID_STRING is expected */ +static inline int cosa_getidstr(struct cosa_data *cosa, char *string) +{ + int l = strlen(cosa->id_string)+1; + copy_to_user_ret(string, cosa->id_string, l, -EFAULT); + return l; +} + +/* Buffer of size at least COSA_MAX_ID_STRING is expected */ +static inline int cosa_gettype(struct cosa_data *cosa, char *string) +{ + int l = strlen(cosa->type)+1; + copy_to_user_ret(string, cosa->type, l, -EFAULT); + return l; +} + +static int cosa_ioctl_common(struct cosa_data *cosa, + struct channel_data *channel, unsigned int cmd, unsigned long arg) +{ + switch(cmd) { + case COSAIORSET: /* Reset the device */ + if (!suser()) + return -EACCES; + return cosa_reset(cosa); + case COSAIOSTRT: /* Start the firmware */ + if (!suser()) + return -EACCES; + return cosa_start(cosa, arg); + case COSAIODOWNLD: /* Download the firmware */ + if (!suser()) + return -EACCES; + return cosa_download(cosa, (struct cosa_download *)arg); + case COSAIORMEM: + if (!suser()) + return -EACCES; + return cosa_readmem(cosa, (struct cosa_download *)arg); + case COSAIORTYPE: + return cosa_gettype(cosa, (char *)arg); + case COSAIORIDSTR: + return cosa_getidstr(cosa, (char *)arg); +/* + * These two are _very_ugly_hack_(tm). Don't even look at this. + * Implementing this saved me few reboots after some process segfaulted + * inside this module. + */ +#ifdef MODULE +#if 0 + case COSAIOMINC: + MOD_INC_USE_COUNT; + return 0; + case COSAIOMDEC: + MOD_DEC_USE_COUNT; + return 0; +#endif +#endif + case COSAIONRCARDS: + return nr_cards; + case COSAIONRCHANS: + return cosa->nchannels; + } + return -ENOIOCTLCMD; +} + +static int cosa_sppp_ioctl(struct device *dev, struct ifreq *ifr, + int cmd) +{ + int rv; + struct channel_data *chan = (struct channel_data *)dev->priv; + rv = cosa_ioctl_common(chan->cosa, chan, cmd, (int)ifr->ifr_data); + if (rv == -ENOIOCTLCMD) { + return sppp_do_ioctl(dev, ifr, cmd); + } + return rv; +} + +static int cosa_chardev_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct channel_data *channel = (struct channel_data *)file->private_data; + struct cosa_data *cosa = channel->cosa; + return cosa_ioctl_common(cosa, channel, cmd, arg); +} + + +/*---------- HW layer interface ---------- */ + +/* + * The higher layer can bind itself to the HW layer by setting the callbacks + * in the channel_data structure and by using these routines. + */ +static void cosa_enable_rx(struct channel_data *chan) +{ + struct cosa_data *cosa = chan->cosa; + + if (!test_and_set_bit(chan->num, &cosa->rxbitmap)) + put_driver_status(cosa); +} + +static void cosa_disable_rx(struct channel_data *chan) +{ + struct cosa_data *cosa = chan->cosa; + + if (test_and_clear_bit(chan->num, &cosa->rxbitmap)) + put_driver_status(cosa); +} + +/* + * FIXME: This routine probably should check for cosa_start_tx() called when + * the previous transmit is still unfinished. In this case the non-zero + * return value should indicate to the caller that the queuing(sp?) up + * the transmit has failed. + */ +static int cosa_start_tx(struct channel_data *chan, char *buf, int len) +{ + struct cosa_data *cosa = chan->cosa; + int flags; +#ifdef DEBUG_DATA + int i; + + printk(KERN_INFO "cosa%dc%d: starting tx(0x%x)", chan->cosa->num, + chan->num, len); + for (i=0; ilock, flags); + chan->txbuf = buf; + chan->txsize = len; + if (len > COSA_MTU) + chan->txsize = COSA_MTU; + spin_unlock_irqrestore(&cosa->lock, flags); + + /* Tell the firmware we are ready */ + set_bit(chan->num, &cosa->txbitmap); + put_driver_status(cosa); + + return 0; +} + +static void put_driver_status_common(struct cosa_data *cosa, int nolock) +{ + unsigned flags=0; + int status; + + if (!nolock) + spin_lock_irqsave(&cosa->lock, flags); + + status = (cosa->rxbitmap ? DRIVER_RX_READY : 0) + | (cosa->txbitmap ? DRIVER_TX_READY : 0) + | (cosa->txbitmap? ~(cosa->txbitmap<rxtx || nolock) { +#ifdef DEBUG_IO + debug_data_cmd(cosa, status); +#endif + cosa_putdata8(cosa, status); + if (cosa->rxbitmap|cosa->txbitmap) { + cosa_putstatus(cosa, SR_RX_INT_ENA); +#ifdef DEBUG_IO + debug_status_out(cosa, SR_RX_INT_ENA); +#endif + } else { + cosa_putstatus(cosa, 0); +#ifdef DEBUG_IO + debug_status_out(cosa, 0); +#endif + } + } + if (!nolock) + spin_unlock_irqrestore(&cosa->lock, flags); +} + +/* + * The "kickme" function: When the DMA times out, this is called to + * clean up the driver status. + * FIXME: Preliminary support, the interface is probably wrong. + */ +static void cosa_kick(struct cosa_data *cosa) +{ + unsigned flags, flags1; + + printk(KERN_INFO "%s: DMA timeout - restarting.\n", cosa->name); + + spin_lock_irqsave(&cosa->lock, flags); + cosa->rxtx = 0; + + flags1 = claim_dma_lock(); + disable_dma(cosa->dma); + clear_dma_ff(cosa->dma); + release_dma_lock(flags1); + + /* FIXME: Anything else? */ + put_driver_status_nolock(cosa); + spin_unlock_irqrestore(&cosa->lock, flags); +} + +/* + * Check if the whole buffer is DMA-able. It means it is below the 16M of + * physical memory and doesn't span the 64k boundary. For now it seems + * SKB's never do this, but we'll check this anyway. + */ +static int cosa_dma_able(struct channel_data *chan, char *buf, int len) +{ + static int count = 0; + unsigned long b = (unsigned long)buf; + if (b+len >= MAX_DMA_ADDRESS) + return 0; + if ((b^ (b+len)) & 0x10000) { + if (count++ < 5) + printk(KERN_INFO "%s: packet spanning a 64k boundary\n", + chan->name); + return 0; + } + return 1; +} + + +/* ---------- The SRP/COSA ROM monitor functions ---------- */ + +/* + * Downloading SRP microcode: say "w" to SRP monitor, it answers by "w=", + * drivers need to say 4-digit hex number meaning start address of the microcode + * separated by a single space. Monitor replies by saying " =". Now driver + * has to write 4-digit hex number meaning the last byte address ended + * by a single space. Monitor has to reply with a space. Now the download + * begins. After the download monitor replies with "\r\n." (CR LF dot). + */ +static int download(struct cosa_data *cosa, char *microcode, int length, int address) +{ + int i; + + if (put_wait_data(cosa, 'w') == -1) return -1; + if ((i=get_wait_data(cosa)) != 'w') { printk("dnld: 0x%04x\n",i); return -2;} + if (get_wait_data(cosa) != '=') return -3; + + if (puthexnumber(cosa, address) < 0) return -4; + if (put_wait_data(cosa, ' ') == -1) return -10; + if (get_wait_data(cosa) != ' ') return -11; + if (get_wait_data(cosa) != '=') return -12; + + if (puthexnumber(cosa, address+length-1) < 0) return -13; + if (put_wait_data(cosa, ' ') == -1) return -18; + if (get_wait_data(cosa) != ' ') return -19; + + while (length--) { + char c; +#ifndef SRP_DOWNLOAD_AT_BOOT + get_user_ret(c,microcode, -23); +#else + c = *microcode; +#endif + if (put_wait_data(cosa, c) == -1) + return -20; + microcode++; + } + + if (get_wait_data(cosa) != '\r') return -21; + if (get_wait_data(cosa) != '\n') return -22; + if (get_wait_data(cosa) != '.') return -23; +#if 0 + printk(KERN_DEBUG "cosa%d: download completed.\n", cosa->num); +#endif + return 0; +} + + +/* + * Starting microcode is done via the "g" command of the SRP monitor. + * The chat should be the following: "g" "g=" "" + * "". + */ +static int startmicrocode(struct cosa_data *cosa, int address) +{ + if (put_wait_data(cosa, 'g') == -1) return -1; + if (get_wait_data(cosa) != 'g') return -2; + if (get_wait_data(cosa) != '=') return -3; + + if (puthexnumber(cosa, address) < 0) return -4; + if (put_wait_data(cosa, '\r') == -1) return -5; + + if (get_wait_data(cosa) != '\r') return -6; + if (get_wait_data(cosa) != '\r') return -7; + if (get_wait_data(cosa) != '\n') return -8; + if (get_wait_data(cosa) != '\r') return -9; + if (get_wait_data(cosa) != '\n') return -10; +#if 0 + printk(KERN_DEBUG "cosa%d: microcode started\n", cosa->num); +#endif + return 0; +} + +/* + * Reading memory is done via the "r" command of the SRP monitor. + * The chat is the following "r" "r=" " " " =" " " " " + * Then driver can read the data and the conversation is finished + * by SRP monitor sending "." (dot at the end). + * + * This routine is not needed during the normal operation and serves + * for debugging purposes only. + */ +static int readmem(struct cosa_data *cosa, char *microcode, int length, int address) +{ + if (put_wait_data(cosa, 'r') == -1) return -1; + if ((get_wait_data(cosa)) != 'r') return -2; + if ((get_wait_data(cosa)) != '=') return -3; + + if (puthexnumber(cosa, address) < 0) return -4; + if (put_wait_data(cosa, ' ') == -1) return -5; + if (get_wait_data(cosa) != ' ') return -6; + if (get_wait_data(cosa) != '=') return -7; + + if (puthexnumber(cosa, address+length-1) < 0) return -8; + if (put_wait_data(cosa, ' ') == -1) return -9; + if (get_wait_data(cosa) != ' ') return -10; + + while (length--) { + char c; + int i; + if ((i=get_wait_data(cosa)) == -1) { + printk (KERN_INFO "cosa: 0x%04x bytes remaining\n", + length); + return -11; + } + c=i; +#if 1 + put_user_ret(c,microcode, -23); +#else + *microcode = c; +#endif + microcode++; + } + + if (get_wait_data(cosa) != '\r') return -21; + if (get_wait_data(cosa) != '\n') return -22; + if (get_wait_data(cosa) != '.') return -23; +#if 0 + printk(KERN_DEBUG "cosa%d: readmem completed.\n", cosa->num); +#endif + return 0; +} + +/* + * This function resets the device and reads the initial prompt + * of the device's ROM monitor. + */ +static int cosa_reset_and_read_id(struct cosa_data *cosa, char *idstring) +{ + int i=0, id=0, prev=0, curr=0; + + /* Reset the card ... */ + cosa_putstatus(cosa, 0); + cosa_getdata8(cosa); + cosa_putstatus(cosa, SR_RST); +#ifdef MODULE + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(HZ/2); + current->state = TASK_RUNNING; +#else + udelay(5*100000); +#endif + /* Disable all IRQs from the card */ + cosa_putstatus(cosa, 0); + + /* + * Try to read the ID string. The card then prints out the + * identification string ended by the "\n\x2e". + * + * The following loop is indexed through i (instead of id) + * to avoid looping forever when for any reason + * the port returns '\r', '\n' or '\x2e' permanently. + */ + for (i=0; istate = TASK_INTERRUPTIBLE; + schedule_timeout(1); + current->state = TASK_RUNNING; + } + printk(KERN_INFO "cosa: timeout in get_wait_data (status 0x%x)\n", + cosa_getstatus(cosa)); + return -1; +} + +/* + * This routine puts the data byte to the card waiting for the SR_TX_RDY + * bit to be set in a loop. It should be used in the exceptional cases + * only (for example when resetting the card or downloading the firmware). + */ +static int put_wait_data(struct cosa_data *cosa, int data) +{ + int retries = 1000; + while (--retries) { + /* read data and return them */ + if (cosa_getstatus(cosa) & SR_TX_RDY) { + cosa_putdata8(cosa, data); +#if 0 + printk(KERN_INFO "Putdata: %d retries\n", 999-retries); +#endif + return 0; + } +#if 0 + /* sleep if not ready to read */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + current->state = TASK_RUNNING; +#endif + } + printk(KERN_INFO "cosa%d: timeout in put_wait_data (status 0x%x)\n", + cosa->num, cosa_getstatus(cosa)); + return -1; +} + +/* + * The following routine puts the hexadecimal number into the SRP monitor + * and verifies the proper echo of the sent bytes. Returns 0 on success, + * negative number on failure (-1,-3,-5,-7) means that put_wait_data() failed, + * (-2,-4,-6,-8) means that reading echo failed. + */ +static int puthexnumber(struct cosa_data *cosa, int number) +{ + char temp[5]; + int i; + + /* Well, I should probably replace this by something faster. */ + sprintf(temp, "%04X", number); + for (i=0; i<4; i++) { + if (put_wait_data(cosa, temp[i]) == -1) { + printk(KERN_NOTICE "cosa%d: puthexnumber failed to write byte %d\n", + cosa->num, i); + return -1-2*i; + } + if (get_wait_data(cosa) != temp[i]) { + printk(KERN_NOTICE "cosa%d: puthexhumber failed to read echo of byte %d\n", + cosa->num, i); + return -2-2*i; + } + } + return 0; +} + + +/* ---------- Interrupt routines ---------- */ + +/* + * There are three types of interrupt: + * At the beginning of transmit - this handled is in tx_interrupt(), + * at the beginning of receive - it is in rx_interrupt() and + * at the end of transmit/receive - it is the eot_interrupt() function. + * These functions are multiplexed by cosa_interrupt() according to the + * COSA status byte. I have moved the rx/tx/eot interrupt handling into + * separate functions to make it more readable. These functions are inline, + * so there should be no overhead of function call. + */ +static inline void tx_interrupt(struct cosa_data *cosa, int status) +{ + unsigned long flags, flags1; +#ifdef DEBUG_IRQS + printk(KERN_INFO "cosa%d: SR_DOWN_REQUEST status=0x%04x\n", + cosa->num, status); +#endif + spin_lock_irqsave(&cosa->lock, flags); + set_bit(TXBIT, &cosa->rxtx); + /* + * Using a round-robin algorithm select a first channel that has + * data ready for transmit. + */ + if (!test_bit(IRQBIT, &cosa->rxtx)) { + do { + cosa->txchan++; + if (cosa->txchan >= cosa->nchannels) + cosa->txchan = 0; + } while(!(cosa->txbitmap & (1<txchan))); + cosa->txsize = cosa->chan[cosa->txchan].txsize; + if (cosa_dma_able(cosa->chan+cosa->txchan, + cosa->chan[cosa->txchan].txbuf, cosa->txsize)) { + cosa->txbuf = cosa->chan[cosa->txchan].txbuf; + } else { + memcpy(cosa->bouncebuf, cosa->chan[cosa->txchan].txbuf, + cosa->txsize); + cosa->txbuf = cosa->bouncebuf; + } + } + + if (is_8bit(cosa)) { + if (!test_bit(IRQBIT, &cosa->rxtx)) { + cosa_putdata8(cosa, ((cosa->txchan << 5) & 0xe0)| + ((cosa->txsize >> 8) & 0x1f)); + cosa_putstatus(cosa, SR_TX_INT_ENA); +#ifdef DEBUG_IO + debug_data_out(cosa, ((cosa->txchan << 5) & 0xe0)| + ((cosa->txsize >> 8) & 0x1f)); + debug_status_out(cosa, SR_TX_INT_ENA); + debug_data_in(cosa, cosa_getdata8(cosa)); +#else + cosa_getdata8(cosa); +#endif + set_bit(IRQBIT, &cosa->rxtx); + spin_unlock_irqrestore(&cosa->lock, flags); + return; + } else { + clear_bit(IRQBIT, &cosa->rxtx); + cosa_putstatus(cosa, 0); + cosa_putdata8(cosa, cosa->txsize&0xff); +#ifdef DEBUG_IO + debug_status_out(cosa, 0); + debug_data_out(cosa, cosa->txsize&0xff); +#endif + } + } else { + cosa_putdata16(cosa, ((cosa->txchan<<13) & 0xe000) + | (cosa->txsize & 0x1fff)); + cosa_getdata16(cosa); +#ifdef DEBUG_IO + debug_status_out(cosa, ((cosa->txchan<<13) & 0xe000) + | (cosa->txsize & 0x1fff)); + debug_data_in(cosa, cosa_getdata16(cosa)); +#else + cosa_getdata16(cosa); +#endif + } + + /* start the DMA */ + flags1 = claim_dma_lock(); + disable_dma(cosa->dma); + clear_dma_ff(cosa->dma); + set_dma_mode(cosa->dma, DMA_MODE_WRITE); + set_dma_addr(cosa->dma, virt_to_bus(cosa->txbuf)); + set_dma_count(cosa->dma, cosa->txsize); + enable_dma(cosa->dma); + release_dma_lock(flags1); + cosa_putstatus(cosa, SR_TX_DMA_ENA|SR_USR_INT_ENA); +#ifdef DEBUG_IO + debug_status_out(cosa, SR_TX_DMA_ENA|SR_USR_INT_ENA); +#endif + spin_unlock_irqrestore(&cosa->lock, flags); +} + +static inline void rx_interrupt(struct cosa_data *cosa, int status) +{ + unsigned long flags; +#ifdef DEBUG_IRQS + printk(KERN_INFO "cosa%d: SR_UP_REQUEST\n", cosa->num); +#endif + + spin_lock_irqsave(&cosa->lock, flags); + set_bit(RXBIT, &cosa->rxtx); + + if (is_8bit(cosa)) { + if (!test_bit(IRQBIT, &cosa->rxtx)) { + set_bit(IRQBIT, &cosa->rxtx); + cosa_putstatus(cosa, 0); + cosa->rxsize = cosa_getdata8(cosa) <<8; +#ifdef DEBUG_IO + debug_status_out(cosa, 0); + debug_data_in(cosa, cosa->rxsize >> 8); +#endif + put_driver_status_nolock(cosa); + spin_unlock_irqrestore(&cosa->lock, flags); + return; + } else { + clear_bit(IRQBIT, &cosa->rxtx); + cosa_putstatus(cosa, 0); + cosa->rxsize |= cosa_getdata8(cosa) & 0xff; +#ifdef DEBUG_IO + debug_status_out(cosa, 0); + debug_data_in(cosa, cosa->rxsize & 0xff); +#endif +#if 0 + printk(KERN_INFO "cosa%d: receive rxsize = (0x%04x).\n", + cosa->num, cosa->rxsize); +#endif + } + } else { + cosa->rxsize = cosa_getdata16(cosa); + cosa_putstatus(cosa, 0); + cosa_putdata8(cosa, DRIVER_RX_READY); +#ifdef DEBUG_IO + debug_data_in(cosa, cosa->rxsize); + debug_status_out(cosa, 0); + debug_cmd_out(cosa, DRIVER_RX_READY); +#endif +#if 0 + printk(KERN_INFO "cosa%d: receive rxsize = (0x%04x).\n", + cosa->num, cosa->rxsize); +#endif + } + if (((cosa->rxsize & 0xe000) >> 13) >= cosa->nchannels) { + printk(KERN_WARNING "%s: rx for unknown channel (0x%04x)\n", + cosa->name, cosa->rxsize); + spin_unlock_irqrestore(&cosa->lock, flags); + goto reject; + } + cosa->rxchan = cosa->chan + ((cosa->rxsize & 0xe000) >> 13); + cosa->rxsize &= 0x1fff; + spin_unlock_irqrestore(&cosa->lock, flags); + + cosa->rxbuf = NULL; + if (cosa->rxchan->setup_rx) + cosa->rxbuf = cosa->rxchan->setup_rx(cosa->rxchan, cosa->rxsize); + + if (!cosa->rxbuf) { +reject: /* Reject the packet */ + printk(KERN_INFO "cosa%d: rejecting packet on channel %d\n", + cosa->num, cosa->rxchan->num); + /* FIXME: This works for COSA only (not SRP) */ + cosa->rxtx = 0; + put_driver_status(cosa); + return; + } + + /* start the DMA */ + flags = claim_dma_lock(); + disable_dma(cosa->dma); + clear_dma_ff(cosa->dma); + set_dma_mode(cosa->dma, DMA_MODE_READ); + if (cosa_dma_able(cosa->rxchan, cosa->rxbuf, cosa->rxsize & 0x1fff)) { + set_dma_addr(cosa->dma, virt_to_bus(cosa->rxbuf)); + } else { + set_dma_addr(cosa->dma, virt_to_bus(cosa->bouncebuf)); + } + set_dma_count(cosa->dma, (cosa->rxsize&0x1fff)); + enable_dma(cosa->dma); + release_dma_lock(flags); + spin_lock_irqsave(&cosa->lock, flags); + cosa_putstatus(cosa, SR_RX_DMA_ENA|SR_USR_INT_ENA); +#ifdef DEBUG_IO + debug_status_out(cosa, SR_RX_DMA_ENA|SR_USR_INT_ENA); +#endif + spin_unlock_irqrestore(&cosa->lock, flags); +} + +static void inline eot_interrupt(struct cosa_data *cosa, int status) +{ + unsigned long flags, flags1; + spin_lock_irqsave(&cosa->lock, flags); + if (test_bit(TXBIT, &cosa->rxtx)) { + struct channel_data *chan = cosa->chan+cosa->txchan; +#ifdef DEBUG_IRQS + printk(KERN_INFO "cosa%d: end of transfer.\n", cosa->num); +#endif + if (chan->tx_done) + if (chan->tx_done(chan, cosa->txsize)) + clear_bit(chan->num, &cosa->txbitmap); + } else if (test_bit(RXBIT, &cosa->rxtx)) { +#ifdef DEBUG_DATA + { + int i; + printk(KERN_INFO "cosa%dc%d: done rx(0x%x)", cosa->num, + cosa->rxchan->num, cosa->rxsize); + for (i=0; irxsize; i++) + printk (" %02x", cosa->rxbuf[i]&0xff); + printk("\n"); + } +#endif + if (!cosa_dma_able(cosa->rxchan, cosa->rxbuf, cosa->rxsize)) + memcpy(cosa->rxbuf, cosa->bouncebuf, cosa->rxsize); + if (cosa->rxchan->rx_done) + if (cosa->rxchan->rx_done(cosa->rxchan)) + clear_bit(cosa->rxchan->num, &cosa->rxbitmap); + } else { + printk(KERN_NOTICE "cosa%d: unexpected EOT interrupt\n", + cosa->num); + } + /* + * Clear the RXBIT, TXBIT and IRQBIT (the latest should be + * cleared anyway). + */ + flags1 = claim_dma_lock(); + disable_dma(cosa->dma); + clear_dma_ff(cosa->dma); + release_dma_lock(flags1); + cosa->rxtx = 0; + put_driver_status_nolock(cosa); + spin_unlock_irqrestore(&cosa->lock, flags); +} + +static void cosa_interrupt(int irq, void *cosa_, struct pt_regs *regs) +{ + int status; + int count = 0; + struct cosa_data *cosa = cosa_; +again: + status = cosa_getstatus(cosa); +#ifdef DEBUG_IRQS + printk(KERN_INFO "cosa%d: got IRQ, status 0x%02x\n", cosa->num, + status & 0xff); +#endif +#ifdef DEBUG_IO + debug_status_in(cosa, status); +#endif + switch (status & SR_CMD_FROM_SRP_MASK) { + case SR_DOWN_REQUEST: + tx_interrupt(cosa, status); + break; + case SR_UP_REQUEST: + rx_interrupt(cosa, status); + break; + case SR_END_OF_TRANSFER: + eot_interrupt(cosa, status); + break; + default: + /* We may be too fast for SRP. Try to wait a bit more. */ + if (count++ < 100) { + udelay(100); + goto again; + } + printk(KERN_INFO "cosa%d: unknown status 0x%02x in IRQ after %d retries\n", + cosa->num, status & 0xff, count); + } +#ifdef DEBUG_IRQS + if (count) + printk(KERN_INFO "%s: %d-times got unknown status in IRQ\n", + cosa->name, count); + else + printk(KERN_INFO "%s: returning from IRQ\n", cosa->name); +#endif +} + + +/* ---------- I/O debugging routines ---------- */ +/* + * These routines can be used to monitor COSA/SRP I/O and to printk() + * the data being transfered on the data and status I/O port in a + * readable way. + */ + +#ifdef DEBUG_IO +static void debug_status_in(struct cosa_data *cosa, int status) +{ + char *s; + switch(status & SR_CMD_FROM_SRP_MASK) { + case SR_UP_REQUEST: + s = "RX_REQ"; + break; + case SR_DOWN_REQUEST: + s = "TX_REQ"; + break; + case SR_END_OF_TRANSFER: + s = "ET_REQ"; + break; + default: + s = "NO_REQ"; + break; + } + printk(KERN_INFO "%s: IO: status -> 0x%02x (%s%s%s%s)\n", + cosa->name, + status, + status & SR_USR_RQ ? "USR_RQ|":"", + status & SR_TX_RDY ? "TX_RDY|":"", + status & SR_RX_RDY ? "RX_RDY|":"", + s); +} + +static void debug_status_out(struct cosa_data *cosa, int status) +{ + printk(KERN_INFO "%s: IO: status <- 0x%02x (%s%s%s%s%s%s)\n", + cosa->name, + status, + status & SR_RX_DMA_ENA ? "RXDMA|":"!rxdma|", + status & SR_TX_DMA_ENA ? "TXDMA|":"!txdma|", + status & SR_RST ? "RESET|":"", + status & SR_USR_INT_ENA ? "USRINT|":"!usrint|", + status & SR_TX_INT_ENA ? "TXINT|":"!txint|", + status & SR_RX_INT_ENA ? "RXINT":"!rxint"); +} + +static void debug_data_in(struct cosa_data *cosa, int data) +{ + printk(KERN_INFO "%s: IO: data -> 0x%04x\n", cosa->name, data); +} + +static void debug_data_out(struct cosa_data *cosa, int data) +{ + printk(KERN_INFO "%s: IO: data <- 0x%04x\n", cosa->name, data); +} + +static void debug_data_cmd(struct cosa_data *cosa, int data) +{ + printk(KERN_INFO "%s: IO: data <- 0x%04x (%s|%s)\n", + cosa->name, data, + data & SR_RDY_RCV ? "RX_RDY" : "!rx_rdy", + data & SR_RDY_SND ? "TX_RDY" : "!tx_rdy"); +} +#endif + +/* EOF -- this file has not been truncated */ diff --git a/drivers/net/cosa.h b/drivers/net/cosa.h new file mode 100644 index 000000000000..10ea328048db --- /dev/null +++ b/drivers/net/cosa.h @@ -0,0 +1,102 @@ +/* $Id: cosa.h,v 1.8 1998/11/09 03:54:49 kas Exp $ */ + +/* + * Copyright (C) 1995-1997 Jan "Yenya" Kasprzak + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef COSA_H__ +#define COSA_H__ + +#include + +#ifdef __KERNEL__ +/* status register - output bits */ +#define SR_RX_DMA_ENA 0x04 /* receiver DMA enable bit */ +#define SR_TX_DMA_ENA 0x08 /* transmitter DMA enable bit */ +#define SR_RST 0x10 /* SRP reset */ +#define SR_USR_INT_ENA 0x20 /* user interrupt enable bit */ +#define SR_TX_INT_ENA 0x40 /* transmitter interrupt enable bit */ +#define SR_RX_INT_ENA 0x80 /* receiver interrupt enable bit */ + +/* status register - input bits */ +#define SR_USR_RQ 0x20 /* user interupt request pending */ +#define SR_TX_RDY 0x40 /* transmitter empty (ready) */ +#define SR_RX_RDY 0x80 /* receiver data ready */ + +#define SR_UP_REQUEST 0x02 /* request from SRP to transfer data + up to PC */ +#define SR_DOWN_REQUEST 0x01 /* SRP is able to transfer data down + from PC to SRP */ +#define SR_END_OF_TRANSFER 0x03 /* SRP signalize end of + transfer (up or down) */ + +#define SR_CMD_FROM_SRP_MASK 0x03 /* mask to get SRP command */ + +/* bits in driver status byte definitions : */ +#define SR_RDY_RCV 0x01 /* ready to receive packet */ +#define SR_RDY_SND 0x02 /* ready to send packet */ +#define SR_CMD_PND 0x04 /* command pending */ /* not currently used */ + +/* ???? */ +#define SR_PKT_UP 0x01 /* transfer of packet up in progress */ +#define SR_PKT_DOWN 0x02 /* transfer of packet down in progress */ + +#endif /* __KERNEL__ */ + +#define SR_LOAD_ADDR 0x4400 /* SRP microcode load address */ +#define SR_START_ADDR 0x4400 /* SRP microcode start address */ + +#define COSA_LOAD_ADDR 0x400 /* SRP microcode load address */ + + +/* ioctls */ +struct cosa_download { + int addr, len; + char *code; +}; + +/* Reset the device */ +#define COSAIORSET _IO('C',0xf0) + +/* Start microcode at given address */ +#define COSAIOSTRT _IOW('C',0xf1,sizeof(int)) + +/* Read the block from the device memory */ +#define COSAIORMEM _IOR('C',0xf2,sizeof(struct cosa_download *)) + +/* Write the block to the device memory (i.e. download the microcode) */ +#define COSAIODOWNLD _IOW('C',0xf2,sizeof(struct cosa_download *)) + +/* Read the device type (one of "srp", "cosa", and "cosa8" for now) */ +#define COSAIORTYPE _IOR('C',0xf3,sizeof(char *)) + +/* Read the device identification string */ +#define COSAIORIDSTR _IOR('C',0xf4,sizeof(char *)) +/* Maximum length of the identification string. */ +#define COSA_MAX_ID_STRING 128 + +/* Increment/decrement the module usage count :-) */ +/* #define COSAIOMINC _IO('C',0xf5) */ +/* #define COSAIOMDEC _IO('C',0xf6) */ + +/* Get the total number of cards installed */ +#define COSAIONRCARDS _IO('C',0xf7) + +/* Get the number of channels on this card */ +#define COSAIONRCHANS _IO('C',0xf8) + +#endif /* !COSA_H__ */ diff --git a/drivers/net/daynaport.c b/drivers/net/daynaport.c index 00c0ed9b6165..777a1dcab5b6 100644 --- a/drivers/net/daynaport.c +++ b/drivers/net/daynaport.c @@ -340,13 +340,13 @@ int ns8390_probe1(struct device *dev, int word16, char *model_name, int type, in { static unsigned version_printed = 0; - static int fwrd4_offsets[16]={ + static u32 fwrd4_offsets[16]={ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60 }; - static int back4_offsets[16]={ + static u32 back4_offsets[16]={ 60, 56, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index dc52fd84e3d9..f6552a8da036 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -1,25 +1,24 @@ -/* epic100.c: A SMC 83c170 EPIC/100 fast ethernet driver for Linux. */ +/* epic100.c: A SMC 83c170 EPIC/100 Fast Ethernet driver for Linux. */ /* - NOTICE: THIS IS THE ALPHA TEST VERSION! - Written 1997 by Donald Becker. + Written/copyright 1997-1998 by Donald Becker. This software may be used and distributed according to the terms of the GNU Public License, incorporated herein by reference. - All other rights reserved. + All other rights reserved. - This driver is for the SMC EtherPower II 9432 PCI ethernet adapter based on - the SMC83c170. + This driver is for the SMC83c170/175 "EPIC" series, as used on the + SMC EtherPower II 9432 PCI adapter, and several CardBus cards. The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O - Center of Excellence in Space Data and Information Sciences + USRA Center of Excellence in Space Data and Information Sciences Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - Support and updates available at + Information and updates available at http://cesdis.gsfc.nasa.gov/linux/drivers/epic100.html */ static const char *version = -"epic100.c:v0.10 10/14/97 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/epic100.html\n"; +"epic100.c:v1.04 8/23/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/epic100.html\n"; /* A few user-configurable values. */ @@ -32,7 +31,7 @@ static const char *version = /* Set the copy breakpoint for the copy-only-tiny-frames scheme. Setting to > 1518 effectively disables this feature. */ -static const int rx_copybreak = 200; +static int rx_copybreak = 200; /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ static int max_interrupt_work = 10; @@ -44,16 +43,16 @@ static int max_interrupt_work = 10; #define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ /* Bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 128 /* Rounded down to 4 byte units. */ +#define TX_FIFO_THRESH 256 /* Rounded down to 4 byte units. */ #define RX_FIFO_THRESH 1 /* 0-3, 0==32, 64,96, or 3==128 bytes */ #include +#include /* Evil, but neccessary */ #ifdef MODULE #ifdef MODVERSIONS #include #endif #include -#include #else #define MOD_INC_USE_COUNT #define MOD_DEC_USE_COUNT @@ -69,6 +68,13 @@ static int max_interrupt_work = 10; #include #include #include +#if LINUX_VERSION_CODE >= 0x20155 +#define PCI_SUPPORT_VER2 +#else +#include +#endif +#include + #include /* Processor type for cache alignment. */ #include #include @@ -80,70 +86,39 @@ static int max_interrupt_work = 10; /* Kernel compatibility defines, common to David Hind's PCMCIA package. This is only in the support-all-kernels source code. */ -#include /* Evil, but neccessary */ -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10300 -#define RUN_AT(x) (x) /* What to put in timer->expires. */ -#define DEV_ALLOC_SKB(len) alloc_skb(len, GFP_ATOMIC) -#define virt_to_bus(addr) ((unsigned long)addr) -#define bus_to_virt(addr) ((void*)addr) - -#else /* 1.3.0 and later */ -#define RUN_AT(x) (jiffies + (x)) -#define DEV_ALLOC_SKB(len) dev_alloc_skb(len + 2) +#if ! defined (LINUX_VERSION_CODE) || LINUX_VERSION_CODE < 0x20000 +#warning This driver version is only for kernel versions 2.0.0 and later. #endif -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10338 -#ifdef MODULE -#if !defined(CONFIG_MODVERSIONS) && !defined(__NO_VERSION__) -char kernel_version[] = UTS_RELEASE; -#endif -#else -#undef MOD_INC_USE_COUNT -#define MOD_INC_USE_COUNT -#undef MOD_DEC_USE_COUNT -#define MOD_DEC_USE_COUNT -#endif -#endif /* 1.3.38 */ - -#if (LINUX_VERSION_CODE >= 0x10344) -#define NEW_MULTICAST -#include -#endif - -#ifdef SA_SHIRQ -#define FREE_IRQ(irqnum, dev) free_irq(irqnum, dev) -#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n, instance) -#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs) -#else -#define FREE_IRQ(irqnum, dev) free_irq(irqnum) -#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n) -#define IRQ(irq, dev_id, pt_regs) (irq, pt_regs) -#endif +#define RUN_AT(x) (jiffies + (x)) -#if (LINUX_VERSION_CODE < 0x20123) -#define test_and_set_bit(val, addr) set_bit(val, addr) -#include -#else -#ifdef MODULE +#if defined(MODULE) && (LINUX_VERSION_CODE >= 0x20115) MODULE_AUTHOR("Donald Becker "); -MODULE_DESCRIPTION("SMC 82c170 EPIC series Ethernet driver"); +MODULE_DESCRIPTION("SMC 83c170 EPIC series Ethernet driver"); MODULE_PARM(debug, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(8) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i"); MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(max_interrupt_work, "i"); #endif +#if LINUX_VERSION_CODE < 0x20123 +#define test_and_set_bit(val, addr) set_bit(val, addr) +#endif +#if LINUX_VERSION_CODE <= 0x20139 +#define net_device_stats enet_statistics +#define NETSTATS_VER2 +#endif +#if LINUX_VERSION_CODE < 0x20159 +#define DEV_FREE_SKB(skb) dev_kfree_skb(skb, FREE_WRITE); +#else /* Grrr, unneeded incompatible change. */ +#define DEV_FREE_SKB(skb) dev_kfree_skb(skb); #endif /* The I/O extent. */ #define EPIC_TOTAL_SIZE 0x100 -#ifdef HAVE_DEVLIST -struct netdev_entry epic100_drv = -{"Epic100", epic100_pci_probe, EPIC_TOTAL_SIZE, NULL}; -#endif - +#define epic_debug debug static int epic_debug = 1; /* @@ -152,7 +127,7 @@ static int epic_debug = 1; I. Board Compatibility This device driver is designed for the SMC "EPCI/100", the SMC -single-chip ethernet controllers for PCI. This chip is used on +single-chip Ethernet controllers for PCI. This chip is used on the SMC EtherPower II boards. @@ -178,17 +153,34 @@ IVc. Errata */ -#ifndef PCI_VENDOR_ID_SMC -#define PCI_VENDOR_ID_SMC 0x10B8 -#endif -#ifndef PCI_DEVICE_ID_SMC_EPIC100 -#define PCI_DEVICE_ID_SMC_EPIC100 0x0005 -#endif - /* The rest of these values should never change. */ + +static struct device *epic_probe1(int pci_bus, int pci_devfn, + struct device *dev, long ioaddr, int irq, + int chip_id, int card_idx); + +enum pci_flags_bit { + PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, + PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3, +}; +struct chip_info { + const char *name; + u16 vendor_id, device_id, device_id_mask, pci_flags; + int io_size, min_latency; + struct device *(*probe1)(int pci_bus, int pci_devfn, struct device *dev, + long ioaddr, int irq, int chip_idx, int fnd_cnt); +} chip_tbl[] = { + {"SMSC EPIC/100 83c170", 0x10B8, 0x0005, 0x7fff, + PCI_USES_IO|PCI_USES_MASTER|PCI_ADDR0, EPIC_TOTAL_SIZE, 32, epic_probe1}, + {"SMSC EPIC/C 83c175", 0x10B8, 0x0006, 0x7fff, + PCI_USES_IO|PCI_USES_MASTER|PCI_ADDR0, EPIC_TOTAL_SIZE, 32, epic_probe1}, + {0,}, +}; + /* Offsets to registers, using the (ugh) SMC names. */ enum epic_registers { COMMAND=0, INTSTAT=4, INTMASK=8, GENCTL=0x0C, NVCTL=0x10, EECTL=0x14, + PCIBurstCnt=0x18, TEST1=0x1C, CRCCNT=0x20, ALICNT=0x24, MPCNT=0x28, /* Rx error counters. */ MIICtrl=0x30, MIIData=0x34, MIICfg=0x38, LAN0=64, /* MAC address. */ @@ -199,8 +191,9 @@ enum epic_registers { /* Interrupt register bits, using my own meaningful names. */ enum IntrStatus { - TxIdle=0x40000, RxIdle=0x20000, - CntFull=0x0200, TxUnderrun=0x0100, + TxIdle=0x40000, RxIdle=0x20000, IntrSummary=0x010000, + PCIBusErr170=0x7000, PCIBusErr175=0x1000, PhyEvent175=0x8000, + RxStarted=0x0800, RxEarlyWarn=0x0400, CntFull=0x0200, TxUnderrun=0x0100, TxEmpty=0x0080, TxDone=0x0020, RxError=0x0010, RxOverflow=0x0008, RxFull=0x0004, RxHeader=0x0002, RxDone=0x0001, }; @@ -213,7 +206,7 @@ struct epic_tx_desc { u32 bufaddr; u16 buflength; u16 control; - u32 next; + u32 next; }; struct epic_rx_desc { @@ -221,29 +214,36 @@ struct epic_rx_desc { u16 rxlength; u32 bufaddr; u32 buflength; - u32 next; + u32 next; }; struct epic_private { char devname[8]; /* Used only for kernel debugging. */ const char *product_name; struct device *next_module; + + /* Rx and Rx rings here so that they remain paragraph aligned. */ struct epic_rx_desc rx_ring[RX_RING_SIZE]; struct epic_tx_desc tx_ring[TX_RING_SIZE]; /* The saved address of a sent-in-place packet/buffer, for skfree(). */ struct sk_buff* tx_skbuff[TX_RING_SIZE]; /* The addresses of receive-in-place skbuffs. */ struct sk_buff* rx_skbuff[RX_RING_SIZE]; - int chip_id; - int revision; - struct enet_statistics stats; - struct timer_list timer; /* Media selection timer. */ + + /* Ring pointers. */ unsigned int cur_rx, cur_tx; /* The next free ring entry */ unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ + + u8 pci_bus, pci_dev_fn; /* PCI bus location. */ + u16 chip_id; + + struct net_device_stats stats; + struct timer_list timer; /* Media selection timer. */ unsigned char mc_filter[8]; signed char phys[4]; /* MII device addresses. */ unsigned int tx_full:1; /* The Tx queue is full. */ - unsigned int full_duplex:1; /* Full-duplex operation requested. */ + unsigned int full_duplex:1; /* Current duplex setting. */ + unsigned int force_fd:1; /* Full-duplex operation requested. */ unsigned int default_port:4; /* Last dev->if_port value. */ unsigned int media2:4; /* Secondary monitored media port. */ unsigned int medialock:1; /* Don't sense media type. */ @@ -251,162 +251,174 @@ struct epic_private { int pad0, pad1; /* Used for 8-byte alignment */ }; -static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1}; -#ifdef MODULE /* Used to pass the full-duplex flag, etc. */ -static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1}; -#endif +#define MAX_UNITS 8 +static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; +static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static struct device *epic100_probe1(struct device *dev, int ioaddr, int irq, - int chip_id, int options, int card_idx); static int epic_open(struct device *dev); -static int read_eeprom(int ioaddr, int location); -static int mii_read(int ioaddr, int phy_id, int location); +static int read_eeprom(long ioaddr, int location); +static int mdio_read(long ioaddr, int phy_id, int location); +static void mdio_write(long ioaddr, int phy_id, int location, int value); +static void epic_restart(struct device *dev); static void epic_timer(unsigned long data); static void epic_tx_timeout(struct device *dev); static void epic_init_ring(struct device *dev); static int epic_start_xmit(struct sk_buff *skb, struct device *dev); static int epic_rx(struct device *dev); static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs); +static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd); static int epic_close(struct device *dev); -static struct enet_statistics *epic_get_stats(struct device *dev); -#ifdef NEW_MULTICAST +static struct net_device_stats *epic_get_stats(struct device *dev); static void set_rx_mode(struct device *dev); -#else -static void set_rx_mode(struct device *dev, int num_addrs, void *addrs); -#endif - -#ifdef MODULE /* A list of all installed EPIC devices, for removing the driver module. */ static struct device *root_epic_dev = NULL; -#endif +#ifndef CARDBUS int epic100_probe(struct device *dev) { int cards_found = 0; - static int pci_index = 0; /* Static, for multiple probe calls. */ + int chip_idx, irq; + u16 pci_command, new_command; + unsigned char pci_bus, pci_device_fn; + +#ifdef PCI_SUPPORT_VER2 + struct pci_dev *pcidev = NULL; + while ((pcidev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pcidev)) + != NULL) { + long pci_ioaddr = pcidev->base_address[0] & ~3; + int vendor = pcidev->vendor; + int device = pcidev->device; + + for (chip_idx = 0; chip_tbl[chip_idx].vendor_id; chip_idx++) + if (vendor == chip_tbl[chip_idx].vendor_id + && (device & chip_tbl[chip_idx].device_id_mask) == + chip_tbl[chip_idx].device_id) + break; + if (chip_tbl[chip_idx].vendor_id == 0 /* Compiled out! */ + || check_region(pci_ioaddr, chip_tbl[chip_idx].io_size)) + continue; + pci_bus = pcidev->bus->number; + pci_device_fn = pcidev->devfn; + irq = pcidev->irq; +#else + int pci_index; - /* Ideally we would detect all network cards in slot order. That would - be best done a central PCI probe dispatch, which wouldn't work - well with the current structure. So instead we detect just the - Epic cards in slot order. */ + if ( ! pcibios_present()) + return -ENODEV; - if (pci_present()) { - unsigned char pci_bus, pci_device_fn; + for (pci_index = 0; pci_index < 0xff; pci_index++) { + u8 pci_irq_line; + u16 vendor, device; + u32 pci_ioaddr; - for (;pci_index < 0xff; pci_index++) { -#if LINUX_VERSION_CODE >= 0x20155 - unsigned int pci_irq_line; - struct pci_dev *pdev; -#else - unsigned char pci_irq_line; -#endif - unsigned char pci_latency; - unsigned short pci_command, vendor, device; - unsigned int pci_ioaddr, chip_idx = 0; - - if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, -#ifdef REVERSE_PROBE_ORDER - 0xff - pci_index, -#else - pci_index, -#endif - &pci_bus, &pci_device_fn) - != PCIBIOS_SUCCESSFUL) + if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, + pci_index, &pci_bus, &pci_device_fn) + != PCIBIOS_SUCCESSFUL) + break; + pcibios_read_config_word(pci_bus, pci_device_fn, + PCI_VENDOR_ID, &vendor); + pcibios_read_config_word(pci_bus, pci_device_fn, + PCI_DEVICE_ID, &device); + + for (chip_idx = 0; chip_tbl[chip_idx].vendor_id; chip_idx++) + if (vendor == chip_tbl[chip_idx].vendor_id + && (device & chip_tbl[chip_idx].device_id_mask) == + chip_tbl[chip_idx].device_id) break; - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_VENDOR_ID, &vendor); - if (vendor != PCI_VENDOR_ID_SMC) - continue; - - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_DEVICE_ID, &device); -#if LINUX_VERSION_CODE >= 0x20155 - pdev = pci_find_slot(pci_bus, pci_device_fn); - pci_irq_line = pdev->irq; - pci_ioaddr = pdev->base_address[0]; -#else - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq_line); - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &pci_ioaddr); + if (chip_tbl[chip_idx].vendor_id == 0) /* Compiled out! */ + continue; + + pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_0, &pci_ioaddr); + pcibios_read_config_byte(pci_bus, pci_device_fn, + PCI_INTERRUPT_LINE, &pci_irq_line); + /* Remove I/O space marker in bit 0. */ + pci_ioaddr &= ~3; + irq = pci_irq_line; + + if (check_region(pci_ioaddr, chip_tbl[chip_idx].io_size)) + continue; #endif - /* Remove I/O space marker in bit 0. */ - pci_ioaddr &= ~3; - - if (device != PCI_DEVICE_ID_SMC_EPIC100) { - printk("Unknown SMC PCI ethernet chip type %4.4x detected:" - " not configured.\n", device); - continue; - } - if (epic_debug > 2) - printk("Found SMC PCI EPIC/100 at I/O %#x, IRQ %d.\n", - pci_ioaddr, pci_irq_line); - if (check_region(pci_ioaddr, EPIC_TOTAL_SIZE)) - continue; + /* EPIC-specific code: Soft-reset the chip ere setting as master. */ + outl(0x0001, pci_ioaddr + GENCTL); + + /* Activate the card: fix for brain-damaged Win98 BIOSes. */ + pcibios_read_config_word(pci_bus, pci_device_fn, + PCI_COMMAND, &pci_command); + new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO; + if (pci_command != new_command) { + printk(KERN_INFO " The PCI BIOS has not enabled Ethernet" + " device %4.4x-%4.4x." + " Updating PCI command %4.4x->%4.4x.\n", + vendor, device, pci_command, new_command); + pcibios_write_config_word(pci_bus, pci_device_fn, + PCI_COMMAND, new_command); + } -#ifdef MODULE - dev = epic100_probe1(dev, pci_ioaddr, pci_irq_line, chip_idx, - options[cards_found], cards_found); -#else - dev = epic100_probe1(dev, pci_ioaddr, pci_irq_line, chip_idx, - dev ? dev->mem_start : 0, -1); -#endif + dev = chip_tbl[chip_idx].probe1(pci_bus, pci_device_fn, dev, pci_ioaddr, + irq, chip_idx, cards_found); - if (dev) { - /* Get and check the bus-master and latency values. */ - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, &pci_command); - if ( ! (pci_command & PCI_COMMAND_MASTER)) { - printk(" PCI Master Bit has not been set! Setting...\n"); - pci_command |= PCI_COMMAND_MASTER; - pcibios_write_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, pci_command); - } - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, &pci_latency); - if (pci_latency < 10) { - printk(" PCI latency timer (CFLT) is unreasonably low at %d." - " Setting to 255 clocks.\n", pci_latency); + /* Check the latency timer. */ + if (dev) { + u8 pci_latency; + pcibios_read_config_byte(pci_bus, pci_device_fn, + PCI_LATENCY_TIMER, &pci_latency); + if (pci_latency < chip_tbl[chip_idx].min_latency) { + printk(KERN_INFO " PCI latency timer (CFLT) value of %d is " + "unreasonably low, setting to %d.\n", pci_latency, + chip_tbl[chip_idx].min_latency); pcibios_write_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, 255); - } else if (epic_debug > 1) - printk(" PCI latency timer (CFLT) is %#x.\n", pci_latency); - dev = 0; - cards_found++; + PCI_LATENCY_TIMER, + chip_tbl[chip_idx].min_latency); } + dev = 0; + cards_found++; } } -#if defined (MODULE) - return cards_found; -#else return cards_found ? 0 : -ENODEV; -#endif } +#endif /* not CARDBUS */ -static struct device *epic100_probe1(struct device *dev, int ioaddr, int irq, - int chip_id, int options, int card_idx) +static struct device *epic_probe1(int pci_bus, int pci_devfn, + struct device *dev, long ioaddr, int irq, + int chip_idx, int card_idx) { - static int did_version = 0; /* Already printed version info. */ - struct epic_private *tp; - int i; - - if (epic_debug > 0 && did_version++ == 0) - printk(version); + struct epic_private *ep; + int i, option = 0, duplex = 0; + + if (dev && dev->mem_start) { + option = dev->mem_start; + duplex = (dev->mem_start & 16) ? 1 : 0; + } else if (card_idx >= 0 && card_idx < MAX_UNITS) { + if (options[card_idx] >= 0) + option = options[card_idx]; + if (full_duplex[card_idx] >= 0) + duplex = full_duplex[card_idx]; + } dev = init_etherdev(dev, 0); - printk("%s: SMC EPIC/100 at %#3x, IRQ %d, ", dev->name, ioaddr, irq); + dev->base_addr = ioaddr; + dev->irq = irq; + printk(KERN_INFO "%s: SMC EPIC/100 at %#lx, IRQ %d, ", + dev->name, ioaddr, dev->irq); /* Bring the chip out of low-power mode. */ - outl(0x0200, ioaddr + GENCTL); + outl(0x4200, ioaddr + GENCTL); /* Magic?! If we don't set this bit the MII interface won't work. */ outl(0x0008, ioaddr + TEST1); + /* Turn on the MII transceiver. */ + outl(0x12, ioaddr + MIICfg); + if (chip_idx == 1) + outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL); + outl(0x0200, ioaddr + GENCTL); + /* This could also be read from the EEPROM. */ for (i = 0; i < 3; i++) ((u16 *)dev->dev_addr)[i] = inw(ioaddr + LAN0 + i*4); @@ -416,65 +428,68 @@ static struct device *epic100_probe1(struct device *dev, int ioaddr, int irq, printk("%2.2x.\n", dev->dev_addr[i]); if (epic_debug > 1) { - printk("%s: EEPROM contents\n", dev->name); - for (i = 0; i < 64; i++) - printk(" %4.4x%s", read_eeprom(ioaddr, i), i % 16 == 15 ? "\n" : ""); + printk(KERN_DEBUG "%s: EEPROM contents\n", dev->name); + for (i = 0; i < 64; i++) + printk(" %4.4x%s", read_eeprom(ioaddr, i), + i % 16 == 15 ? "\n" : ""); } /* We do a request_region() to register /proc/ioports info. */ - request_region(ioaddr, EPIC_TOTAL_SIZE, "SMC EPIC/100"); - - dev->base_addr = ioaddr; - dev->irq = irq; + request_region(ioaddr, EPIC_TOTAL_SIZE, dev->name); /* The data structures must be quadword aligned. */ - tp = kmalloc(sizeof(*tp), GFP_KERNEL | GFP_DMA); - memset(tp, 0, sizeof(*tp)); - dev->priv = tp; + ep = kmalloc(sizeof(*ep), GFP_KERNEL | GFP_DMA); + memset(ep, 0, sizeof(*ep)); + dev->priv = ep; -#ifdef MODULE - tp->next_module = root_epic_dev; + ep->next_module = root_epic_dev; root_epic_dev = dev; -#endif - tp->chip_id = chip_id; + ep->pci_bus = pci_bus; + ep->pci_dev_fn = pci_devfn; +#if defined(PCI_SUPPORT_VER2) + ep->chip_id = pci_find_slot(pci_bus, pci_devfn)->device; +#else + ep->chip_id = chip_tbl[chip_idx].device_id; +#endif /* Find the connected MII xcvrs. Doing this in open() would allow detecting external xcvrs later, but takes too much time. */ { int phy, phy_idx; - for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys); + for (phy = 1, phy_idx = 0; phy < 32 && phy_idx < sizeof(ep->phys); phy++) { - int mii_status = mii_read(ioaddr, phy, 0); + int mii_status = mdio_read(ioaddr, phy, 1); if (mii_status != 0xffff && mii_status != 0x0000) { - tp->phys[phy_idx++] = phy; - printk("%s: MII transceiver found at address %d.\n", - dev->name, phy); + ep->phys[phy_idx++] = phy; + printk(KERN_INFO "%s: MII transceiver #%d control " + "%4.4x status %4.4x.\n" + KERN_INFO "%s: Autonegotiation advertising %4.4x " + "link partner %4.4x.\n", + dev->name, phy, mdio_read(ioaddr, phy, 0), mii_status, + dev->name, mdio_read(ioaddr, phy, 4), + mdio_read(ioaddr, phy, 5)); } } if (phy_idx == 0) { - printk("%s: ***WARNING***: No MII transceiver found!\n", + printk(KERN_WARNING "%s: ***WARNING***: No MII transceiver found!\n", dev->name); /* Use the known PHY address of the EPII. */ - tp->phys[0] = 3; + ep->phys[0] = 3; } } - /* Leave the chip in low-power mode. */ + /* Turn off the MII xcvr (175 only!), leave the chip in low-power mode. */ + if (ep->chip_id == 6) + outl(inl(ioaddr + NVCTL) & ~0x483C, ioaddr + NVCTL); outl(0x0008, ioaddr + GENCTL); /* The lower four bits are the media type. */ - if (options > 0) { - tp->full_duplex = (options & 16) ? 1 : 0; - tp->default_port = options & 15; - if (tp->default_port) - tp->medialock = 1; - } - if (card_idx >= 0) { - if (full_duplex[card_idx] >= 0) - tp->full_duplex = full_duplex[card_idx]; - } + ep->force_fd = duplex; + ep->default_port = option; + if (ep->default_port) + ep->medialock = 1; /* The Epic-specific entries in the device structure. */ dev->open = &epic_open; @@ -482,6 +497,7 @@ static struct device *epic100_probe1(struct device *dev, int ioaddr, int irq, dev->stop = &epic_close; dev->get_stats = &epic_get_stats; dev->set_multicast_list = &set_rx_mode; + dev->do_ioctl = &mii_ioctl; return dev; } @@ -498,41 +514,42 @@ static struct device *epic100_probe1(struct device *dev, int ioaddr, int irq, #define EE_ENB (0x0001 | EE_CS) /* Delay between EEPROM clock transitions. - The 1.2 code is a "nasty" timing loop, but PC compatible machines are - *supposed* to delay an ISA-compatible period for the SLOW_DOWN_IO macro. */ + No extra delay is needed with 33Mhz PCI, but 66Mhz is untested. + */ + #ifdef _LINUX_DELAY_H -#define eeprom_delay(nanosec) udelay((nanosec + 999)/1000) +#define eeprom_delay(nanosec) udelay(1) #else -#define eeprom_delay(nanosec) do { int _i = 3; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0) +#define eeprom_delay(nanosec) do { ; } while (0) #endif /* The EEPROM commands include the alway-set leading bit. */ #define EE_WRITE_CMD (5 << 6) -#define EE_READ_CMD (6 << 6) +#define EE_READ64_CMD (6 << 6) +#define EE_READ256_CMD (6 << 8) #define EE_ERASE_CMD (7 << 6) -static int read_eeprom(int ioaddr, int location) +static int read_eeprom(long ioaddr, int location) { int i; int retval = 0; - int ee_addr = ioaddr + EECTL; - int read_cmd = location | EE_READ_CMD; - + long ee_addr = ioaddr + EECTL; + int read_cmd = location | + (inl(ee_addr) & 0x40) ? EE_READ64_CMD : EE_READ256_CMD; + outl(EE_ENB & ~EE_CS, ee_addr); outl(EE_ENB, ee_addr); - + /* Shift the read command bits out. */ - for (i = 10; i >= 0; i--) { - short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; + for (i = 12; i >= 0; i--) { + short dataval = (read_cmd & (1 << i)) ? EE_WRITE_1 : EE_WRITE_0; outl(EE_ENB | dataval, ee_addr); eeprom_delay(100); outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); eeprom_delay(150); - outl(EE_ENB | dataval, ee_addr); /* Finish EEPROM a clock tick. */ - eeprom_delay(250); } outl(EE_ENB, ee_addr); - + for (i = 16; i > 0; i--) { outl(EE_ENB | EE_SHIFT_CLK, ee_addr); eeprom_delay(100); @@ -548,7 +565,7 @@ static int read_eeprom(int ioaddr, int location) #define MII_READOP 1 #define MII_WRITEOP 2 -static int mii_read(int ioaddr, int phy_id, int location) +static int mdio_read(long ioaddr, int phy_id, int location) { int i; @@ -556,66 +573,82 @@ static int mii_read(int ioaddr, int phy_id, int location) /* Typical operation takes < 50 ticks. */ for (i = 4000; i > 0; i--) if ((inl(ioaddr + MIICtrl) & MII_READOP) == 0) + return inw(ioaddr + MIIData); + return 0xffff; +} + +static void mdio_write(long ioaddr, int phy_id, int location, int value) +{ + int i; + + outw(value, ioaddr + MIIData); + outl((phy_id << 9) | (location << 4) | MII_WRITEOP, ioaddr + MIICtrl); + for (i = 10000; i > 0; i--) { + if ((inl(ioaddr + MIICtrl) & MII_WRITEOP) == 0) break; - return inw(ioaddr + MIIData); + } + return; } static int epic_open(struct device *dev) { - struct epic_private *tp = (struct epic_private *)dev->priv; - int ioaddr = dev->base_addr; + struct epic_private *ep = (struct epic_private *)dev->priv; + long ioaddr = dev->base_addr; int i; int mii_reg5; - int full_duplex = 0; + ep->full_duplex = ep->force_fd; /* Soft reset the chip. */ - outl(0x0001, ioaddr + GENCTL); + outl(0x4001, ioaddr + GENCTL); -#ifdef SA_SHIRQ - if (request_irq(dev->irq, &epic_interrupt, SA_SHIRQ, - "SMC EPIC/100", dev)) { + if (request_irq(dev->irq, &epic_interrupt, SA_SHIRQ, "SMC EPIC/100", dev)) return -EAGAIN; - } -#else - if (irq2dev_map[dev->irq] != NULL - || (irq2dev_map[dev->irq] = dev) == NULL - || dev->irq == 0 - || request_irq(dev->irq, &epic_interrupt, 0, "SMC EPIC/100")) { - return -EAGAIN; - } -#endif MOD_INC_USE_COUNT; epic_init_ring(dev); - /* This next line by Ken Yamaguchi.. ?? */ - outl(0x8, ioaddr + 0x1c); + outl(0x4000, ioaddr + GENCTL); + /* This next magic! line by Ken Yamaguchi.. ?? */ + outl(0x0008, ioaddr + TEST1); - /* Pull the chip out of low-power mode, enable interrupts, and set for PCI read multiple. */ + /* Pull the chip out of low-power mode, enable interrupts, and set for + PCI read multiple. The MIIcfg setting and strange write order are + required by the details of which bits are reset and the transceiver + wiring on the Ositech CardBus card. + */ + outl(0x12, ioaddr + MIICfg); + if (ep->chip_id == 6) + outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL); + +#if defined(__powerpc__) || defined(__sparc__) /* Big endian */ + outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL); +#else outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL); +#endif for (i = 0; i < 3; i++) outl(((u16*)dev->dev_addr)[i], ioaddr + LAN0 + i*4); outl(TX_FIFO_THRESH, ioaddr + TxThresh); - full_duplex = tp->full_duplex; - mii_reg5 = mii_read(ioaddr, tp->phys[0], 5); - if (mii_reg5 != 0xffff && (mii_reg5 & 0x0100)) { - full_duplex = 1; + mii_reg5 = mdio_read(ioaddr, ep->phys[0], 5); + if (mii_reg5 != 0xffff) { + if ((mii_reg5 & 0x0100) || (mii_reg5 & 0x01C0) == 0x0040) + ep->full_duplex = 1; + else if (! (mii_reg5 & 0x4000)) + mdio_write(ioaddr, ep->phys[0], 0, 0x1200); if (epic_debug > 1) - printk("%s: Setting %s-duplex based on MII xcvr %d" + printk(KERN_INFO "%s: Setting %s-duplex based on MII xcvr %d" " register read of %4.4x.\n", dev->name, - full_duplex ? "full" : "half", tp->phys[0], - mii_read(ioaddr, tp->phys[0], 5)); + ep->full_duplex ? "full" : "half", ep->phys[0], mii_reg5); } - outl(full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl); - outl(virt_to_bus(tp->rx_ring), ioaddr + PRxCDAR); - outl(virt_to_bus(tp->tx_ring), ioaddr + PTxCDAR); + outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl); + outl(virt_to_bus(ep->rx_ring), ioaddr + PRxCDAR); + outl(virt_to_bus(ep->tx_ring), ioaddr + PTxCDAR); /* Start the chip's Rx process. */ set_rx_mode(dev); @@ -626,67 +659,160 @@ epic_open(struct device *dev) dev->start = 1; /* Enable interrupts by setting the interrupt mask. */ - outl(CntFull | TxUnderrun | TxDone + outl((ep->chip_id == 6 ? PCIBusErr175 : PCIBusErr170) + | CntFull | TxUnderrun | TxDone | RxError | RxOverflow | RxFull | RxHeader | RxDone, ioaddr + INTMASK); if (epic_debug > 1) - printk("%s: epic_open() ioaddr %4.4x IRQ %d status %4.4x %s-duplex.\n", + printk(KERN_DEBUG "%s: epic_open() ioaddr %lx IRQ %d status %4.4x " + "%s-duplex.\n", dev->name, ioaddr, dev->irq, inl(ioaddr + GENCTL), - full_duplex ? "full" : "half"); + ep->full_duplex ? "full" : "half"); /* Set the timer to switch to check for link beat and perhaps switch to an alternate media type. */ - init_timer(&tp->timer); - tp->timer.expires = RUN_AT((24*HZ)/10); /* 2.4 sec. */ - tp->timer.data = (unsigned long)dev; - tp->timer.function = &epic_timer; /* timer handler */ - add_timer(&tp->timer); + init_timer(&ep->timer); + ep->timer.expires = RUN_AT((24*HZ)/10); /* 2.4 sec. */ + ep->timer.data = (unsigned long)dev; + ep->timer.function = &epic_timer; /* timer handler */ + add_timer(&ep->timer); return 0; } +/* Reset the chip to recover from a PCI transaction error. + This may occur at interrupt time. */ +static void epic_pause(struct device *dev) +{ + long ioaddr = dev->base_addr; + struct epic_private *ep = (struct epic_private *)dev->priv; + + /* Disable interrupts by clearing the interrupt mask. */ + outl(0x00000000, ioaddr + INTMASK); + /* Stop the chip's Tx and Rx DMA processes. */ + outw(0x0061, ioaddr + COMMAND); + + /* Update the error counts. */ + if (inw(ioaddr + COMMAND) != 0xffff) { + ep->stats.rx_missed_errors += inb(ioaddr + MPCNT); + ep->stats.rx_frame_errors += inb(ioaddr + ALICNT); + ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT); + } + + /* Remove the packets on the Rx queue. */ + epic_rx(dev); +} + +static void epic_restart(struct device *dev) +{ + long ioaddr = dev->base_addr; + struct epic_private *ep = (struct epic_private *)dev->priv; + int i; + + printk(KERN_DEBUG "%s: Restarting the EPIC chip, Rx %d/%d Tx %d/%d.\n", + dev->name, ep->cur_rx, ep->dirty_rx, ep->dirty_tx, ep->cur_tx); + /* Soft reset the chip. */ + outl(0x0001, ioaddr + GENCTL); + + udelay(1); + /* Duplicate code from epic_open(). */ + outl(0x0008, ioaddr + TEST1); + +#if defined(__powerpc__) /* Big endian */ + outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL); +#else + outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL); +#endif + outl(0x12, ioaddr + MIICfg); + if (ep->chip_id == 6) + outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL); + + for (i = 0; i < 3; i++) + outl(((u16*)dev->dev_addr)[i], ioaddr + LAN0 + i*4); + + outl(TX_FIFO_THRESH, ioaddr + TxThresh); + outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl); + outl(virt_to_bus(&ep->rx_ring[ep->cur_rx%RX_RING_SIZE]), ioaddr + PRxCDAR); + outl(virt_to_bus(&ep->tx_ring[ep->dirty_tx%TX_RING_SIZE]), + ioaddr + PTxCDAR); + + /* Start the chip's Rx process. */ + set_rx_mode(dev); + outl(0x000A, ioaddr + COMMAND); + + /* Enable interrupts by setting the interrupt mask. */ + outl((ep->chip_id == 6 ? PCIBusErr175 : PCIBusErr170) + | CntFull | TxUnderrun | TxDone + | RxError | RxOverflow | RxFull | RxHeader | RxDone, + ioaddr + INTMASK); + printk(KERN_DEBUG "%s: epic_restart() done, cmd status %4.4x, ctl %4.4x" + " interrupt %4.4x.\n", + dev->name, inl(ioaddr + COMMAND), inl(ioaddr + GENCTL), + inl(ioaddr + INTSTAT)); + return; +} + static void epic_timer(unsigned long data) { struct device *dev = (struct device *)data; - struct epic_private *tp = (struct epic_private *)dev->priv; - int ioaddr = dev->base_addr; + struct epic_private *ep = (struct epic_private *)dev->priv; + long ioaddr = dev->base_addr; int next_tick = 0; + int mii_reg5 = mdio_read(ioaddr, ep->phys[0], 5); if (epic_debug > 3) { - printk("%s: Media selection tick, Tx status %8.8x.\n", + printk(KERN_DEBUG "%s: Media selection tick, Tx status %8.8x.\n", dev->name, inl(ioaddr + TxSTAT)); - printk("%s: Other registers are IntMask %4.4x IntStatus %4.4x RxStatus" - " %4.4x.\n", + printk(KERN_DEBUG "%s: Other registers are IntMask %4.4x " + "IntStatus %4.4x RxStatus %4.4x.\n", dev->name, inl(ioaddr + INTMASK), inl(ioaddr + INTSTAT), inl(ioaddr + RxSTAT)); } + if (! ep->force_fd && mii_reg5 != 0xffff) { + int duplex = (mii_reg5&0x0100) || (mii_reg5 & 0x01C0) == 0x0040; + if (ep->full_duplex != duplex) { + ep->full_duplex = duplex; + printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d link" + " partner capability of %4.4x.\n", dev->name, + ep->full_duplex ? "full" : "half", ep->phys[0], mii_reg5); + outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl); + } + next_tick = 60*HZ; + } if (next_tick) { - tp->timer.expires = RUN_AT(next_tick); - add_timer(&tp->timer); + ep->timer.expires = RUN_AT(next_tick); + add_timer(&ep->timer); } } static void epic_tx_timeout(struct device *dev) { - struct epic_private *tp = (struct epic_private *)dev->priv; - int ioaddr = dev->base_addr; + struct epic_private *ep = (struct epic_private *)dev->priv; + long ioaddr = dev->base_addr; if (epic_debug > 0) { - printk("%s: Transmit timeout using MII device, Tx status %4.4x.\n", + printk(KERN_WARNING "%s: Transmit timeout using MII device, " + "Tx status %4.4x.\n", dev->name, inw(ioaddr + TxSTAT)); if (epic_debug > 1) { - printk("%s: Tx indices: dirty_tx %d, cur_tx %d.\n", - dev->name, tp->dirty_tx, tp->cur_tx); + printk(KERN_DEBUG "%s: Tx indices: dirty_tx %d, cur_tx %d.\n", + dev->name, ep->dirty_tx, ep->cur_tx); } } + if (inw(ioaddr + TxSTAT) & 0x10) { /* Tx FIFO underflow. */ + ep->stats.tx_fifo_errors++; + /* Restart the transmit process. */ + outl(0x0080, ioaddr + COMMAND); + } + /* Perhaps stop and restart the chip's Tx processes . */ /* Trigger a transmit demand. */ outl(0x0004, dev->base_addr + COMMAND); dev->trans_start = jiffies; - tp->stats.tx_errors++; + ep->stats.tx_errors++; return; } @@ -694,66 +820,51 @@ static void epic_tx_timeout(struct device *dev) static void epic_init_ring(struct device *dev) { - struct epic_private *tp = (struct epic_private *)dev->priv; + struct epic_private *ep = (struct epic_private *)dev->priv; int i; - tp->tx_full = 0; - tp->cur_rx = tp->cur_tx = 0; - tp->dirty_rx = tp->dirty_tx = 0; + ep->tx_full = 0; + ep->cur_rx = ep->cur_tx = 0; + ep->dirty_rx = ep->dirty_tx = 0; for (i = 0; i < RX_RING_SIZE; i++) { - tp->rx_ring[i].status = 0x8000; /* Owned by Epic chip */ - tp->rx_ring[i].buflength = PKT_BUF_SZ; + ep->rx_ring[i].status = 0x8000; /* Owned by Epic chip */ + ep->rx_ring[i].buflength = PKT_BUF_SZ; { /* Note the receive buffer must be longword aligned. dev_alloc_skb() provides 16 byte alignment. But do *not* use skb_reserve() to align the IP header! */ struct sk_buff *skb; - skb = DEV_ALLOC_SKB(PKT_BUF_SZ); - tp->rx_skbuff[i] = skb; + skb = dev_alloc_skb(PKT_BUF_SZ); + ep->rx_skbuff[i] = skb; if (skb == NULL) break; /* Bad news! */ skb->dev = dev; /* Mark as being used by this device. */ -#if LINUX_VERSION_CODE > 0x10300 skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ - tp->rx_ring[i].bufaddr = virt_to_bus(skb->tail); -#else - tp->rx_ring[i].bufaddr = virt_to_bus(skb->data); -#endif + ep->rx_ring[i].bufaddr = virt_to_bus(skb->tail); } - tp->rx_ring[i].next = virt_to_bus(&tp->rx_ring[i+1]); + ep->rx_ring[i].next = virt_to_bus(&ep->rx_ring[i+1]); } /* Mark the last entry as wrapping the ring. */ - tp->rx_ring[i-1].next = virt_to_bus(&tp->rx_ring[0]); + ep->rx_ring[i-1].next = virt_to_bus(&ep->rx_ring[0]); /* The Tx buffer descriptor is filled in as needed, but we do need to clear the ownership bit. */ for (i = 0; i < TX_RING_SIZE; i++) { - tp->tx_skbuff[i] = 0; - tp->tx_ring[i].status = 0x0000; - tp->tx_ring[i].next = virt_to_bus(&tp->tx_ring[i+1]); + ep->tx_skbuff[i] = 0; + ep->tx_ring[i].status = 0x0000; + ep->tx_ring[i].next = virt_to_bus(&ep->tx_ring[i+1]); } - tp->tx_ring[i-1].next = virt_to_bus(&tp->tx_ring[0]); + ep->tx_ring[i-1].next = virt_to_bus(&ep->tx_ring[0]); } static int epic_start_xmit(struct sk_buff *skb, struct device *dev) { - struct epic_private *tp = (struct epic_private *)dev->priv; + struct epic_private *ep = (struct epic_private *)dev->priv; int entry; u32 flag; -#ifndef final_version - if (skb == NULL || skb->len <= 0) { - printk("%s: Obsolete driver layer request made: skbuff==NULL.\n", - dev->name); -#if 0 - dev_tint(dev); -#endif - return 0; - } -#endif - /* Block a timer-based transmit from overlapping. This could better be done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { @@ -767,37 +878,37 @@ epic_start_xmit(struct sk_buff *skb, struct device *dev) with the "ownership" bits last. */ /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % TX_RING_SIZE; + entry = ep->cur_tx % TX_RING_SIZE; - tp->tx_skbuff[entry] = skb; - tp->tx_ring[entry].txlength = (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN); - tp->tx_ring[entry].bufaddr = virt_to_bus(skb->data); - tp->tx_ring[entry].buflength = skb->len; + ep->tx_skbuff[entry] = skb; + ep->tx_ring[entry].txlength = (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN); + ep->tx_ring[entry].bufaddr = virt_to_bus(skb->data); + ep->tx_ring[entry].buflength = skb->len; - if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE/2) {/* Typical path */ + if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE/2) {/* Typical path */ flag = 0x10; /* No interrupt */ - dev->tbusy = 0; - } else if (tp->cur_tx - tp->dirty_tx == TX_RING_SIZE/2) { + clear_bit(0, (void*)&dev->tbusy); + } else if (ep->cur_tx - ep->dirty_tx == TX_RING_SIZE/2) { flag = 0x14; /* Tx-done intr. */ - dev->tbusy = 0; - } else if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE - 2) { + clear_bit(0, (void*)&dev->tbusy); + } else if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE - 2) { flag = 0x10; /* No Tx-done intr. */ - dev->tbusy = 0; + clear_bit(0, (void*)&dev->tbusy); } else { /* Leave room for two additional entries. */ flag = 0x14; /* Tx-done intr. */ - tp->tx_full = 1; + ep->tx_full = 1; } - tp->tx_ring[entry].control = flag; - tp->tx_ring[entry].status = 0x8000; /* Pass ownership to the chip. */ - tp->cur_tx++; + ep->tx_ring[entry].control = flag; + ep->tx_ring[entry].status = 0x8000; /* Pass ownership to the chip. */ + ep->cur_tx++; /* Trigger an immediate transmit demand. */ outl(0x0004, dev->base_addr + COMMAND); dev->trans_start = jiffies; if (epic_debug > 4) - printk("%s: Queued Tx packet size %d to slot %d, " + printk(KERN_DEBUG "%s: Queued Tx packet size %d to slot %d, " "flag %2.2x Tx status %8.8x.\n", dev->name, (int)skb->len, entry, flag, inl(dev->base_addr + TxSTAT)); @@ -807,27 +918,28 @@ epic_start_xmit(struct sk_buff *skb, struct device *dev) /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ -static void epic_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs) +static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs) { -#ifdef SA_SHIRQ struct device *dev = (struct device *)dev_instance; + struct epic_private *ep = (struct epic_private *)dev->priv; + long ioaddr = dev->base_addr; + int status, boguscnt = max_interrupt_work; + +#if defined(__i386__) + /* A lock to prevent simultaneous entry bug on Intel SMP machines. */ + if (test_and_set_bit(0, (void*)&dev->interrupt)) { + printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n", + dev->name); + dev->interrupt = 0; /* Avoid halting machine. */ + return; + } #else - struct device *dev = (struct device *)(irq2dev_map[irq]); -#endif - struct epic_private *lp; - int status, ioaddr, boguscnt = max_interrupt_work; - - if (dev == NULL) { - printk ("epic_interrupt(): irq %d for unknown device.\n", irq); + if (dev->interrupt) { + printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name); return; } - - ioaddr = dev->base_addr; - lp = (struct epic_private *)dev->priv; - if (dev->interrupt) - printk("%s: Re-entering the interrupt handler.\n", dev->name); - dev->interrupt = 1; +#endif do { status = inl(ioaddr + INTSTAT); @@ -838,18 +950,18 @@ static void epic_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs printk("%s: interrupt interrupt=%#8.8x new intstat=%#8.8x.\n", dev->name, status, inl(ioaddr + INTSTAT)); - if ((status & (RxDone | TxEmpty | TxDone)) == 0) + if ((status & IntrSummary) == 0) break; - if (status & RxDone) /* Rx interrupt */ + if (status & (RxDone | RxStarted | RxEarlyWarn)) epic_rx(dev); if (status & (TxEmpty | TxDone)) { int dirty_tx; - for (dirty_tx = lp->dirty_tx; dirty_tx < lp->cur_tx; dirty_tx++) { + for (dirty_tx = ep->dirty_tx; dirty_tx < ep->cur_tx; dirty_tx++) { int entry = dirty_tx % TX_RING_SIZE; - int txstatus = lp->tx_ring[entry].status; + int txstatus = ep->tx_ring[entry].status; if (txstatus < 0) break; /* It still hasn't been Txed */ @@ -861,66 +973,77 @@ static void epic_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs printk("%s: Transmit error, Tx status %8.8x.\n", dev->name, txstatus); #endif - lp->stats.tx_errors++; - if (txstatus & 0x1050) lp->stats.tx_aborted_errors++; - if (txstatus & 0x0008) lp->stats.tx_carrier_errors++; - if (txstatus & 0x0040) lp->stats.tx_window_errors++; - if (txstatus & 0x0010) lp->stats.tx_fifo_errors++; + ep->stats.tx_errors++; + if (txstatus & 0x1050) ep->stats.tx_aborted_errors++; + if (txstatus & 0x0008) ep->stats.tx_carrier_errors++; + if (txstatus & 0x0040) ep->stats.tx_window_errors++; + if (txstatus & 0x0010) ep->stats.tx_fifo_errors++; #ifdef ETHER_STATS - if (txstatus & 0x1000) lp->stats.collisions16++; + if (txstatus & 0x1000) ep->stats.collisions16++; #endif } else { #ifdef ETHER_STATS - if ((txstatus & 0x0002) != 0) lp->stats.tx_deferred++; + if ((txstatus & 0x0002) != 0) ep->stats.tx_deferred++; #endif - lp->stats.collisions += (txstatus >> 8) & 15; - lp->stats.tx_packets++; + ep->stats.collisions += (txstatus >> 8) & 15; + ep->stats.tx_packets++; } /* Free the original skb. */ - dev_kfree_skb(lp->tx_skbuff[entry]); - lp->tx_skbuff[entry] = 0; + DEV_FREE_SKB(ep->tx_skbuff[entry]); + ep->tx_skbuff[entry] = 0; } #ifndef final_version - if (lp->cur_tx - dirty_tx > TX_RING_SIZE) { + if (ep->cur_tx - dirty_tx > TX_RING_SIZE) { printk("%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n", - dev->name, dirty_tx, lp->cur_tx, lp->tx_full); + dev->name, dirty_tx, ep->cur_tx, ep->tx_full); dirty_tx += TX_RING_SIZE; } #endif - if (lp->tx_full && dev->tbusy - && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) { + if (ep->tx_full && dev->tbusy + && dirty_tx > ep->cur_tx - TX_RING_SIZE + 2) { /* The ring is no longer full, clear tbusy. */ - lp->tx_full = 0; - dev->tbusy = 0; + ep->tx_full = 0; + clear_bit(0, (void*)&dev->tbusy); mark_bh(NET_BH); } - lp->dirty_tx = dirty_tx; + ep->dirty_tx = dirty_tx; } /* Check uncommon events all at once. */ - if (status & (CntFull | TxUnderrun | RxOverflow)) { + if (status & (CntFull | TxUnderrun | RxOverflow | + PCIBusErr170 | PCIBusErr175)) { + if (status == 0xffffffff) /* Chip failed or removed (CardBus). */ + break; /* Always update the error counts to avoid overhead later. */ - lp->stats.rx_missed_errors += inb(ioaddr + MPCNT); - lp->stats.rx_frame_errors += inb(ioaddr + ALICNT); - lp->stats.rx_crc_errors += inb(ioaddr + CRCCNT); + ep->stats.rx_missed_errors += inb(ioaddr + MPCNT); + ep->stats.rx_frame_errors += inb(ioaddr + ALICNT); + ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT); if (status & TxUnderrun) { /* Tx FIFO underflow. */ - lp->stats.tx_fifo_errors++; - /* Restart the transmit process. */ - outl(0x0080, ioaddr + COMMAND); + ep->stats.tx_fifo_errors++; + outl(1536, ioaddr + TxThresh); + /* Restart the transmit process. */ + outl(0x0080, ioaddr + COMMAND); } if (status & RxOverflow) { /* Missed a Rx frame. */ - lp->stats.rx_errors++; + ep->stats.rx_errors++; + } + if (status & PCIBusErr170) { + printk(KERN_ERR "%s: PCI Bus Error! EPIC status %4.4x.\n", + dev->name, status); + epic_pause(dev); + epic_restart(dev); } /* Clear all error sources. */ outl(status & 0x7f18, ioaddr + INTSTAT); } if (--boguscnt < 0) { - printk("%s: Too much work at interrupt, IntrStatus=0x%8.8x.\n", + printk(KERN_ERR "%s: Too much work at interrupt, " + "IntrStatus=0x%8.8x.\n", dev->name, status); /* Clear all interrupt sources. */ outl(0x0001ffff, ioaddr + INTSTAT); @@ -929,133 +1052,101 @@ static void epic_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs } while (1); if (epic_debug > 3) - printk("%s: exiting interrupt, intr_status=%#4.4x.\n", + printk(KERN_DEBUG "%s: exiting interrupt, intr_status=%#4.4x.\n", dev->name, inl(ioaddr + INTSTAT)); - /* Code that should never be run! Perhaps remove after testing.. */ - { - static int stopit = 10; - if (dev->start == 0 && --stopit < 0) { - printk("%s: Emergency stop, looping startup interrupt.\n", - dev->name); - FREE_IRQ(irq, dev); - } - } - +#if defined(__i386__) + clear_bit(0, (void*)&dev->interrupt); +#else dev->interrupt = 0; +#endif return; } -static int -epic_rx(struct device *dev) +static int epic_rx(struct device *dev) { - struct epic_private *lp = (struct epic_private *)dev->priv; - int entry = lp->cur_rx % RX_RING_SIZE; + struct epic_private *ep = (struct epic_private *)dev->priv; + int entry = ep->cur_rx % RX_RING_SIZE; + int work_done = 0; if (epic_debug > 4) - printk(" In epic_rx(), entry %d %8.8x.\n", entry, - lp->rx_ring[entry].status); + printk(KERN_DEBUG " In epic_rx(), entry %d %8.8x.\n", entry, + ep->rx_ring[entry].status); /* If we own the next entry, it's a new packet. Send it up. */ - while (lp->rx_ring[entry].status >= 0) { - int status = lp->rx_ring[entry].status; + while (ep->rx_ring[entry].status >= 0 && ep->rx_skbuff[entry]) { + int status = ep->rx_ring[entry].status; if (epic_debug > 4) - printk(" epic_rx() status was %8.8x.\n", status); - if (status & 0x2000) { - printk("%s: Oversized Ethernet frame spanned multiple buffers," - " status %4.4x!\n", dev->name, status); - lp->stats.rx_length_errors++; - } else if (status & 0x0006) { - /* Rx Frame errors are counted in hardware. */ - lp->stats.rx_errors++; + printk(KERN_DEBUG " epic_rx() status was %8.8x.\n", status); + if (status & 0x2006) { + if (status & 0x2000) { + printk(KERN_WARNING "%s: Oversized Ethernet frame spanned " + "multiple buffers, status %4.4x!\n", dev->name, status); + ep->stats.rx_length_errors++; + } else if (status & 0x0006) + /* Rx Frame errors are counted in hardware. */ + ep->stats.rx_errors++; } else { /* Malloc up new buffer, compatible with net-2e. */ /* Omit the four octet CRC from the length. */ - short pkt_len = lp->rx_ring[entry].rxlength - 4; + short pkt_len = ep->rx_ring[entry].rxlength - 4; struct sk_buff *skb; - int rx_in_place = 0; - - /* Check if the packet is long enough to just accept without - copying to a properly sized skbuff. */ - if (pkt_len > rx_copybreak) { - struct sk_buff *newskb; - char *temp; - - /* Pass up the skb already on the Rx ring. */ - skb = lp->rx_skbuff[entry]; - temp = skb_put(skb, pkt_len); - if (bus_to_virt(lp->rx_ring[entry].bufaddr) != temp) - printk("%s: Warning -- the skbuff addresses do not match" - " in epic_rx: %p vs. %p / %p.\n", dev->name, - bus_to_virt(lp->rx_ring[entry].bufaddr), - skb->head, temp); - /* Get a fresh skbuff to replace the filled one. */ - newskb = DEV_ALLOC_SKB(PKT_BUF_SZ); - if (newskb) { - rx_in_place = 1; - lp->rx_skbuff[entry] = newskb; - newskb->dev = dev; -#if LINUX_VERSION_CODE > 0x10300 - /* Align IP on 16 byte boundaries */ - skb_reserve(newskb, 2); - lp->rx_ring[entry].bufaddr = virt_to_bus(newskb->tail); + + /* Check if the packet is long enough to accept without copying + to a minimally-sized skbuff. */ + if (pkt_len < rx_copybreak + && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { + skb->dev = dev; + skb_reserve(skb, 2); /* 16 byte align the IP header */ +#if 1 /* USE_IP_COPYSUM */ + eth_copy_and_sum(skb, bus_to_virt(ep->rx_ring[entry].bufaddr), + pkt_len, 0); + skb_put(skb, pkt_len); #else - lp->rx_ring[entry].bufaddr = virt_to_bus(newskb->data); -#endif - } else /* No memory, drop the packet. */ - skb = 0; - } else - skb = DEV_ALLOC_SKB(pkt_len + 2); - if (skb == NULL) { - int i; - printk("%s: Memory squeeze, deferring packet.\n", dev->name); - /* Check that at least two ring entries are free. - If not, free one and mark stats->rx_dropped++. */ - for (i = 0; i < RX_RING_SIZE; i++) - if (lp->rx_ring[(entry+i) % RX_RING_SIZE].status < 0) - break; - - if (i > RX_RING_SIZE -2) { - lp->stats.rx_dropped++; - lp->rx_ring[entry].status = 0x8000; - lp->cur_rx++; - } - break; - } - skb->dev = dev; - if (! rx_in_place) { - skb_reserve(skb, 2); /* 16 byte align the data fields */ memcpy(skb_put(skb, pkt_len), - bus_to_virt(lp->rx_ring[entry].bufaddr), pkt_len); + bus_to_virt(ep->rx_ring[entry].bufaddr), pkt_len); +#endif + } else { + skb_put(skb = ep->rx_skbuff[entry], pkt_len); + ep->rx_skbuff[entry] = NULL; } -#if LINUX_VERSION_CODE > 0x10300 skb->protocol = eth_type_trans(skb, dev); -#else - skb->len = pkt_len; -#endif netif_rx(skb); - lp->stats.rx_packets++; + ep->stats.rx_packets++; } - - lp->rx_ring[entry].status = 0x8000; - entry = (++lp->cur_rx) % RX_RING_SIZE; + work_done++; + entry = (++ep->cur_rx) % RX_RING_SIZE; } - return 0; + /* Refill the Rx ring buffers. */ + for (; ep->cur_rx - ep->dirty_rx > 0; ep->dirty_rx++) { + entry = ep->dirty_rx % RX_RING_SIZE; + if (ep->rx_skbuff[entry] == NULL) { + struct sk_buff *skb; + skb = ep->rx_skbuff[entry] = dev_alloc_skb(PKT_BUF_SZ); + if (skb == NULL) + break; + skb->dev = dev; /* Mark as being used by this device. */ + skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ + ep->rx_ring[entry].bufaddr = virt_to_bus(skb->tail); + work_done++; + } + ep->rx_ring[entry].status = 0x8000; + } + return work_done; } -static int -epic_close(struct device *dev) +static int epic_close(struct device *dev) { - int ioaddr = dev->base_addr; - struct epic_private *tp = (struct epic_private *)dev->priv; + long ioaddr = dev->base_addr; + struct epic_private *ep = (struct epic_private *)dev->priv; int i; dev->start = 0; dev->tbusy = 1; if (epic_debug > 1) - printk("%s: Shutting down ethercard, status was %2.2x.\n", + printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", dev->name, inl(ioaddr + INTSTAT)); /* Disable interrupts by clearing the interrupt mask. */ @@ -1064,67 +1155,61 @@ epic_close(struct device *dev) outw(0x0061, ioaddr + COMMAND); /* Update the error counts. */ - tp->stats.rx_missed_errors += inb(ioaddr + MPCNT); - tp->stats.rx_frame_errors += inb(ioaddr + ALICNT); - tp->stats.rx_crc_errors += inb(ioaddr + CRCCNT); + ep->stats.rx_missed_errors += inb(ioaddr + MPCNT); + ep->stats.rx_frame_errors += inb(ioaddr + ALICNT); + ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT); - del_timer(&tp->timer); + del_timer(&ep->timer); -#ifdef SA_SHIRQ free_irq(dev->irq, dev); -#else - free_irq(dev->irq); - irq2dev_map[dev->irq] = 0; -#endif /* Free all the skbuffs in the Rx queue. */ for (i = 0; i < RX_RING_SIZE; i++) { - struct sk_buff *skb = tp->rx_skbuff[i]; - tp->rx_skbuff[i] = 0; - tp->rx_ring[i].status = 0; /* Not owned by Epic chip. */ - tp->rx_ring[i].buflength = 0; - tp->rx_ring[i].bufaddr = 0xBADF00D0; /* An invalid address. */ + struct sk_buff *skb = ep->rx_skbuff[i]; + ep->rx_skbuff[i] = 0; + ep->rx_ring[i].status = 0; /* Not owned by Epic chip. */ + ep->rx_ring[i].buflength = 0; + ep->rx_ring[i].bufaddr = 0xBADF00D0; /* An invalid address. */ if (skb) { #if LINUX_VERSION_CODE < 0x20100 skb->free = 1; #endif - dev_kfree_skb(skb); + DEV_FREE_SKB(skb); } } for (i = 0; i < TX_RING_SIZE; i++) { - if (tp->tx_skbuff[i]) - dev_kfree_skb(tp->tx_skbuff[i]); - tp->tx_skbuff[i] = 0; + if (ep->tx_skbuff[i]) + DEV_FREE_SKB(ep->tx_skbuff[i]); + ep->tx_skbuff[i] = 0; } /* Green! Leave the chip in low-power mode. */ outl(0x0008, ioaddr + GENCTL); - + MOD_DEC_USE_COUNT; return 0; } -static struct enet_statistics * -epic_get_stats(struct device *dev) +static struct net_device_stats *epic_get_stats(struct device *dev) { - struct epic_private *tp = (struct epic_private *)dev->priv; - int ioaddr = dev->base_addr; + struct epic_private *ep = (struct epic_private *)dev->priv; + long ioaddr = dev->base_addr; if (dev->start) { /* Update the error counts. */ - tp->stats.rx_missed_errors += inb(ioaddr + MPCNT); - tp->stats.rx_frame_errors += inb(ioaddr + ALICNT); - tp->stats.rx_crc_errors += inb(ioaddr + CRCCNT); + ep->stats.rx_missed_errors += inb(ioaddr + MPCNT); + ep->stats.rx_frame_errors += inb(ioaddr + ALICNT); + ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT); } - return &tp->stats; + return &ep->stats; } /* Set or clear the multicast filter for this adaptor. Note that we only use exclusion around actually queueing the - new frame, not around filling tp->setup_frame. This is non-deterministic + new frame, not around filling ep->setup_frame. This is non-deterministic when re-entered but still correct. */ /* The little-endian AUTODIN II ethernet CRC calculation. @@ -1149,21 +1234,17 @@ static inline unsigned ether_crc_le(int length, unsigned char *data) } -#ifdef NEW_MULTICAST static void set_rx_mode(struct device *dev) -#else -static void set_rx_mode(struct device *dev, int num_addrs, void *addrs); -#endif { - int ioaddr = dev->base_addr; - struct epic_private *tp = (struct epic_private *)dev->priv; + long ioaddr = dev->base_addr; + struct epic_private *ep = (struct epic_private *)dev->priv; unsigned char mc_filter[8]; /* Multicast hash filter */ int i; if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ outl(0x002C, ioaddr + RxCtrl); /* Unconditionally log net taps. */ - printk("%s: Promiscuous mode enabled.\n", dev->name); + printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name); memset(mc_filter, 0xff, sizeof(mc_filter)); } else if ((dev->mc_count > 0) || (dev->flags & IFF_ALLMULTI)) { /* There is apparently a chip bug, so the multicast filter @@ -1184,45 +1265,176 @@ static void set_rx_mode(struct device *dev, int num_addrs, void *addrs); mc_filter); } /* ToDo: perhaps we need to stop the Tx and Rx process here? */ - if (memcmp(mc_filter, tp->mc_filter, sizeof(mc_filter))) { + if (memcmp(mc_filter, ep->mc_filter, sizeof(mc_filter))) { for (i = 0; i < 4; i++) outw(((u16 *)mc_filter)[i], ioaddr + MC0 + i*4); - memcpy(tp->mc_filter, mc_filter, sizeof(mc_filter)); + memcpy(ep->mc_filter, mc_filter, sizeof(mc_filter)); } return; } + +static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd) +{ + long ioaddr = dev->base_addr; + u16 *data = (u16 *)&rq->ifr_data; + + switch(cmd) { + case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ + data[0] = ((struct epic_private *)dev->priv)->phys[0] & 0x1f; + /* Fall Through */ + case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ + if (! dev->start) { + outl(0x0200, ioaddr + GENCTL); + outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL); + } + data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f); + if (! dev->start) { +#ifdef notdef + outl(0x0008, ioaddr + GENCTL); + outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL); +#endif + } + return 0; + case SIOCDEVPRIVATE+2: /* Write the specified MII register */ + if (!suser()) + return -EPERM; + if (! dev->start) { + outl(0x0200, ioaddr + GENCTL); + outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL); + } + mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]); + if (! dev->start) { +#ifdef notdef + outl(0x0008, ioaddr + GENCTL); + outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL); +#endif + } + return 0; + default: + return -EOPNOTSUPP; + } +} + -#ifdef MODULE +#ifdef CARDBUS -/* An additional parameter that may be passed in... */ -static int debug = -1; +#include -int -init_module(void) +static dev_node_t *epic_attach(dev_locator_t *loc) { - int cards_found; + struct device *dev; + u16 dev_id; + u32 io; + u8 bus, devfn, irq; + + if (loc->bus != LOC_PCI) return NULL; + bus = loc->b.pci.bus; devfn = loc->b.pci.devfn; + printk(KERN_DEBUG "epic_attach(bus %d, function %d)\n", bus, devfn); + pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io); + pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq); + pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id); + io &= ~3; + if (io == 0 || irq == 0) { + printk(KERN_ERR "The EPIC/C CardBus Ethernet interface was not " + "assigned an %s.\n" KERN_ERR " It will not be activated.\n", + io == 0 ? "I/O address" : "IRQ"); + return NULL; + } + dev = epic_probe1(bus, devfn, NULL, io, irq, 2, -1); + if (dev) { + dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL); + strcpy(node->dev_name, dev->name); + node->major = node->minor = 0; + node->next = NULL; + MOD_INC_USE_COUNT; + return node; + } + return NULL; +} - if (debug >= 0) - epic_debug = debug; +static void epic_suspend(dev_node_t *node) +{ + struct device **devp, **next; + printk(KERN_INFO "epic_suspend(%s)\n", node->dev_name); + for (devp = &root_epic_dev; *devp; devp = next) { + next = &((struct epic_private *)(*devp)->priv)->next_module; + if (strcmp((*devp)->name, node->dev_name) == 0) break; + } + if (*devp) { + long ioaddr = (*devp)->base_addr; + epic_pause(*devp); + /* Put the chip into low-power mode. */ + outl(0x0008, ioaddr + GENCTL); + } +} +static void epic_resume(dev_node_t *node) +{ + struct device **devp, **next; + printk(KERN_INFO "epic_resume(%s)\n", node->dev_name); + for (devp = &root_epic_dev; *devp; devp = next) { + next = &((struct epic_private *)(*devp)->priv)->next_module; + if (strcmp((*devp)->name, node->dev_name) == 0) break; + } + if (*devp) { + epic_restart(*devp); + } +} +static void epic_detach(dev_node_t *node) +{ + struct device **devp, **next; + printk(KERN_INFO "epic_detach(%s)\n", node->dev_name); + for (devp = &root_epic_dev; *devp; devp = next) { + next = &((struct epic_private *)(*devp)->priv)->next_module; + if (strcmp((*devp)->name, node->dev_name) == 0) break; + } + if (*devp) { + unregister_netdev(*devp); + kfree(*devp); + *devp = *next; + kfree(node); + MOD_DEC_USE_COUNT; + } +} - root_epic_dev = NULL; - cards_found = epic100_probe(0); +struct driver_operations epic_ops = { + "epic_cb", epic_attach, epic_suspend, epic_resume, epic_detach +}; - return cards_found ? 0 : -ENODEV; +#endif /* Cardbus support */ + + +#ifdef MODULE + +int init_module(void) +{ + if (epic_debug) + printk(KERN_INFO "%s", version); + +#ifdef CARDBUS + register_driver(&epic_ops); + return 0; +#else + return epic100_probe(0); +#endif } -void -cleanup_module(void) +void cleanup_module(void) { struct device *next_dev; +#ifdef CARDBUS + unregister_driver(&epic_ops); +#endif + /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ while (root_epic_dev) { - next_dev = ((struct epic_private *)root_epic_dev->priv)->next_module; + struct epic_private *ep = (struct epic_private *)root_epic_dev->priv; + next_dev = ep->next_module; unregister_netdev(root_epic_dev); release_region(root_epic_dev->base_addr, EPIC_TOTAL_SIZE); kfree(root_epic_dev); root_epic_dev = next_dev; + kfree(ep); } } @@ -1230,7 +1442,8 @@ cleanup_module(void) /* * Local variables: - * compile-command: "gcc -DMODULE -DMODVERSIONS -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c" + * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" + * cardbus-compile-command: "gcc -DCARDBUS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c -o epic_cb.o -I/usr/src/pcmcia-cs-3.0.5/include/" * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 4 diff --git a/drivers/net/irda/Config.in b/drivers/net/irda/Config.in new file mode 100644 index 000000000000..ffa7e062d0a3 --- /dev/null +++ b/drivers/net/irda/Config.in @@ -0,0 +1,16 @@ +mainmenu_option next_comment +comment 'Infrared-port device drivers' + +dep_tristate 'IrTTY (uses serial driver)' CONFIG_IRTTY_SIR $CONFIG_IRDA +if [ "$CONFIG_IRTTY_SIR" != "n" ]; then + comment ' Dongle support' + bool ' Serial dongle support' CONFIG_DONGLE + if [ "$CONFIG_DONGLE" != "n" ]; then + dep_tristate ' ESI JetEye PC dongle' CONFIG_ESI_DONGLE $CONFIG_IRTTY_SIR + dep_tristate ' ACTiSYS IR-220L and IR220L+ dongle' CONFIG_ACTISYS_DONGLE $CONFIG_IRTTY_SIR + dep_tristate ' Tekram IrMate 210B dongle' CONFIG_TEKRAM_DONGLE $CONFIG_IRTTY_SIR + fi +fi +dep_tristate ' NSC PC87108' CONFIG_NSC_FIR $CONFIG_IRDA +dep_tristate ' Winbond W83977AF (IR)' CONFIG_WINBOND_FIR $CONFIG_IRDA +endmenu diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile new file mode 100644 index 000000000000..acc00c14d477 --- /dev/null +++ b/drivers/net/irda/Makefile @@ -0,0 +1,72 @@ +# File: drivers/irda/Makefile +# +# Makefile for the Linux IrDA infrared port device drivers. +# + +SUB_DIRS := +MOD_SUB_DIRS := $(SUB_DIRS) +ALL_SUB_DIRS := $(SUB_DIRS) + +L_TARGET := irda_drivers.a +L_OBJS := +M_OBJS := +MOD_LIST_NAME := IRDA_MODULES + +ifeq ($(CONFIG_IRTTY_SIR),y) +L_OBJS += irtty.o +else + ifeq ($(CONFIG_IRTTY_SIR),m) + M_OBJS += irtty.o + endif +endif + +ifeq ($(CONFIG_NSC_FIR),y) +L_OBJS += pc87108.o +else + ifeq ($(CONFIG_NSC_FIR),m) + M_OBJS += pc87108.o + endif +endif + +ifeq ($(CONFIG_WINBOND_FIR),y) +L_OBJS += w83977af_ir.o +else + ifeq ($(CONFIG_WINBOND_FIR),m) + M_OBJS += w83977af_ir.o + endif +endif + +ifeq ($(CONFIG_ESI_DONGLE),y) +L_OBJS += esi.o +else + ifeq ($(CONFIG_ESI_DONGLE),m) + M_OBJS += esi.o + endif +endif + +ifeq ($(CONFIG_TEKRAM_DONGLE),y) +L_OBJS += tekram.o +else + ifeq ($(CONFIG_TEKRAM_DONGLE),m) + M_OBJS += tekram.o + endif +endif + +ifeq ($(CONFIG_ACTISYS_DONGLE),y) +L_OBJS += actisys.o +else + ifeq ($(CONFIG_ACTISYS_DONGLE),m) + M_OBJS += actisys.o + endif +endif + +include $(TOPDIR)/Rules.make + +clean: + rm -f core *.o *.a *.s + + + + + + diff --git a/drivers/net/irda/actisys.c b/drivers/net/irda/actisys.c new file mode 100644 index 000000000000..c419d92979f7 --- /dev/null +++ b/drivers/net/irda/actisys.c @@ -0,0 +1,315 @@ +/********************************************************************* + * + * Filename: actisys.c + * Version: 0.3 + * Description: Implementation for the ACTiSYS IR-220L and IR-220L+ + * dongles + * Status: Experimental. + * Author: Dag Brattli + * Created at: Wed Oct 21 20:02:35 1998 + * Modified at: Mon Dec 14 11:50:32 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +static void actisys_reset( struct irda_device *dev, int unused); +static void actisys_open( struct irda_device *idev, int type); +static void actisys_close( struct irda_device *dev); +static void actisys_change_speed( struct irda_device *dev, int baudrate); +static void actisys_reset( struct irda_device *dev, int unused); +static void actisys_init_qos( struct irda_device *idev, struct qos_info *qos); + +/* These are the baudrates supported */ +static int baud_rates[] = { 9600, 19200, 57600, 115200, 38400}; + +static struct dongle dongle = { + ACTISYS_DONGLE, + actisys_open, + actisys_close, + actisys_reset, + actisys_change_speed, + actisys_init_qos, +}; + +__initfunc(void actisys_init(void)) +{ + irtty_register_dongle(&dongle); +} + +void actisys_cleanup(void) +{ + irtty_unregister_dongle(&dongle); +} + +static void actisys_open( struct irda_device *idev, int type) +{ + strcat( idev->name, " <-> actisys"); + + idev->io.dongle_id = type; + + MOD_INC_USE_COUNT; +} + +static void actisys_close( struct irda_device *dev) +{ + MOD_DEC_USE_COUNT; +} + +/* + * Function actisys_change_speed (tty, baud) + * + * Change speed of the ACTiSYS IR-220L and IR-220L+ type IrDA dongles. + * To cycle through the available baud rates, pulse RTS low for a few ms. + * To be compatible with the new IR-220L+, we have to reset the dongle + * first since its not possible cycle around anymore and still be + * compatible with both dongles :-( + */ +static void actisys_change_speed( struct irda_device *idev, int baudrate) +{ + struct irtty_cb *self; + struct tty_struct *tty; + int arg = 0; + struct termios old_termios; + int cflag; + int current_baudrate; + int index = 0; + mm_segment_t fs; + + DEBUG( 0, __FUNCTION__ "()\n"); + + ASSERT( idev != NULL, return;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); + + self = (struct irtty_cb *) idev->priv; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRTTY_MAGIC, return;); + + current_baudrate = idev->qos.baud_rate.value; + + /* Find the correct baudrate index for the currently used baudrate */ + while ( current_baudrate != baud_rates[index]) + index++; + + DEBUG( 0, __FUNCTION__ "(), index=%d\n", index); + + if ( !self->tty) + return; + + tty = self->tty; + + /* Cycle through avaiable baudrates until we reach the correct one */ + while ( current_baudrate != baudrate) { + DEBUG( 0, __FUNCTION__ "(), current baudrate = %d\n", + baud_rates[index]); + DEBUG( 0, __FUNCTION__ "(), Clearing RTS\n"); + + /* Set DTR, clear RTS */ + arg = TIOCM_DTR; + + fs = get_fs(); + set_fs( get_ds()); + + if ( tty->driver.ioctl( tty, NULL, TIOCMSET, + (unsigned long) &arg)) { + DEBUG( 0, __FUNCTION__ + "Error clearing RTS!\n"); + } + set_fs(fs); + + /* Wait at a few ms */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(2); + + /* Set DTR, Set RTS */ + arg = TIOCM_DTR | TIOCM_RTS; + + fs = get_fs(); + set_fs( get_ds()); + + if ( tty->driver.ioctl( tty, NULL, TIOCMSET, + (unsigned long) &arg)) { + DEBUG( 0, __FUNCTION__ "Error setting RTS!\n"); + } + set_fs(fs); + + /* Wait at a few ms again */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout( 2); + + /* Go to next baudrate */ + if ( idev->io.dongle_id == ACTISYS_DONGLE) + index = (index+1) % 4; /* IR-220L */ + else + index = (index+1) % 5; /* IR-220L+ */ + + current_baudrate = baud_rates[index]; + } + DEBUG( 0, __FUNCTION__ "(), current baudrate = %d\n", + baud_rates[index]); + + /* Now change the speed of the serial port */ + old_termios = *(tty->termios); + cflag = tty->termios->c_cflag; + + cflag &= ~CBAUD; + + switch ( baudrate) { + case 9600: + default: + cflag |= B9600; + break; + case 19200: + cflag |= B19200; + break; + case 38400: + cflag |= B38400; + break; + case 57600: + cflag |= B57600; + break; + case 115200: + cflag |= B115200; + break; + } + + tty->termios->c_cflag = cflag; + + DEBUG( 0, __FUNCTION__ "(), Setting the speed of the serial port\n"); + tty->driver.set_termios( tty, &old_termios); +} + +/* + * Function actisys_reset (dev) + * + * Reset the Actisys type dongle. Warning, this function must only be + * called with a process context! + * + * 1. Clear DTR for a few ms. + * + */ +static void actisys_reset( struct irda_device *idev, int unused) +{ + struct irtty_cb *self; + struct tty_struct *tty; + int arg = 0; + mm_segment_t fs; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( idev != NULL, return;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); + + self = (struct irtty_cb *) idev->priv; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRTTY_MAGIC, return;); + + tty = self->tty; + if ( !tty) + return; + + DEBUG( 0, __FUNCTION__ "(), Clearing DTR\n"); + arg = TIOCM_RTS; + + fs = get_fs(); + set_fs( get_ds()); + + if ( tty->driver.ioctl( tty, NULL, TIOCMSET, + (unsigned long) &arg)) + { + DEBUG( 0, __FUNCTION__"(), Ioctl error!\n"); + } + set_fs(fs); + + /* Sleep 10-20 ms*/ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(2); + + DEBUG( 0, __FUNCTION__ "(), Setting DTR\n"); + arg = TIOCM_RTS | TIOCM_DTR; + + fs = get_fs(); + set_fs( get_ds()); + + if ( tty->driver.ioctl( tty, NULL, TIOCMSET, + (unsigned long) &arg)) + { + DEBUG( 0, __FUNCTION__"(), Ioctl error!\n"); + } + set_fs(fs); + + idev->qos.baud_rate.value = 9600; +} + +/* + * Function actisys_init_qos (qos) + * + * Initialize QoS capabilities + * + */ +static void actisys_init_qos( struct irda_device *idev, struct qos_info *qos) +{ + qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; + + /* Remove support for 38400 if this is not a 220L+ dongle */ + if ( idev->io.dongle_id == ACTISYS_DONGLE) + qos->baud_rate.bits &= ~IR_38400; + + qos->min_turn_time.bits &= 0xfe; /* All except 0 ms */ +} + +#ifdef MODULE + +/* + * Function init_module (void) + * + * Initialize Actisys module + * + */ +int init_module(void) +{ + actisys_init(); + return(0); +} + +/* + * Function cleanup_module (void) + * + * Cleanup Actisys module + * + */ +void cleanup_module(void) +{ + actisys_cleanup(); +} + +#endif diff --git a/drivers/net/irda/esi.c b/drivers/net/irda/esi.c new file mode 100644 index 000000000000..a5106658840f --- /dev/null +++ b/drivers/net/irda/esi.c @@ -0,0 +1,196 @@ +/********************************************************************* + * + * Filename: esi.c + * Version: 1.0 + * Description: Driver for the Extended Systems JetEye PC + * Status: Experimental. + * Author: Thomas Davis, + * Created at: Sat Feb 21 18:54:38 1998 + * Modified at: Mon Dec 14 11:48:22 1998 + * Modified by: Dag Brattli + * Sources: esi.c + * + * Copyright (c) 1998, Thomas Davis, , + * Copyright (c) 1998, Dag Brattli, + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * I, Thomas Davis, provide no warranty for any of this software. + * This material is provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +static void esi_open( struct irda_device *idev, int type); +static void esi_close( struct irda_device *driver); +static void esi_change_speed( struct irda_device *idev, int baud); +static void esi_reset( struct irda_device *idev, int unused); +static void esi_qos_init( struct irda_device *idev, struct qos_info *qos); + +static struct dongle dongle = { + ESI_DONGLE, + esi_open, + esi_close, + esi_reset, + esi_change_speed, + esi_qos_init, +}; + +__initfunc(void esi_init(void)) +{ + irtty_register_dongle( &dongle); +} + +void esi_cleanup(void) +{ + irtty_unregister_dongle( &dongle); +} + +static void esi_open( struct irda_device *idev, int type) +{ + strcat( idev->name, " <-> esi"); + + idev->io.dongle_id = type; + + MOD_INC_USE_COUNT; +} + +static void esi_close( struct irda_device *driver) +{ + MOD_DEC_USE_COUNT; +} + +/* + * Function esi_change_speed (tty, baud) + * + * Set the speed for the Extended Systems JetEye PC ESI-9680 type dongle + * + */ +static void esi_change_speed( struct irda_device *idev, int baud) +{ + struct irtty_cb *self; + struct tty_struct *tty; + int arg = 0; + struct termios old_termios; + int cflag; + mm_segment_t fs; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( idev != NULL, return;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); + + self = (struct irtty_cb *) idev->priv; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRTTY_MAGIC, return;); + + if ( !self->tty) + return; + + tty = self->tty; + + old_termios = *(tty->termios); + cflag = tty->termios->c_cflag; + + cflag &= ~CBAUD; + + switch (baud) { + case 19200: + cflag |= B19200; + arg = TIOCM_DTR; + break; + case 115200: + cflag |= B115200; + arg = TIOCM_RTS | TIOCM_DTR; + break; + case 9600: + default: + cflag |= B9600; + arg = TIOCM_RTS; + break; + } + + tty->termios->c_cflag = cflag; + tty->driver.set_termios( tty, &old_termios); + + /* + * The ioctl function, or actually set_modem_info in serial.c + * expects a pointer to the argument in user space. To hack us + * around this we use the set_fs function to fool the routines + * that check if they are called from user space. We also need + * to send a pointer to the argument so get_user() gets happy. + * DB. + */ + fs = get_fs(); + set_fs( get_ds()); + + if ( tty->driver.ioctl( tty, NULL, TIOCMSET, (unsigned long) &arg)) { + DEBUG(0, "error setting ESI speed!\n"); + } + set_fs(fs); +} + +static void esi_reset( struct irda_device *idev, int unused) +{ + /* Empty */ +} + +/* + * Function esi_qos_init (qos) + * + * Init QoS capabilities for the dongle + * + */ +static void esi_qos_init( struct irda_device *idev, struct qos_info *qos) +{ + qos->baud_rate.bits &= IR_9600|IR_19200|IR_115200; +} + +#ifdef MODULE + +/* + * Function init_module (void) + * + * Initialize ESI module + * + */ +int init_module(void) +{ + esi_init(); + return(0); +} + +/* + * Function cleanup_module (void) + * + * Cleanup ESI module + * + */ +void cleanup_module(void) +{ + esi_cleanup(); +} + +#endif diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c new file mode 100644 index 000000000000..9553ea978d57 --- /dev/null +++ b/drivers/net/irda/irport.c @@ -0,0 +1,361 @@ +/********************************************************************* + * + * Filename: irport.c + * Version: 0.1 + * Description: Serial driver for IrDA. The functions in this file + * may be used by FIR drivers, but this file knows + * nothing about FIR drivers!!! + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sun Aug 3 13:49:59 1997 + * Modified at: Sat May 23 23:15:20 1998 + * Modified by: Dag Brattli + * Sources: serial.c by Linus Torvalds + * serial_serial.c by Aage Kvalnes + * + * Copyright (c) 1997,1998 Dag Brattli + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +/* #include */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "irda.h" +#include "ircompat.h" +#include "irport.h" +#include "timer.h" +#include "crc.h" +#include "wrapper.h" +#include "irlap_frame.h" + +#define IO_EXTENT 8 + +static void irport_write_wakeup( struct irda_device *idev); +static int irport_write( int iobase, int fifo_size, __u8 *buf, int len); +static void irport_receive( struct irda_device *idev); + +/* + * Function irport_open (void) + * + * Start IO port + * + */ +int irport_open( int iobase) +{ + /* Initialize UART */ + outb_p( UART_LCR_WLEN8, iobase+UART_LCR); /* Reset DLAB */ + outb_p(( UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), + iobase+UART_MCR); + + /* Turn on interrups */ + outb_p(( UART_IER_THRI |UART_IER_RLSI | UART_IER_RDI), + iobase+UART_IER); + + return 0; +} + +/* + * Function irport_cleanup () + * + * Stop IO port + * + */ +void irport_close( int iobase) +{ + DEBUG( 0, __FUNCTION__ "()\n"); + + /* Reset UART */ + outb_p( 0, iobase+UART_MCR); + + /* Turn off interrupts */ + outb_p( 0, iobase+UART_IER); +} + +/* + * Function irport_change_speed (idev, speed) + * + * Set speed of port to specified baudrate + * + */ +void irport_change_speed( int iobase, int speed) +{ + int fcr; /* FIFO control reg */ + int lcr; /* Line control reg */ + int divisor; + + DEBUG( 0, __FUNCTION__ "(), Setting speed to: %d\n", speed); + + /* Turn off interrupts */ + outb_p( 0, iobase+UART_IER); + + divisor = SPEED_MAX/speed; + + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14; + + /* IrDA ports use 8N1 */ + lcr = UART_LCR_WLEN8; + + outb_p( UART_LCR_DLAB | lcr, iobase+UART_LCR); /* Set DLAB */ + outb_p( divisor & 0xff, iobase+UART_DLL); /* Set speed */ + outb_p( divisor >> 8, iobase+UART_DLM); + outb_p( lcr, iobase+UART_LCR); /* Set 8N1 */ + outb_p( fcr, iobase+UART_FCR); /* Enable FIFO's */ + + /* Turn on interrups */ + outb_p(( UART_IER_THRI |UART_IER_RLSI | UART_IER_RDI), + iobase+UART_IER); +} + +/* + * Function irport_interrupt (irq, dev_id, regs) + * + * + */ +void irport_interrupt( int irq, void *dev_id, struct pt_regs *regs) +{ + struct irda_device *idev = (struct irda_device *) dev_id; + + int iobase, status; + int iir; + + DEBUG( 4, __FUNCTION__ "(), irq %d\n", irq); + + if ( !idev) { + printk( KERN_WARNING __FUNCTION__ + "() irq %d for unknown device.\n", irq); + return; + } + + iobase = idev->io.iobase; + iir = inb( iobase + UART_IIR); + + do { + status = inb( iobase+UART_LSR); + + if ( status & UART_LSR_DR) { + /* Receive interrupt */ + irport_receive( idev); + } + if ( status & UART_LSR_THRE) { + /* Transmitter ready for data */ + irport_write_wakeup( idev); + } + } while ( !(inb( iobase+UART_IIR) & UART_IIR_NO_INT)); +} + +/* + * Function irport_write_wakeup (tty) + * + * Called by the driver when there's room for more data. If we have + * more packets to send, we send them here. + * + */ +static void irport_write_wakeup( struct irda_device *idev) +{ + int actual = 0, count; + + DEBUG( 4, __FUNCTION__ "() <%ld>\n", jiffies); + + /* + * First make sure we're connected. + */ + ASSERT( idev != NULL, return;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); + + /* + * Finished with frame? + */ + if ( idev->tx.ptr == idev->tx.len) { + + /* + * Now serial buffer is almost free & we can start + * transmission of another packet + */ + DEBUG( 4, __FUNCTION__ "(), finished with frame!\n"); + + idev->netdev.tbusy = 0; /* Unlock */ + idev->stats.tx_packets++; + + /* Schedule network layer, so we can get some more frames */ + mark_bh( NET_BH); + return; + } + /* + * Write data left in transmit buffer + */ + count = idev->tx.len - idev->tx.ptr; + actual = irport_write( idev->io.iobase, idev->io.fifo_size, + idev->tx.head, count); + idev->tx.ptr += actual; + idev->tx.head += actual; +} + +/* + * Function irport_write (driver) + * + * + * + */ +static int irport_write( int iobase, int fifo_size, __u8 *buf, int len) +{ + int actual = 0; + + if (!(inb_p( iobase+UART_LSR) & UART_LSR_THRE)) { + DEBUG( 0, __FUNCTION__ "(), failed, fifo not empty!\n"); + return -1; + } + + /* Fill FIFO with current frame */ + while (( fifo_size-- > 0) && (actual < len)) { + /* Transmit next byte */ + outb( buf[actual], iobase+UART_TX); + + actual++; + } + + DEBUG( 4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", + fifo_size, actual, len); + + return actual; +} + +/* + * Function irport_xmit (void) + * + * Transmits the current frame until FIFO is full, then + * waits until the next transmitt interrupt, and continues until the + * frame is transmited. + */ +int irport_hard_xmit( struct sk_buff *skb, struct device *dev) +{ + struct irda_device *idev; + int xbofs; + int actual; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( dev != NULL, return -1;); + + if ( dev->tbusy) { + DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n"); + + return -EBUSY; + } + + idev = (struct irda_device *) dev->priv; + + ASSERT( idev != NULL, return -1;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;); + + if ( skb == NULL) { + DEBUG( 0, __FUNCTION__ "(), skb==NULL\n"); +#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,0) + dev_tint(dev); +#endif + return 0; + } + + /* Lock transmit buffer */ + if ( irda_lock( (void *) &dev->tbusy) == FALSE) + return -EBUSY; + + /* + * Transfer skb to tx_buff while wrapping, stuffing and making CRC + */ + idev->tx.len = async_wrap_skb( skb, idev->tx.buff, idev->tx.buffsize); + + actual = irport_write( idev->io.iobase, idev->io.fifo_size, + idev->tx.buff, idev->tx.len); + + idev->tx.ptr = actual; + idev->tx.head = idev->tx.buff + actual; + + IS_SKB( skb, return 0;); + FREE_SKB_MAGIC( skb); + DEV_KFREE_SKB( skb, FREE_WRITE); + + return 0; +} + +/* + * Function irport_receive (void) + * + * Receive one frame from the infrared port + * + */ +static void irport_receive( struct irda_device *idev) +{ + __u8 byte = 0x00; + int iobase; + + if ( !idev) + return; + + DEBUG( 0, __FUNCTION__ "()\n"); + + iobase = idev->io.iobase; + + if ( idev->rx.len == 0) { + idev->rx.head = idev->rx.buff; + } + + /* + * Receive all characters in FIFO + */ + do { + byte = inb_p( iobase+UART_RX); + async_unwrap_char( idev, byte); + + } while ( inb_p( iobase+UART_LSR) & UART_LSR_DR); +} + +/* + * Function cleanup_module (void) + * + * + * + */ +/* void cleanup_module(void) */ +/* { */ +/* DEBUG( 3, "IrPORT: cleanup_module!\n"); */ +/* irport_cleanup(irport_drv); */ +/* } */ + +/* + * Function init_module (void) + * + * + * + */ +/* int init_module(void) */ +/* { */ +/* if (irport_init() < 0) { */ +/* cleanup_module(); */ +/* return 1; */ +/* } */ +/* return(0); */ +/* } */ + diff --git a/drivers/net/irda/irtty.c b/drivers/net/irda/irtty.c new file mode 100644 index 000000000000..5d68763c65c2 --- /dev/null +++ b/drivers/net/irda/irtty.c @@ -0,0 +1,748 @@ +/********************************************************************* + * + * Filename: irtty.c + * Version: 1.0 + * Description: IrDA line discipline implementation + * Status: Experimental. + * Author: Dag Brattli + * Created at: Tue Dec 9 21:18:38 1997 + * Modified at: Mon Dec 14 20:09:42 1998 + * Modified by: Dag Brattli + * Sources: slip.c by Laurence Culhane, + * Fred N. van Kempen, + * + * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static hashbin_t *irtty = NULL; +static hashbin_t *dongles = NULL; + +static struct tty_ldisc irda_ldisc; + +static int irtty_hard_xmit( struct sk_buff *skb, struct device *dev); +static void irtty_wait_until_sent( struct irda_device *driver); +static int irtty_is_receiving( struct irda_device *idev); +static int irtty_net_init( struct device *dev); +static int irtty_net_open(struct device *dev); +static int irtty_net_close(struct device *dev); + +static int irtty_open( struct tty_struct *tty); +static void irtty_close( struct tty_struct *tty); +static int irtty_ioctl( struct tty_struct *, void *, int, void *); +static int irtty_receive_room( struct tty_struct *tty); +static void irtty_change_speed( struct irda_device *dev, int baud); +static void irtty_write_wakeup( struct tty_struct *tty); + +static void irtty_receive_buf( struct tty_struct *, const unsigned char *, + char *, int); +char *driver_name = "irtty"; + +__initfunc(int irtty_init(void)) +{ + int status; + + irtty = hashbin_new( HB_LOCAL); + if ( irtty == NULL) { + printk( KERN_WARNING "IrDA: Can't allocate irtty hashbin!\n"); + return -ENOMEM; + } + + dongles = hashbin_new( HB_LOCAL); + if ( dongles == NULL) { + printk( KERN_WARNING + "IrDA: Can't allocate dongles hashbin!\n"); + return -ENOMEM; + } + + /* Fill in our line protocol discipline, and register it */ + memset( &irda_ldisc, 0, sizeof( irda_ldisc)); + + irda_ldisc.magic = TTY_LDISC_MAGIC; + irda_ldisc.name = "irda"; + irda_ldisc.flags = 0; + irda_ldisc.open = irtty_open; + irda_ldisc.close = irtty_close; + irda_ldisc.read = NULL; + irda_ldisc.write = NULL; + irda_ldisc.ioctl = (int (*)(struct tty_struct *, struct file *, + unsigned int, unsigned long)) irtty_ioctl; + irda_ldisc.poll = NULL; + irda_ldisc.receive_buf = irtty_receive_buf; + irda_ldisc.receive_room = irtty_receive_room; + irda_ldisc.write_wakeup = irtty_write_wakeup; + + if (( status = tty_register_ldisc( N_IRDA, &irda_ldisc)) != 0) { + printk( KERN_ERR + "IrDA: can't register line discipline (err = %d)\n", + status); + } + + return status; +} + +/* + * Function irtty_cleanup ( ) + * + * Called when the irda module is removed. Here we remove all instances + * of the driver, and the master array. + */ +#ifdef MODULE +static void irtty_cleanup(void) +{ + int ret; + + /* + * Unregister tty line-discipline + */ + if (( ret = tty_register_ldisc( N_IRDA, NULL))) { + printk( KERN_ERR + "IrTTY: can't unregister line discipline (err = %d)\n", + ret); + } + + /* + * The TTY should care of deallocating the instances by using the + * callback to irtty_close(), therefore we do give any deallocation + * function to hashbin_destroy(). + */ + hashbin_delete( irtty, NULL); + hashbin_delete( dongles, NULL); +} +#endif /* MODULE */ + +/* + * Function irtty_open(tty) + * + * This function is called by the TTY module when the IrDA line + * discipline is called for. Because we are sure the tty line exists, + * we only have to link it to a free IrDA channel. + */ +static int irtty_open( struct tty_struct *tty) +{ + struct irtty_cb *self; + char name[16]; + + ASSERT( tty != NULL, return -EEXIST;); + + /* First make sure we're not already connected. */ + self = (struct irtty_cb *) tty->disc_data; + if ( self != NULL && self->magic == IRTTY_MAGIC) + return -EEXIST; + + /* + * Allocate new instance of the driver + */ + self = kmalloc( sizeof(struct irtty_cb), GFP_KERNEL); + if ( self == NULL) { + printk( KERN_ERR "IrDA: Can't allocate memory for " + "IrDA control block!\n"); + return -ENOMEM; + } + memset( self, 0, sizeof(struct irtty_cb)); + + self->tty = tty; + tty->disc_data = self; + + /* Give self a name */ + sprintf( name, "%s%d", tty->driver.name, + MINOR(tty->device) - tty->driver.minor_start + + tty->driver.name_base); + + /* hashbin_insert( irtty, (QUEUE*) self, 0, self->name); */ + hashbin_insert( irtty, (QUEUE*) self, (int) self, NULL); + + if (tty->driver.flush_buffer) { + tty->driver.flush_buffer(tty); + } + + if (tty->ldisc.flush_buffer) { + tty->ldisc.flush_buffer(tty); + } + + self->magic = IRTTY_MAGIC; + + /* + * Initialize driver + */ + /* self->idev.flags |= SIR_MODE | IO_PIO; */ + self->idev.rx_buff.state = OUTSIDE_FRAME; + + /* + * Initialize QoS capabilities, we fill in all the stuff that + * we support. Be careful not to place any restrictions on values + * that are not device dependent (such as link disconnect time) so + * this parameter can be set by IrLAP (or the user) instead. DB + */ + irda_init_max_qos_capabilies( &self->idev.qos); + + /* The only value we must override it the baudrate */ + self->idev.qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| + IR_115200; + irda_qos_bits_to_value( &self->idev.qos); + + /* Specify which buffer allocation policy we need */ + self->idev.rx_buff.flags = GFP_KERNEL; + self->idev.tx_buff.flags = GFP_KERNEL; + + /* Specify how much memory we want */ + self->idev.rx_buff.truesize = 4000; + self->idev.tx_buff.truesize = 4000; + + /* Initialize callbacks */ + self->idev.change_speed = irtty_change_speed; + self->idev.is_receiving = irtty_is_receiving; + /* self->idev.is_tbusy = irtty_is_tbusy; */ + self->idev.wait_until_sent = irtty_wait_until_sent; + + /* Override the network functions we need to use */ + self->idev.netdev.init = irtty_net_init; + self->idev.netdev.hard_start_xmit = irtty_hard_xmit; + self->idev.netdev.open = irtty_net_open; + self->idev.netdev.stop = irtty_net_close; + + /* Open the IrDA device */ + irda_device_open( &self->idev, name, self); + + MOD_INC_USE_COUNT; + + return 0; +} + +/* + * Function irtty_close ( tty) + * + * Close down a IrDA channel. This means flushing out any pending queues, + * and then restoring the TTY line discipline to what it was before it got + * hooked to IrDA (which usually is TTY again). + */ +static void irtty_close( struct tty_struct *tty) +{ + struct irtty_cb *self = (struct irtty_cb *) tty->disc_data; + + /* First make sure we're connected. */ + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRTTY_MAGIC, return;); + + /* We are not using any dongle anymore! */ + if ( self->dongle_q) + self->dongle_q->dongle->close( &self->idev); + + /* Remove driver */ + irda_device_close( &self->idev); + + /* Stop tty */ + tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); + tty->disc_data = 0; + + self->tty = NULL; + self->magic = 0; + + /* hashbin_remove( irtty, 0, self->name); */ + self = hashbin_remove( irtty, (int) self, NULL); + + if ( self != NULL) + kfree( self); + + MOD_DEC_USE_COUNT; + + DEBUG( 4, "IrTTY: close() -->\n"); +} + +/* + * Function irtty_change_speed ( self, baud) + * + * Change the speed of the serial port. The driver layer must check that + * all transmission has finished using the irtty_wait_until_sent() + * function. + */ +static void irtty_change_speed( struct irda_device *idev, int baud) +{ + struct termios old_termios; + struct irtty_cb *self; + int cflag; + + ASSERT( idev != NULL, return;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); + + self = (struct irtty_cb *) idev->priv; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRTTY_MAGIC, return;); + + old_termios = *(self->tty->termios); + cflag = self->tty->termios->c_cflag; + + cflag &= ~CBAUD; + + DEBUG( 4, __FUNCTION__ "(), Setting speed to %d\n", baud); + + switch( baud) { + case 1200: + cflag |= B1200; + break; + case 2400: + cflag |= B2400; + break; + case 4800: + cflag |= B4800; + break; + case 19200: + cflag |= B19200; + break; + case 38400: + cflag |= B38400; + break; + case 57600: + cflag |= B57600; + break; + case 115200: + cflag |= B115200; + break; + case 9600: + default: + cflag |= B9600; + break; + } + + self->tty->termios->c_cflag = cflag; + self->tty->driver.set_termios( self->tty, &old_termios); +} + +/* + * Function irtty_init_dongle (self, type) + * + * Initialize attached dongle. Warning, must be called with a process + * context! + */ +static void irtty_init_dongle( struct irtty_cb *self, int type) +{ + struct dongle_q *node; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRTTY_MAGIC, return;); + +#ifdef CONFIG_KMOD + /* Try to load the module needed */ + switch( type) { + case ESI_DONGLE: + DEBUG( 0, __FUNCTION__ "(), ESI dongle!\n"); + request_module( "esi"); + break; + case TEKRAM_DONGLE: + DEBUG( 0, __FUNCTION__ "(), Tekram dongle!\n"); + request_module( "tekram"); + break; + case ACTISYS_DONGLE: + DEBUG( 0, __FUNCTION__ "(), ACTiSYS dongle!\n"); + request_module( "actisys"); + break; + default: + DEBUG( 0, __FUNCTION__ "(), Unknown dongle type!\n"); + return; + break; + } +#endif /* CONFIG_KMOD */ + + node = hashbin_find( dongles, type, NULL); + if ( !node) { + DEBUG( 0, __FUNCTION__ + "(), Unable to find requested dongle\n"); + return; + } + self->dongle_q = node; + + /* Use this change speed function instead of the default */ + self->idev.change_speed = node->dongle->change_speed; + + /* + * Now initialize the dongle! + */ + node->dongle->open( &self->idev, type); + node->dongle->qos_init( &self->idev, &self->idev.qos); + + /* Reset dongle */ + node->dongle->reset( &self->idev, 0); + + /* Set to default baudrate */ + node->dongle->change_speed( &self->idev, 9600); +} + +/* + * Function irtty_ioctl (tty, file, cmd, arg) + * + * The Swiss army knife of system calls :-) + * + */ +static int irtty_ioctl( struct tty_struct *tty, void *file, int cmd, + void *arg) +{ + struct irtty_cb *self; + int err = 0; + int size = _IOC_SIZE(cmd); + + self = (struct irtty_cb *) tty->disc_data; + + ASSERT( self != NULL, return -ENODEV;); + ASSERT( self->magic == IRTTY_MAGIC, return -EBADR;); + + if ( _IOC_DIR(cmd) & _IOC_READ) + err = verify_area( VERIFY_WRITE, (void *) arg, size); + else if ( _IOC_DIR(cmd) & _IOC_WRITE) + err = verify_area( VERIFY_READ, (void *) arg, size); + if ( err) + return err; + + switch(cmd) { + case TCGETS: + case TCGETA: + return n_tty_ioctl( tty, (struct file *) file, cmd, + (unsigned long) arg); + break; + case IRTTY_IOCTDONGLE: + /* Initialize dongle */ + irtty_init_dongle( self, (int) arg); + break; + default: + return -ENOIOCTLCMD; + } + return 0; +} + +/* + * Function irtty_receive_buf( tty, cp, count) + * + * Handle the 'receiver data ready' interrupt. This function is called + * by the 'tty_io' module in the kernel when a block of IrDA data has + * been received, which can now be decapsulated and delivered for + * further processing + */ +static void irtty_receive_buf( struct tty_struct *tty, const unsigned + char *cp, char *fp, int count) +{ + struct irtty_cb *self = (struct irtty_cb *) tty->disc_data; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRTTY_MAGIC, return;); + + /* Read the characters out of the buffer */ + while (count--) { + /* + * Characters received with a parity error, etc? + */ + if (fp && *fp++) { + DEBUG( 0, "Framing or parity error!\n"); + irda_device_set_media_busy( &self->idev, TRUE); + /* sl->rx_errors++; */ + cp++; + continue; + } + /* + * Unwrap and destuff one byte + */ + async_unwrap_char( &self->idev, *cp++); + /* self->rx_over_errors++; */ + + } +} + +/* + * Function irtty_hard_xmit (skb, dev) + * + * Transmit skb + * + */ +static int irtty_hard_xmit( struct sk_buff *skb, struct device *dev) +{ + struct irtty_cb *self; + struct irda_device *idev; + int actual = 0; + + ASSERT( dev != NULL, return 0;); + ASSERT( skb != NULL, return 0;); + + if ( dev->tbusy) { + DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n"); + + return -EBUSY; + } + + idev = (struct irda_device *) dev->priv; + + ASSERT( idev != NULL, return 0;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;); + + self = (struct irtty_cb *) idev->priv; + + ASSERT( self != NULL, return 0;); + ASSERT( self->magic == IRTTY_MAGIC, return 0;); + + /* Lock transmit buffer */ + if ( irda_lock( (void *) &dev->tbusy) == FALSE) + return 0; + + /* + * Transfer skb to tx_buff while wrapping, stuffing and making CRC + */ + idev->tx_buff.len = async_wrap_skb( skb, idev->tx_buff.data, + idev->tx_buff.truesize); + + self->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); + + dev->trans_start = jiffies; + + if ( self->tty->driver.write) + actual = self->tty->driver.write( self->tty, 0, + idev->tx_buff.data, + idev->tx_buff.len); + + idev->tx_buff.offset = actual; + idev->tx_buff.head = idev->tx_buff.data + actual; +#if 0 + /* + * Did we transmit the whole frame? Commented out for now since + * I must check if this optimalization really works. DB. + */ + if (( idev->tx.count - idev->tx.ptr) <= 0) { + DEBUG( 4, "irtty_xmit_buf: finished with frame!\n"); + self->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); + irda_unlock( &self->tbusy); + } +#endif + + dev_kfree_skb( skb); + + return 0; +} + +/* + * Function irtty_receive_room (tty) + * + * Used by the TTY to find out how much data we can receive at a time + * +*/ +static int irtty_receive_room( struct tty_struct *tty) +{ + return 65536; /* We can handle an infinite amount of data. :-) */ +} + +/* + * Function irtty_write_wakeup (tty) + * + * Called by the driver when there's room for more data. If we have + * more packets to send, we send them here. + * + */ +static void irtty_write_wakeup( struct tty_struct *tty) +{ + int actual = 0, count; + struct irtty_cb *self = (struct irtty_cb *) tty->disc_data; + struct irda_device *idev; + + /* + * First make sure we're connected. + */ + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRTTY_MAGIC, return;); + + idev = &self->idev; + + /* + * Finished with frame? + */ + if ( idev->tx_buff.offset == idev->tx_buff.len) { + + /* + * Now serial buffer is almost free & we can start + * transmission of another packet + */ + DEBUG( 4, __FUNCTION__ "(), finished with frame!\n"); + + tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); + + + idev->netdev.tbusy = 0; /* Unlock */ + idev->stats.tx_packets++; + + /* Tell network layer that we want more frames */ + mark_bh( NET_BH); + + return; + } + /* + * Write data left in transmit buffer + */ + count = idev->tx_buff.len - idev->tx_buff.offset; + actual = tty->driver.write( tty, 0, idev->tx_buff.head, count); + idev->tx_buff.offset += actual; + idev->tx_buff.head += actual; + + DEBUG( 4, "actual=%d, sent %d\n", actual, count); +} + +/* + * Function irtty_is_receiving (idev) + * + * Return TRUE is we are currently receiving a frame + * + */ +static int irtty_is_receiving( struct irda_device *idev) +{ + return ( idev->rx_buff.state != OUTSIDE_FRAME); +} + +/* + * Function irtty_change_speed_ready (idev) + * + * Are we completely finished with transmitting frames so its possible + * to change the speed of the serial port. Warning this function must + * be called with a process context! + */ +static void irtty_wait_until_sent( struct irda_device *idev) +{ + struct irtty_cb *self = (struct irtty_cb *) idev->priv; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRTTY_MAGIC, return;); + + DEBUG( 4, "Chars in buffer %d\n", + self->tty->driver.chars_in_buffer( self->tty)); + + tty_wait_until_sent( self->tty, 0); +} + +int irtty_register_dongle( struct dongle *dongle) +{ + struct dongle_q *new; + + /* Check if this compressor has been registred before */ + if ( hashbin_find ( dongles, dongle->type, NULL)) { + DEBUG( 0, __FUNCTION__ "(), Dongle already registered\n"); + return 0; + } + + /* Make new IrDA dongle */ + new = (struct dongle_q *) kmalloc (sizeof (struct dongle_q), + GFP_KERNEL); + if (new == NULL) { + return 1; + + } + memset( new, 0, sizeof( struct dongle_q)); + new->dongle = dongle; + + /* Insert IrDA compressor into hashbin */ + hashbin_insert( dongles, (QUEUE *) new, dongle->type, NULL); + + return 0; +} + +void irtty_unregister_dongle( struct dongle *dongle) +{ + struct dongle_q *node; + + node = hashbin_remove( dongles, dongle->type, NULL); + if ( !node) { + DEBUG( 0, __FUNCTION__ "(), dongle not found!\n"); + return; + } + kfree( node); +} + +static int irtty_net_init( struct device *dev) +{ + /* Set up to be a normal IrDA network device driver */ + irda_device_setup( dev); + + /* Insert overrides below this line! */ + + return 0; +} + + +static int irtty_net_open( struct device *dev) +{ + ASSERT( dev != NULL, return -1;); + + /* Ready to play! */ + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + MOD_INC_USE_COUNT; + + return 0; +} + +static int irtty_net_close(struct device *dev) +{ + ASSERT( dev != NULL, return -1;); + + /* Stop device */ + dev->tbusy = 1; + dev->start = 0; + + MOD_DEC_USE_COUNT; + + return 0; +} + +#ifdef MODULE + +/* + * Function init_module (void) + * + * Initialize IrTTY module + * + */ +int init_module(void) +{ + irtty_init(); + return(0); +} + +/* + * Function cleanup_module (void) + * + * Cleanup IrTTY module + * + */ +void cleanup_module(void) +{ + irtty_cleanup(); +} + +#endif /* MODULE */ + + + + + + + diff --git a/drivers/net/irda/pc87108.c b/drivers/net/irda/pc87108.c new file mode 100644 index 000000000000..5a11460be74d --- /dev/null +++ b/drivers/net/irda/pc87108.c @@ -0,0 +1,1502 @@ +/********************************************************************* + * + * Filename: pc87108.c + * Version: 0.8 + * Description: FIR/MIR driver for the NS PC87108 chip + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sat Nov 7 21:43:15 1998 + * Modified at: Mon Dec 14 11:40:24 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli + * Copyright (c) 1998 Lichen Wang, + * Copyright (c) 1998 Actisys Corp., www.actisys.com + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + * Notice that all functions that needs to access the chip in _any_ + * way, must save BSR register on entry, and restore it on exit. + * It is _very_ important to follow this policy! + * + * __u8 bank; + * + * bank = inb( iobase+BSR); + * + * do_your_stuff_here(); + * + * outb( bank, iobase+BSR); + * + * If you find bugs in this file, its very likely that the same bug + * will also be in w83977af_ir.c since the implementations is quite + * similar. + * + ********************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#define BROKEN_DONGLE_ID + +static char *driver_name = "pc87108"; + +#define CHIP_IO_EXTENT 8 + +static unsigned int io[] = { 0x2f8, ~0, ~0, ~0 }; +static unsigned int io2[] = { 0x150, 0, 0, 0}; +static unsigned int irq[] = { 3, 0, 0, 0 }; +static unsigned int dma[] = { 0, 0, 0, 0 }; + +static struct pc87108 *dev_self[] = { NULL, NULL, NULL, NULL}; + +static char *dongle_types[] = { + "Differential serial interface", + "Differential serial interface", + "Reserved", + "Reserved", + "Sharp RY5HD01", + "Reserved", + "Single-ended serial interface", + "Consumer-IR only", + "HP HSDL-2300, HP HSDL-3600/HSDL-3610", + "IBM31T1100 or Temic TFDS6000/TFDS6500", + "Reserved", + "Reserved", + "HP HSDL-1100/HSDL-2100", + "HP HSDL-1100/HSDL-2100" + "Supports SIR Mode only", + "No dongle connected", +}; + +/* Some prototypes */ +static int pc87108_open( int i, unsigned int iobase, unsigned int board_addr, + unsigned int irq, unsigned int dma); +static int pc87108_close( struct irda_device *idev); +static int pc87108_probe( int iobase, int board_addr, int irq, int dma); +static void pc87108_pio_receive( struct irda_device *idev); +static int pc87108_dma_receive( struct irda_device *idev); +static int pc87108_dma_receive_complete(struct irda_device *idev, int iobase); +static int pc87108_hard_xmit( struct sk_buff *skb, struct device *dev); +static int pc87108_pio_write( int iobase, __u8 *buf, int len, int fifo_size); +static void pc87108_dma_write( struct irda_device *idev, int iobase); +static void pc87108_change_speed( struct irda_device *idev, int baud); +static void pc87108_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static void pc87108_wait_until_sent( struct irda_device *idev); +static int pc87108_is_receiving( struct irda_device *idev); +static int pc87108_read_dongle_id ( int iobase); +static void pc87108_init_dongle_interface ( int iobase, int dongle_id); + +static int pc87108_net_init( struct device *dev); +static int pc87108_net_open( struct device *dev); +static int pc87108_net_close( struct device *dev); + +/* + * Function pc87108_init () + * + * Initialize chip. Just try to find out how many chips we are dealing with + * and where they are + */ +__initfunc(int pc87108_init(void)) +{ + int i; + + DEBUG( 0, __FUNCTION__ "()\n"); + + + for ( i=0; (io[i] < 2000) && (i < 4); i++) { + int ioaddr = io[i]; + if (check_region(ioaddr, CHIP_IO_EXTENT)) + continue; + if (pc87108_open( i, io[i], io2[i], irq[i], dma[i]) == 0) + return 0; + } + return -ENODEV; +} + +/* + * Function pc87108_cleanup () + * + * Close all configured chips + * + */ +#ifdef MODULE +static void pc87108_cleanup(void) +{ + int i; + + DEBUG( 4, __FUNCTION__ "()\n"); + + for ( i=0; i < 4; i++) { + if ( dev_self[i]) + pc87108_close( &(dev_self[i]->idev)); + } +} +#endif /* MODULE */ + +/* + * Function pc87108_open (iobase, irq) + * + * Open driver instance + * + */ +static int pc87108_open( int i, unsigned int iobase, unsigned int board_addr, + unsigned int irq, unsigned int dma) +{ + struct pc87108 *self; + struct irda_device *idev; + int ret; + int dongle_id; + + DEBUG( 0, __FUNCTION__ "()\n"); + + if (( dongle_id = pc87108_probe( iobase, board_addr, irq, dma)) == -1) + return -1; + + /* + * Allocate new instance of the driver + */ + self = kmalloc( sizeof(struct pc87108), GFP_KERNEL); + if ( self == NULL) { + printk( KERN_ERR "IrDA: Can't allocate memory for " + "IrDA control block!\n"); + return -ENOMEM; + } + memset( self, 0, sizeof(struct pc87108)); + + /* Need to store self somewhere */ + dev_self[i] = self; + + idev = &self->idev; + + /* Initialize IO */ + idev->io.iobase = iobase; + idev->io.irq = irq; + idev->io.io_ext = CHIP_IO_EXTENT; + idev->io.dma = dma; + idev->io.fifo_size = 32; + + /* Lock the port that we need */ + ret = check_region( idev->io.iobase, idev->io.io_ext); + if ( ret < 0) { + DEBUG( 0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", + idev->io.iobase); + /* pc87108_cleanup( self->idev); */ + return -ENODEV; + } + request_region( idev->io.iobase, idev->io.io_ext, idev->name); + + /* Initialize QoS for this device */ + irda_init_max_qos_capabilies( &idev->qos); + + /* The only value we must override it the baudrate */ + idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| + IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8); + + idev->qos.min_turn_time.bits = 0x07; + irda_qos_bits_to_value( &idev->qos); + + /* Specify which buffer allocation policy we need */ + idev->rx_buff.flags = GFP_KERNEL | GFP_DMA; + idev->tx_buff.flags = GFP_KERNEL | GFP_DMA; + + /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */ + idev->rx_buff.truesize = 14384; + idev->tx_buff.truesize = 4000; + + /* Initialize callbacks */ + idev->hard_xmit = pc87108_hard_xmit; + idev->change_speed = pc87108_change_speed; + idev->wait_until_sent = pc87108_wait_until_sent; + idev->is_receiving = pc87108_is_receiving; + + /* Override the network functions we need to use */ + idev->netdev.init = pc87108_net_init; + idev->netdev.hard_start_xmit = pc87108_hard_xmit; + idev->netdev.open = pc87108_net_open; + idev->netdev.stop = pc87108_net_close; + + idev->io.dongle_id = dongle_id; + pc87108_init_dongle_interface( iobase, dongle_id); + + /* Open the IrDA device */ + irda_device_open( idev, driver_name, self); + + return 0; +} + +/* + * Function pc87108_close (idev) + * + * Close driver instance + * + */ +static int pc87108_close( struct irda_device *idev) +{ + int iobase; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( idev != NULL, return -1;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;); + + iobase = idev->io.iobase; + + /* Release the PORT that this driver is using */ + DEBUG( 4, __FUNCTION__ "(), Releasing Region %03x\n", + idev->io.iobase); + release_region( idev->io.iobase, idev->io.io_ext); + + irda_device_close( idev); + + return 0; +} + +/* + * Function pc87108_probe (iobase, board_addr, irq, dma) + * + * Returns non-negative on success. + * + */ +static int pc87108_probe( int iobase, int board_addr, int irq, int dma) +{ + int version; + __u8 temp=0; + int dongle_id; + + DEBUG( 4, __FUNCTION__ "()\n"); + + /* Base Address and Interrupt Control Register BAIC */ + outb(0, board_addr); + switch ( iobase) { + case 0x3E8: outb( 0x14, board_addr+1); break; + case 0x2E8: outb( 0x15, board_addr+1); break; + case 0x3F8: outb( 0x16, board_addr+1); break; + case 0x2F8: outb( 0x17, board_addr+1); break; + default: DEBUG(0, __FUNCTION__ "(), invalid base_address"); + } + + /* Control Signal Routing Register CSRT */ + switch (irq) { + case 3: temp = 0x01; break; + case 4: temp = 0x02; break; + case 5: temp = 0x03; break; + case 7: temp = 0x04; break; + case 9: temp = 0x05; break; + case 11: temp = 0x06; break; + case 15: temp = 0x07; break; + default: DEBUG( 0, __FUNCTION__ "(), invalid irq"); + } + outb( 1, board_addr); + + switch (dma) { + case 0: outb( 0x08+temp, board_addr+1); break; + case 1: outb( 0x10+temp, board_addr+1); break; + case 3: outb( 0x18+temp, board_addr+1); break; + default: DEBUG( 0, __FUNCTION__ "(), invalid dma"); + } + + /* Mode Control Register MCTL */ + outb( 2, board_addr); + outb( 0x03, board_addr+1); + + /* read the Module ID */ + switch_bank( iobase, BANK3); + version = inb( iobase+MID); + + /* should be 0x2? */ + if (0x20 != (version & 0xf0)) + { + DEBUG( 0, __FUNCTION__ "(), Wrong chip version"); + return -1; + } + + /* Switch to advanced mode */ + switch_bank( iobase, BANK2); + outb( ECR1_EXT_SL, iobase+ECR1); + switch_bank( iobase, BANK0); + + dongle_id = pc87108_read_dongle_id( iobase); + DEBUG( 0, __FUNCTION__ "(), Found dongle: %s\n", + dongle_types[ dongle_id]); + + /* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */ + switch_bank( iobase, BANK0); + outb( FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR); + + /* Set FIFO size to 32 */ + switch_bank( iobase, BANK2); + outb( EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2); + + /* IRCR2: FEND_MD is set */ + switch_bank( iobase, BANK5); + outb( 0x2a, iobase+4); + + /* Make sure that some defaults are OK */ + switch_bank( iobase, BANK6); + outb( 0x20, iobase+0); /* Set 32 bits FIR CRC */ + outb( 0x0a, iobase+1); /* Set MIR pulse width */ + outb( 0x0d, iobase+2); /* Set SIR pulse width */ + outb( 0x2a, iobase+4); /* Set beginning frag, and preamble length */ + + /* Receiver frame length */ + switch_bank( iobase, BANK4); + outb( 4000 & 0xff, iobase+6); + outb(( 4000 >> 8) & 0x1f, iobase+7); + + /* Transmitter frame length */ + outb( 4000 & 0xff, iobase+4); + outb(( 4000 >> 8) & 0x1f, iobase+5); + + DEBUG( 0, "PC87108 driver loaded. Version: 0x%02x\n", version); + + /* Enable receive interrupts */ + switch_bank( iobase, BANK0); + outb( IER_RXHDL_IE, iobase+IER); + + return dongle_id; +} + +/* + * Function pc87108_read_dongle_id (void) + * + * Try to read dongle indentification. This procedure needs to be executed + * once after power-on/reset. It also needs to be used whenever you suspect + * that the user may have plugged/unplugged the IrDA Dongle. + * + */ +static int pc87108_read_dongle_id ( int iobase) +{ + int dongle_id; + __u8 bank; + + DEBUG( 4, __FUNCTION__ "()\n"); + + bank = inb( iobase+BSR); + + /* Select Bank 7 */ + switch_bank( iobase, BANK7); + + /* IRCFG4: IRSL0_DS and IRSL21_DS are cleared */ + outb( 0x00, iobase+7); + + /* ID0, 1, and 2 are pulled up/down very slowly */ + udelay(50); + + /* IRCFG1: read the ID bits */ + dongle_id = inb( iobase+4) & 0x0f; + +#ifdef BROKEN_DONGLE_ID + if ( dongle_id == 0x0a) + dongle_id = 0x09; +#endif + + /* Go back to bank 0 before returning */ + switch_bank( iobase, BANK0); + + DEBUG( 0, __FUNCTION__ "(), Dongle = %#x\n", dongle_id); + + outb( bank, iobase+BSR); + + return dongle_id; +} + +/* + * Function pc87108_init_dongle_interface (iobase, dongle_id) + * + * This function initializes the dongle for the transceiver that is + * used. This procedure needs to be executed once after + * power-on/reset. It also needs to be used whenever you suspect that + * the dongle is changed. + */ +static void pc87108_init_dongle_interface ( int iobase, int dongle_id) +{ + int bank; + + /* Save current bank */ + bank = inb( iobase+BSR); + + /* Select Bank 7 */ + switch_bank( iobase, BANK7); + + /* IRCFG4: set according to dongle_id */ + switch (dongle_id) { + case 0x00: /* same as */ + case 0x01: /* Differential serial interface */ + DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n", + dongle_types[dongle_id]); + break; + case 0x02: /* same as */ + case 0x03: /* Reserved */ + DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n", + dongle_types[dongle_id]); + break; + case 0x04: /* Sharp RY5HD01 */ + DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n", + dongle_types[dongle_id]); + break; + case 0x05: /* Reserved */ + DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet", + dongle_types[dongle_id]); + break; + case 0x06: /* Single-ended serial interface */ + DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n", + dongle_types[dongle_id]); + break; + case 0x07: /* Consumer-IR only */ + DEBUG( 0, __FUNCTION__ "(), %s is not for IrDA mode\n", + dongle_types[dongle_id]); + break; + case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */ + DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n", + dongle_types[dongle_id]); + break; + case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */ + outb_p( 0x28, iobase+7); /* Set irsl[0-2] as output */ + break; + case 0x0A: /* same as */ + case 0x0B: /* Reserved */ + DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n", + dongle_types[dongle_id]); + break; + case 0x0C: /* same as */ + case 0x0D: /* HP HSDL-1100/HSDL-2100 */ + /* + * Set irsl0 as input, irsl[1-2] as output, and separate + * inputs are used for SIR and MIR/FIR + */ + outb( 0x48, iobase+7); + break; + case 0x0E: /* Supports SIR Mode only */ + outb( 0x28, iobase+7); /* Set irsl[0-2] as output */ + break; + case 0x0F: /* No dongle connected */ + DEBUG( 0, __FUNCTION__ "(), %s\n", + dongle_types[dongle_id]); + DEBUG( 0, "***\n"); + + switch_bank( iobase, BANK0); + outb( 0x62, iobase+MCR); + break; + default: + DEBUG( 0, __FUNCTION__ "(), invalid dongle_id %#x", dongle_id); + } + + /* IRCFG1: IRSL1 and 2 are set to IrDA mode */ + outb( 0x00, iobase+4); + + /* Restore bank register */ + outb( bank, iobase+BSR); + +} /* set_up_dongle_interface */ + +/* + * Function pc87108_change_dongle_speed (iobase, speed, dongle_id) + * + * Change speed of the attach dongle + * + */ +static void pc87108_change_dongle_speed( int iobase, int speed, int dongle_id) +{ + unsigned long flags; + __u8 bank; + + DEBUG( 4, __FUNCTION__ "()\n"); + + /* Save current bank */ + bank = inb( iobase+BSR); + + /* Select Bank 7 */ + switch_bank( iobase, BANK7); + + /* IRCFG1: set according to dongle_id */ + switch (dongle_id) { + case 0x00: /* same as */ + case 0x01: /* Differential serial interface */ + DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n", + dongle_types[dongle_id]); + break; + case 0x02: /* same as */ + case 0x03: /* Reserved */ + DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n", + dongle_types[dongle_id]); + break; + case 0x04: /* Sharp RY5HD01 */ + DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n", + dongle_types[dongle_id]); + case 0x05: /* Reserved */ + DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n", + dongle_types[dongle_id]); + break; + case 0x06: /* Single-ended serial interface */ + DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n", + dongle_types[dongle_id]); + break; + case 0x07: /* Consumer-IR only */ + DEBUG( 0, __FUNCTION__ "(), %s is not for IrDA mode\n", + dongle_types[dongle_id]); + break; + case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */ + DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n", + dongle_types[dongle_id]); + case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */ + switch_bank( iobase, BANK7); + outb_p( 0x01, iobase+4); + + if ( speed == 4000000) { + save_flags(flags); + cli(); + outb( 0x81, iobase+4); + outb( 0x80, iobase+4); + restore_flags(flags); + } + else + outb_p( 0x00, iobase+4); + break; + case 0x0A: /* same as */ + case 0x0B: /* Reserved */ + DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n", + dongle_types[dongle_id]); + break; + case 0x0C: /* same as */ + case 0x0D: /* HP HSDL-1100/HSDL-2100 */ + break; + case 0x0E: /* Supports SIR Mode only */ + break; + case 0x0F: /* No dongle connected */ + DEBUG( 0, __FUNCTION__ "(), %s is not for IrDA mode\n", + dongle_types[dongle_id]); + + switch_bank( iobase, BANK0); + outb( 0x62, iobase+MCR); + break; + default: + DEBUG( 0, __FUNCTION__ "(), invalid data_rate\n"); + } + /* Restore bank register */ + outb( bank, iobase+BSR); +} + +/* + * Function pc87108_change_speed (idev, baud) + * + * Change the speed of the device + * + */ +static void pc87108_change_speed( struct irda_device *idev, int speed) +{ + __u8 mcr = MCR_SIR; + __u8 bank; + int iobase; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( idev != NULL, return;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); + + iobase = idev->io.iobase; + + /* Update accounting for new speed */ + idev->io.baudrate = speed; + + /* Save current bank */ + bank = inb( iobase+BSR); + + /* Disable interrupts */ + switch_bank( iobase, BANK0); + outb( 0, iobase+IER); + + /* Select Bank 2 */ + switch_bank( iobase, BANK2); + + outb( 0x00, iobase+BGDH); + switch ( speed) { + case 9600: outb( 0x0c, iobase+BGDL); break; + case 19200: outb( 0x06, iobase+BGDL); break; + case 37600: outb( 0x03, iobase+BGDL); break; + case 57600: outb( 0x02, iobase+BGDL); break; + case 115200: outb( 0x01, iobase+BGDL); break; + case 576000: + switch_bank( iobase, BANK5); + + /* IRCR2: MDRS is set */ + outb( inb( iobase+4) | 0x04, iobase+4); + + mcr = MCR_MIR; + DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n"); + break; + case 1152000: + mcr = MCR_MIR; + DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n"); + break; + case 4000000: + mcr = MCR_FIR; + DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n"); + break; + default: + mcr = MCR_FIR; + DEBUG( 0, __FUNCTION__ "(), unknown baud rate of %d\n", speed); + break; + } + + /* Set appropriate speed mode */ + switch_bank(iobase, BANK0); + outb( mcr|MCR_TX_DFR, iobase+MCR); + + /* Give some hits to the transceiver */ + pc87108_change_dongle_speed( iobase, speed, idev->io.dongle_id); + + /* Set FIFO threshold to TX17, RX16 */ + switch_bank( iobase, BANK0); + outb( FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR); + /* outb( 0xa7, iobase+FCR); */ + + /* Set FIFO size to 32 */ + switch_bank( iobase, BANK2); + outb( EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2); + + idev->netdev.tbusy = 0; + + /* Enable some interrupts so we can receive frames */ + switch_bank( iobase, BANK0); + if ( speed > 115200) { + outb( IER_SFIF_IE, iobase+IER); + pc87108_dma_receive( idev); + } else + outb( IER_RXHDL_IE, iobase+IER); + + /* Restore BSR */ + outb( bank, iobase+BSR); +} + +/* + * Function pc87108_hard_xmit (skb, dev) + * + * Transmit the frame! + * + */ +static int pc87108_hard_xmit( struct sk_buff *skb, struct device *dev) +{ + struct irda_device *idev; + int iobase; + __u8 bank; + int mtt; + + idev = (struct irda_device *) dev->priv; + + ASSERT( idev != NULL, return 0;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;); + + iobase = idev->io.iobase; + + DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len); + + if ( dev->tbusy) { + DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n"); + + return -EBUSY; + } + + /* Lock transmit buffer */ + if ( irda_lock( (void *) &dev->tbusy) == FALSE) + return -EBUSY; + + /* Save current bank */ + bank = inb( iobase+BSR); + + /* Decide if we should use PIO or DMA transfer */ + if ( idev->io.baudrate > 115200) { + memcpy( idev->tx_buff.data, skb->data, skb->len); + idev->tx_buff.len = skb->len; + idev->tx_buff.head = idev->tx_buff.data; + idev->tx_buff.offset = 0; + + mtt = irda_get_mtt( skb); + if ( mtt > 50) { + /* Adjust for timer resolution */ + mtt = mtt / 125 + 1; + + /* Setup timer */ + switch_bank( iobase, BANK4); + outb( mtt & 0xff, iobase+TMRL); + outb(( mtt >> 8) & 0x0f, iobase+TMRH); + + /* Start timer */ + outb( IRCR1_TMR_EN, iobase+IRCR1); + idev->io.direction = IO_XMIT; + + /* Enable timer interrupt */ + switch_bank( iobase, BANK0); + outb( IER_TMR_IE, iobase+IER); + } else { + /* Use udelay for delays less than 50 us. */ + if (mtt) + udelay( mtt); + + /* Enable DMA interrupt */ + switch_bank( iobase, BANK0); + outb( IER_DMA_IE, iobase+IER); + pc87108_dma_write( idev, iobase); + } + } else { + idev->tx_buff.len = async_wrap_skb( skb, idev->tx_buff.data, + idev->tx_buff.truesize); + + idev->tx_buff.offset = 0; + idev->tx_buff.head = idev->tx_buff.data; + + /* Add interrupt on tx low level (will fire immediately) */ + switch_bank( iobase, BANK0); + outb( IER_TXLDL_IE, iobase+IER); + } + dev_kfree_skb( skb); + + /* Restore bank register */ + outb( bank, iobase+BSR); + + return 0; +} + +/* + * Function pc87108_dma_xmit (idev, iobase) + * + * Transmit data using DMA + * + */ +static void pc87108_dma_write( struct irda_device *idev, int iobase) +{ + int bsr; + + DEBUG( 4, __FUNCTION__ "()\n"); + + /* Save current bank */ + bsr = inb( iobase+BSR); + + /* Disable DMA */ + switch_bank(iobase, BANK0); + outb( inb( iobase+MCR) & ~MCR_DMA_EN, iobase+MCR); + + setup_dma( idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, + DMA_MODE_WRITE); + + /* idev->media_busy = TRUE; */ + idev->io.direction = IO_XMIT; + + /* Choose transmit DMA channel */ + switch_bank(iobase, BANK2); + outb( inb( iobase+ECR1) | ECR1_DMASWP|ECR1_DMANF|ECR1_EXT_SL, + iobase+ECR1); + + /* Enable DMA */ + switch_bank( iobase, BANK0); + outb( inb( iobase+MCR)|MCR_DMA_EN, iobase+MCR); + + /* Restore bank register */ + outb( bsr, iobase+BSR); +} + +/* + * Function pc87108_pio_xmit (idev, iobase) + * + * Transmit data using PIO. Returns the number of bytes that actually + * got transfered + * + */ +static int pc87108_pio_write( int iobase, __u8 *buf, int len, int fifo_size) +{ + int actual = 0; + __u8 bank; + + DEBUG( 4, __FUNCTION__ "()\n"); + + /* Save current bank */ + bank = inb( iobase+BSR); + + switch_bank( iobase, BANK0); + if (!(inb_p( iobase+LSR) & LSR_TXEMP)) { + DEBUG( 4, __FUNCTION__ "(), warning, FIFO not empty yet!\n"); + + fifo_size -= 17; + DEBUG( 4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size); + } + + /* Fill FIFO with current frame */ + while (( fifo_size-- > 0) && (actual < len)) { + /* Transmit next byte */ + outb( buf[actual++], iobase+TXD); + } + + DEBUG( 4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", + fifo_size, actual, len); + + /* Restore bank */ + outb( bank, iobase+BSR); + + return actual; +} + +/* + * Function pc87108_dma_xmit_complete (idev) + * + * The transfer of a frame in finished. This function will only be called + * by the interrupt handler + * + */ +static void pc87108_dma_xmit_complete( struct irda_device *idev) +{ + int iobase; + __u8 bank; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( idev != NULL, return;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); + + iobase = idev->io.iobase; + + /* Save current bank */ + bank = inb( iobase+BSR); + + /* Disable DMA */ + switch_bank( iobase, BANK0); + outb( inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR); + + /* Check for underrrun! */ + if ( inb( iobase+ASCR) & ASCR_TXUR) { + idev->stats.tx_errors++; + idev->stats.tx_fifo_errors++; + + /* Clear bit, by writing 1 to it */ + outb( ASCR_TXUR, iobase+ASCR); + } else { + idev->stats.tx_packets++; + idev->stats.tx_bytes += idev->tx_buff.len; + } + + /* Unlock tx_buff and request another frame */ + idev->netdev.tbusy = 0; /* Unlock */ + idev->media_busy = FALSE; + + /* Tell the network layer, that we can accept more frames */ + mark_bh( NET_BH); + + /* Restore bank */ + outb( bank, iobase+BSR); +} + +/* + * Function pc87108_dma_receive (idev) + * + * Get ready for receiving a frame. The device will initiate a DMA + * if it starts to receive a frame. + * + */ +static int pc87108_dma_receive( struct irda_device *idev) +{ + struct pc87108 *self; + int iobase; + __u8 bsr; + + ASSERT( idev != NULL, return -1;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;); + + DEBUG( 4, __FUNCTION__ "\n"); + + self = idev->priv; + iobase= idev->io.iobase; + + /* Save current bank */ + bsr = inb( iobase+BSR); + + /* Disable DMA */ + switch_bank( iobase, BANK0); + outb( inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR); + + setup_dma( idev->io.dma, idev->rx_buff.data, idev->rx_buff.truesize, + DMA_MODE_READ); + + /* driver->media_busy = FALSE; */ + idev->io.direction = IO_RECV; + idev->rx_buff.head = idev->rx_buff.data; + idev->rx_buff.offset = 0; + + /* Reset Rx FIFO. This will also flush the ST_FIFO */ + outb( FCR_RXTH|FCR_TXTH|FCR_RXSR|FCR_FIFO_EN, iobase+FCR); + self->st_fifo.len = self->st_fifo.tail = self->st_fifo.head = 0; + + /* Choose DMA Rx, DMA Fairness, and Advanced mode */ + switch_bank(iobase, BANK2); + outb(( inb( iobase+ECR1) & ~ECR1_DMASWP)|ECR1_DMANF|ECR1_EXT_SL, + iobase+ECR1); + + /* enable DMA */ + switch_bank(iobase, BANK0); + outb( inb( iobase+MCR)|MCR_DMA_EN, iobase+MCR); + + /* Restore bank register */ + outb( bsr, iobase+BSR); + + DEBUG( 4, __FUNCTION__ "(), done!\n"); + + return 0; +} + +/* + * Function pc87108_dma_receive_complete (idev) + * + * Finished with receiving frames + * + * + */ +static int pc87108_dma_receive_complete( struct irda_device *idev, int iobase) +{ + struct sk_buff *skb; + struct pc87108 *self; + struct st_fifo *st_fifo; + int len; + __u8 bank; + __u8 status; + + self = idev->priv; + st_fifo = &self->st_fifo; + + /* Save current bank */ + bank = inb( iobase+BSR); + + iobase = idev->io.iobase; + + /* Read status FIFO */ + switch_bank(iobase, BANK5); + while (( status = inb( iobase+FRM_ST)) & FRM_ST_VLD) { + st_fifo->entries[ st_fifo->tail].status = status; + + st_fifo->entries[ st_fifo->tail].len = inb(iobase+RFLFL); + st_fifo->entries[ st_fifo->tail].len |= inb(iobase+RFLFH) << 8; + + st_fifo->tail++; + st_fifo->len++; + } + + /* Try to process all entries in status FIFO */ + switch_bank( iobase, BANK0); + while ( st_fifo->len) { + + /* Get first entry */ + status = st_fifo->entries[ st_fifo->head].status; + len = st_fifo->entries[ st_fifo->head].len; + st_fifo->head++; + st_fifo->len--; + + /* Check for errors */ + if ( status & FRM_ST_ERR_MSK) { + if ( status & FRM_ST_LOST_FR) { + /* Add number of lost frames to stats */ + idev->stats.rx_errors += len; + } else { + /* Skip frame */ + idev->stats.rx_errors++; + + idev->rx_buff.offset += len; + idev->rx_buff.head += len; + + if ( status & FRM_ST_MAX_LEN) + idev->stats.rx_length_errors++; + + if ( status & FRM_ST_PHY_ERR) + idev->stats.rx_frame_errors++; + + if ( status & FRM_ST_BAD_CRC) + idev->stats.rx_crc_errors++; + } + /* The errors below can be reported in both cases */ + if ( status & FRM_ST_OVR1) + idev->stats.rx_fifo_errors++; + + if ( status & FRM_ST_OVR2) + idev->stats.rx_fifo_errors++; + + } else { + /* Check if we have transfered all data to memory */ + if ( inb( iobase+LSR) & LSR_RXDA) { + /* Put this entry back in fifo */ + st_fifo->head--; + st_fifo->len++; + st_fifo->entries[ st_fifo->head].status = status; + st_fifo->entries[ st_fifo->head].len = len; + + /* Restore bank register */ + outb( bank, iobase+BSR); + + return FALSE; /* I'll be back! */ + } + + /* Should be OK then */ + skb = dev_alloc_skb( len+1); + if (skb == NULL) { + printk( KERN_INFO __FUNCTION__ + "(), memory squeeze, dropping frame.\n"); + /* Restore bank register */ + outb( bank, iobase+BSR); + + return FALSE; + } + + /* Make sure IP header gets aligned */ + skb_reserve( skb, 1); + + /* Copy frame without CRC */ + if ( idev->io.baudrate < 4000000) { + skb_put( skb, len-2); + memcpy( skb->data, idev->rx_buff.head, len-2); + } else { + skb_put( skb, len-4); + memcpy( skb->data, idev->rx_buff.head, len-4); + } + + /* Move to next frame */ + idev->rx_buff.offset += len; + idev->rx_buff.head += len; + idev->stats.rx_packets++; + + skb->dev = &idev->netdev; + skb->mac.raw = skb->data; + skb->protocol = htons(ETH_P_IRDA); + netif_rx( skb); + } + } + /* Restore bank register */ + outb( bank, iobase+BSR); + + return TRUE; +} + +/* + * Function pc87108_pio_receive (idev) + * + * Receive all data in receiver FIFO + * + */ +static void pc87108_pio_receive( struct irda_device *idev) +{ + __u8 byte = 0x00; + int iobase; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( idev != NULL, return;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); + + iobase = idev->io.iobase; + + if ( idev->rx_buff.len == 0) { + idev->rx_buff.head = idev->rx_buff.data; + } + + /* Receive all characters in Rx FIFO */ + do { + byte = inb( iobase+RXD); + async_unwrap_char( idev, byte); + + } while ( inb( iobase+LSR) & LSR_RXDA); /* Data available */ +} + +/* + * Function pc87108_sir_interrupt (idev, eir) + * + * Handle SIR interrupt + * + */ +static __u8 pc87108_sir_interrupt( struct irda_device *idev, int eir) +{ + int len; + int actual; + __u8 new_ier = 0; + + /* Transmit FIFO low on data */ + if ( eir & EIR_TXLDL_EV) { + /* Write data left in transmit buffer */ + len = idev->tx_buff.len - idev->tx_buff.offset; + + ASSERT( len > 0, return 0;); + actual = pc87108_pio_write( idev->io.iobase, + idev->tx_buff.head, + len, idev->io.fifo_size); + idev->tx_buff.offset += actual; + idev->tx_buff.head += actual; + + idev->io.direction = IO_XMIT; + ASSERT( actual <= len, return 0;); + + /* Check if finished */ + if ( actual == len) { + DEBUG( 4, __FUNCTION__ "(), finished with frame!\n"); + idev->netdev.tbusy = 0; /* Unlock */ + idev->stats.tx_packets++; + + mark_bh(NET_BH); + + new_ier |= IER_TXEMP_IE; + } else + new_ier |= IER_TXLDL_IE; + } + /* Check if transmission has completed */ + if ( eir & EIR_TXEMP_EV) { + + /* Turn around and get ready to receive some data */ + idev->io.direction = IO_RECV; + new_ier |= IER_RXHDL_IE; + } + + /* Rx FIFO threshold or timeout */ + if ( eir & EIR_RXHDL_EV) { + pc87108_pio_receive( idev); + + /* Keep receiving */ + new_ier |= IER_RXHDL_IE; + } + return new_ier; +} + +/* + * Function pc87108_fir_interrupt (idev, eir) + * + * Handle MIR/FIR interrupt + * + */ +static __u8 pc87108_fir_interrupt( struct irda_device *idev, int iobase, + int eir) +{ + __u8 new_ier = 0; + __u8 bank; + + bank = inb( iobase+BSR); + + /* Status event, or end of frame detected in FIFO */ + if ( eir & (EIR_SFIF_EV|EIR_LS_EV)) { + if ( pc87108_dma_receive_complete( idev, iobase)) { + + /* Wait for next status FIFO interrupt */ + new_ier |= IER_SFIF_IE; + } else { + /* DMA not finished yet */ + + /* Set timer value, resolution 125 us */ + switch_bank( iobase, BANK4); + outb( 0x0f, iobase+TMRL); /* 125 us */ + outb( 0x00, iobase+TMRH); + + /* Start timer */ + outb( IRCR1_TMR_EN, iobase+IRCR1); + + new_ier |= IER_TMR_IE; + } + } + /* Timer finished */ + if ( eir & EIR_TMR_EV) { + /* Disable timer */ + switch_bank( iobase, BANK4); + outb( 0, iobase+IRCR1); + + /* Clear timer event */ + switch_bank(iobase, BANK0); + outb( ASCR_CTE, iobase+ASCR); + + /* Check if this is a TX timer interrupt */ + if ( idev->io.direction == IO_XMIT) { + pc87108_dma_write( idev, iobase); + + /* Interrupt on DMA */ + new_ier |= IER_DMA_IE; + } else { + /* Check if DMA has now finished */ + pc87108_dma_receive_complete( idev, iobase); + + new_ier |= IER_SFIF_IE; + } + } + /* Finished with transmission */ + if ( eir & EIR_DMA_EV) { + pc87108_dma_xmit_complete( idev); + + /* Check if there are more frames to be transmitted */ + if ( irda_device_txqueue_empty( idev)) { + /* Prepare for receive */ + pc87108_dma_receive( idev); + + new_ier = IER_LS_IE|IER_SFIF_IE; + } + } + outb( bank, iobase+BSR); + + return new_ier; +} + +/* + * Function pc87108_interrupt (irq, dev_id, regs) + * + * An interrupt from the chip has arrived. Time to do some work + * + */ +static void pc87108_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + __u8 bsr, eir, ier; + int iobase; + + struct irda_device *idev = (struct irda_device *) dev_id; + + if (idev == NULL) { + printk( KERN_WARNING "%s: irq %d for unknown device.\n", + driver_name, irq); + return; + } + + idev->netdev.interrupt = 1; + + iobase = idev->io.iobase; + + /* Save current bank */ + bsr = inb( iobase+BSR); + + switch_bank( iobase, BANK0); + ier = inb( iobase+IER); + eir = inb( iobase+EIR) & ier; /* Mask out the interesting ones */ + + outb( 0, iobase+IER); /* Disable interrupts */ + + if ( eir) { + /* Dispatch interrupt handler for the current speed */ + if ( idev->io.baudrate > 115200) + ier = pc87108_fir_interrupt( idev, iobase, eir); + else + ier = pc87108_sir_interrupt( idev, eir); + } + + outb( ier, iobase+IER); /* Restore interrupts */ + outb( bsr, iobase+BSR); /* Restore bank register */ + + idev->netdev.interrupt = 0; +} + +/* + * Function pc87108_wait_until_sent (idev) + * + * This function should put the current thread to sleep until all data + * have been sent, so it is safe to f.eks. change the speed. + */ +static void pc87108_wait_until_sent( struct irda_device *idev) +{ + /* Just delay 60 ms */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(6); +} + +/* + * Function pc87108_is_receiving (idev) + * + * Return TRUE is we are currently receiving a frame + * + */ +static int pc87108_is_receiving( struct irda_device *idev) +{ + int status = FALSE; + int iobase; + __u8 bank; + + ASSERT( idev != NULL, return FALSE;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return FALSE;); + + if ( idev->io.baudrate > 115200) { + iobase = idev->io.iobase; + + /* Check if rx FIFO is not empty */ + bank = inb( iobase+BSR); + switch_bank( iobase, BANK2); + if (( inb( iobase+RXFLV) & 0x3f) != 0) { + /* We are receiving something */ + status = TRUE; + } + outb( bank, iobase+BSR); + } else + status = ( idev->rx_buff.state != OUTSIDE_FRAME); + + return status; +} + +/* + * Function pc87108_net_init (dev) + * + * Initialize network device + * + */ +static int pc87108_net_init( struct device *dev) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + /* Setup to be a normal IrDA network device driver */ + irda_device_setup( dev); + + /* Insert overrides below this line! */ + + return 0; +} + + +/* + * Function pc87108_net_open (dev) + * + * Start the device + * + */ +static int pc87108_net_open( struct device *dev) +{ + struct irda_device *idev; + int iobase; + __u8 bank; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( dev != NULL, return -1;); + idev = (struct irda_device *) dev->priv; + + ASSERT( idev != NULL, return 0;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;); + + iobase = idev->io.iobase; + + if (request_irq( idev->io.irq, pc87108_interrupt, 0, idev->name, + (void *) idev)) { + return -EAGAIN; + } + /* + * Always allocate the DMA channel after the IRQ, + * and clean up on failure. + */ + if (request_dma(idev->io.dma, idev->name)) { + free_irq( idev->io.irq, idev); + return -EAGAIN; + } + + /* Ready to play! */ + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + /* Save current bank */ + bank = inb( iobase+BSR); + + /* turn on interrupts */ + switch_bank( iobase, BANK0); + outb( IER_LS_IE | IER_RXHDL_IE, iobase+IER); + + /* Restore bank register */ + outb( bank, iobase+BSR); + + MOD_INC_USE_COUNT; + + return 0; +} + +/* + * Function pc87108_net_close (dev) + * + * Stop the device + * + */ +static int pc87108_net_close(struct device *dev) +{ + struct irda_device *idev; + int iobase; + __u8 bank; + + DEBUG( 4, __FUNCTION__ "()\n"); + + /* Stop device */ + dev->tbusy = 1; + dev->start = 0; + + ASSERT( dev != NULL, return -1;); + idev = (struct irda_device *) dev->priv; + + ASSERT( idev != NULL, return 0;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;); + + iobase = idev->io.iobase; + + disable_dma( idev->io.dma); + + /* Save current bank */ + bank = inb( iobase+BSR); + + /* Disable interrupts */ + switch_bank( iobase, BANK0); + outb( 0, iobase+IER); + + free_irq( idev->io.irq, idev); + free_dma( idev->io.dma); + + /* Restore bank register */ + outb( bank, iobase+BSR); + + MOD_DEC_USE_COUNT; + + return 0; +} + +#ifdef MODULE + +/* + * Function init_module (void) + * + * + * + */ +int init_module(void) +{ + pc87108_init(); + + return(0); +} + +/* + * Function cleanup_module (void) + * + * + * + */ +void cleanup_module(void) +{ + pc87108_cleanup(); +} + +#endif + diff --git a/drivers/net/irda/tekram.c b/drivers/net/irda/tekram.c new file mode 100644 index 000000000000..818937ee16a0 --- /dev/null +++ b/drivers/net/irda/tekram.c @@ -0,0 +1,313 @@ +/********************************************************************* + * + * Filename: tekram.c + * Version: 0.3 + * Description: Implementation of the Tekram IrMate IR-210B dongle + * Status: Experimental. + * Author: Dag Brattli + * Created at: Wed Oct 21 20:02:35 1998 + * Modified at: Mon Dec 14 11:48:37 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +static void tekram_reset( struct irda_device *dev, int unused); +static void tekram_open( struct irda_device *dev, int type); +static void tekram_close( struct irda_device *dev); +static void tekram_change_speed( struct irda_device *dev, int baud); +static void tekram_init_qos( struct irda_device *idev, struct qos_info *qos); + +static struct dongle dongle = { + TEKRAM_DONGLE, + tekram_open, + tekram_close, + tekram_reset, + tekram_change_speed, + tekram_init_qos, +}; + +__initfunc(void tekram_init(void)) +{ + irtty_register_dongle( &dongle); +} + +void tekram_cleanup(void) +{ + irtty_unregister_dongle( &dongle); +} + +static void tekram_open( struct irda_device *dev, int type) +{ + strcat( dev->name, " <-> tekram"); + + MOD_INC_USE_COUNT; +} + +static void tekram_close( struct irda_device *dev) +{ + MOD_DEC_USE_COUNT; +} + +/* + * Function tekram_change_speed (tty, baud) + * + * Set the speed for the Tekram IRMate 210 type dongle. Warning, this + * function must be called with a process context! + * + * Algorithm + * 1. clear DTR + * 2. set RTS, and wait at least 7 us + * 3. send Control Byte to the IR-210 through TXD to set new baud rate + * wait until the stop bit of Control Byte is sent (for 9600 baud rate, + * it takes about 100 msec) + * 5. clear RTS (return to NORMAL Operation) + * 6. wait at least 50 us, new setting (baud rate, etc) takes effect here + * after + */ +static void tekram_change_speed( struct irda_device *dev, int baud) +{ + struct irtty_cb *self; + struct tty_struct *tty; + struct termios old_termios; + int arg = 0; + int cflag; + __u8 byte; + int actual; + mm_segment_t fs; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( dev != NULL, return;); + ASSERT( dev->magic == IRDA_DEVICE_MAGIC, return;); + + self = (struct irtty_cb *) dev->priv; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRTTY_MAGIC, return;); + + if ( !self->tty) + return; + + tty = self->tty; + + old_termios = *(tty->termios); + cflag = tty->termios->c_cflag; + + cflag &= ~CBAUD; + + switch (baud) { + case 9600: + default: + cflag |= B9600; + byte = 4; + break; + case 19200: + cflag |= B19200; + byte = 3; + break; + case 34800: + cflag |= B38400; + byte = 2; + break; + case 57600: + cflag |= B57600; + byte = 1; + break; + case 115200: + cflag |= B115200; + byte = 0; + break; + } + + /* Set DTR, Clear RTS */ + DEBUG( 0, __FUNCTION__ "(), Setting DTR, Clearing RTS\n"); + arg = TIOCM_DTR; + + fs = get_fs(); + set_fs( get_ds()); + + if ( tty->driver.ioctl( tty, NULL, TIOCMSET, + (unsigned long) &arg)) { + DEBUG( 0, "error setting Tekram speed!\n"); + } + set_fs(fs); + + /* Wait at least 7us */ + udelay( 7); + + DEBUG( 0, __FUNCTION__ "(), Writing control byte\n"); + /* Write control byte */ + if ( tty->driver.write) + actual = tty->driver.write( self->tty, 0, &byte, 1); + + /* Wait at least 100 ms */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout( 10); + + /* Set DTR, Set RTS */ + DEBUG( 0, __FUNCTION__ "(), Setting DTR, Setting RTS\n"); + arg = TIOCM_DTR | TIOCM_RTS; + + fs = get_fs(); + set_fs( get_ds()); + + if ( tty->driver.ioctl( tty, NULL, TIOCMSET, + (unsigned long) &arg)) { + DEBUG( 0, "error setting Tekram speed!\n"); + } + set_fs(fs); + + DEBUG( 0, __FUNCTION__ "(), Setting new speed on serial port\n"); + /* Now change the speed of the serial port */ + tty->termios->c_cflag = cflag; + tty->driver.set_termios( tty, &old_termios); +} + +/* + * Function tekram_reset (driver) + * + * This function resets the tekram dongle. Warning, this function + * must be called with a process context!! + * + * Algorithm: + * 0. set RTS and DTR, and wait 50 ms + * ( power off the IR-210 ) + * 1. clear RTS + * 2. set DTR, and wait at least 1 ms + * 3. clear DTR to SPACE state, wait at least 50 us for further + * operation + */ +void tekram_reset( struct irda_device *dev, int unused) +{ + struct irtty_cb *self; + struct tty_struct *tty; + int arg = 0; + mm_segment_t fs; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( dev != NULL, return;); + ASSERT( dev->magic == IRDA_DEVICE_MAGIC, return;); + + self = (struct irtty_cb *) dev->priv; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRTTY_MAGIC, return;); + + tty = self->tty; + if ( !tty) + return; + + DEBUG( 0, __FUNCTION__ "(), Power off dongle\n"); + arg = TIOCM_RTS | TIOCM_DTR; + + fs = get_fs(); + set_fs( get_ds()); + + if ( tty->driver.ioctl( tty, NULL, TIOCMSET, + (unsigned long) &arg)) + { + DEBUG(0, "error setting ESI speed!\n"); + } + set_fs(fs); + + /* Sleep 50 ms */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(5); + + DEBUG( 0, __FUNCTION__ "(), Set DTR, clear RTS\n"); + /* Set DTR, clear RTS */ + arg = TIOCM_DTR; + + fs = get_fs(); + set_fs( get_ds()); + + if ( tty->driver.ioctl( tty, NULL, TIOCMSET, + (unsigned long) &arg)) { + DEBUG( 0, "Error setting Tekram speed!\n"); + } + set_fs(fs); + + /* Should sleep 1 ms, but 10-20 should not do any harm */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(2); + + DEBUG( 0, __FUNCTION__ "(), STATE3\n"); + /* Clear DTR, clear RTS */ + fs = get_fs(); + set_fs( get_ds()); + + if ( tty->driver.ioctl( tty, NULL, TIOCMSET, (unsigned long) &arg)) { + DEBUG( 0, "error setting Tekram speed!\n"); + } + set_fs(fs); + + /* Finished! */ +} + +/* + * Function tekram_init_qos (qos) + * + * Initialize QoS capabilities + * + */ +static void tekram_init_qos( struct irda_device *idev, struct qos_info *qos) +{ + qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; + qos->min_turn_time.bits &= 0xfe; /* All except 0 ms */ +} + +#ifdef MODULE + +/* + * Function init_module (void) + * + * Initialize Tekram module + * + */ +int init_module(void) +{ + tekram_init(); + return(0); +} + +/* + * Function cleanup_module (void) + * + * Cleanup Tekram module + * + */ +void cleanup_module(void) +{ + tekram_cleanup(); +} + +#endif diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c new file mode 100644 index 000000000000..850ba7203149 --- /dev/null +++ b/drivers/net/irda/w83977af_ir.c @@ -0,0 +1,1275 @@ +/********************************************************************* + * + * Filename: w83977af_ir.c + * Version: 0.8 + * Description: FIR/MIR driver for the Winbond W83977AF Super I/O chip + * Status: Experimental. + * Author: Paul VanderSpek + * Created at: Wed Nov 4 11:46:16 1998 + * Modified at: Mon Dec 14 21:51:53 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Corel Computer Corp. + * Copyright (c) 1998 Dag Brattli + * + * 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. + * + * Neither Paul VanderSpek nor Corel Computer Corp. admit liability + * nor provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + * If you find bugs in this file, its very likely that the same bug + * will also be in w83977af_ir.c since the implementations is quite + * similar. + * + * Notice that all functions that needs to access the chip in _any_ + * way, must save BSR register on entry, and restore it on exit. + * It is _very_ important to follow this policy! + * + * __u8 bank; + * + * bank = inb( iobase+BSR); + * + * do_your_stuff_here(); + * + * outb( bank, iobase+BSR); + * + ********************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define NETWINDER + +static char *driver_name = "w83977af_ir"; + +#define CHIP_IO_EXTENT 8 + +static unsigned int io[] = { 0x400, ~0, ~0, ~0 }; +static unsigned int irq[] = { 22, 0, 0, 0 }; +static unsigned int dma[] = { 0, 0, 0, 0 }; + +static struct irda_device *dev_self[] = { NULL, NULL, NULL, NULL}; + +/* For storing entries in the status FIFO */ +struct st_fifo_entry { + int status; + int len; +}; + +static struct st_fifo_entry prev; + +/* Some prototypes */ +static int w83977af_open( int i, unsigned int iobase, unsigned int irq, + unsigned int dma); +static int w83977af_close( struct irda_device *idev); +static int w83977af_probe( int iobase, int irq, int dma); +static int w83977af_dma_receive(struct irda_device *idev); +static int w83977af_dma_receive_complete(struct irda_device *idev); +static int w83977af_hard_xmit( struct sk_buff *skb, struct device *dev); +static int w83977af_pio_write( int iobase, __u8 *buf, int len, int fifo_size); +static void w83977af_dma_write( struct irda_device *idev, int iobase); +static void w83977af_change_speed( struct irda_device *idev, int baud); +static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static void w83977af_wait_until_sent( struct irda_device *idev); +static int w83977af_is_receiving( struct irda_device *idev); + +static int w83977af_net_init( struct device *dev); +static int w83977af_net_open( struct device *dev); +static int w83977af_net_close( struct device *dev); + +/* + * Function w83977af_init () + * + * Initialize chip. Just try to find out how many chips we are dealing with + * and where they are + */ +__initfunc(int w83977af_init(void)) +{ + int i; + + DEBUG( 0, __FUNCTION__ "()\n"); + + prev.status = 0; + + for ( i=0; (io[i] < 2000) && (i < 4); i++) { + int ioaddr = io[i]; + if (check_region(ioaddr, CHIP_IO_EXTENT)) + continue; + if (w83977af_open( i, io[i], irq[i], dma[i]) == 0) + return 0; + } + return -ENODEV; +} + +/* + * Function w83977af_cleanup () + * + * Close all configured chips + * + */ +#ifdef MODULE +void w83977af_cleanup(void) +{ + int i; + + DEBUG( 4, __FUNCTION__ "()\n"); + + for ( i=0; i < 4; i++) { + if ( dev_self[i]) + w83977af_close( dev_self[i]); + } +} +#endif /* MODULE */ + +/* + * Function w83977af_open (iobase, irq) + * + * Open driver instance + * + */ +int w83977af_open( int i, unsigned int iobase, unsigned int irq, + unsigned int dma) +{ + struct irda_device *idev; + int ret; + + DEBUG( 0, __FUNCTION__ "()\n"); + + if ( w83977af_probe( iobase, irq, dma) == -1) + return -1; + + /* + * Allocate new instance of the driver + */ + idev = kmalloc( sizeof(struct irda_device), GFP_KERNEL); + if ( idev == NULL) { + printk( KERN_ERR "IrDA: Can't allocate memory for " + "IrDA control block!\n"); + return -ENOMEM; + } + memset( idev, 0, sizeof(struct irda_device)); + + /* Need to store self somewhere */ + dev_self[i] = idev; + + /* Initialize IO */ + idev->io.iobase = iobase; + idev->io.irq = irq; + idev->io.io_ext = CHIP_IO_EXTENT; + idev->io.dma = dma; + idev->io.fifo_size = 32; + + /* Lock the port that we need */ + ret = check_region( idev->io.iobase, idev->io.io_ext); + if ( ret < 0) { + DEBUG( 0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", + idev->io.iobase); + /* w83977af_cleanup( self->idev); */ + return -ENODEV; + } + request_region( idev->io.iobase, idev->io.io_ext, idev->name); + + /* Initialize QoS for this device */ + irda_init_max_qos_capabilies( &idev->qos); + + /* The only value we must override it the baudrate */ + + /* FIXME: The HP HDLS-1100 does not support 1152000! */ + idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| + IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8); + + /* The HP HDLS-1100 needs 1 ms according to the specs */ + idev->qos.min_turn_time.bits = 0x03; /* 1ms and more */ + irda_qos_bits_to_value( &idev->qos); + + /* Specify which buffer allocation policy we need */ + idev->rx_buff.flags = GFP_KERNEL | GFP_DMA; + idev->tx_buff.flags = GFP_KERNEL | GFP_DMA; + + /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */ + idev->rx_buff.truesize = 14384; + idev->tx_buff.truesize = 4000; + + /* Initialize callbacks */ + idev->hard_xmit = w83977af_hard_xmit; + idev->change_speed = w83977af_change_speed; + idev->wait_until_sent = w83977af_wait_until_sent; + idev->is_receiving = w83977af_is_receiving; + + /* Override the network functions we need to use */ + idev->netdev.init = w83977af_net_init; + idev->netdev.hard_start_xmit = w83977af_hard_xmit; + idev->netdev.open = w83977af_net_open; + idev->netdev.stop = w83977af_net_close; + + /* Open the IrDA device */ + irda_device_open( idev, driver_name, NULL); + + return 0; +} + +/* + * Function w83977af_close (idev) + * + * Close driver instance + * + */ +static int w83977af_close( struct irda_device *idev) +{ + int iobase; + + DEBUG( 0, __FUNCTION__ "()\n"); + + ASSERT( idev != NULL, return -1;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;); + + iobase = idev->io.iobase; + + /* enter PnP configuration mode */ + w977_efm_enter(); + + w977_select_device(W977_DEVICE_IR); + + /* Deactivate device */ + w977_write_reg(0x30, 0x00); + + w977_efm_exit(); + + /* Release the PORT that this driver is using */ + DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", + idev->io.iobase); + release_region( idev->io.iobase, idev->io.io_ext); + + irda_device_close( idev); + + return 0; +} + +/* + * Function w83977af_probe (iobase, irq, dma) + * + * Returns non-negative on success. + * + */ +int w83977af_probe( int iobase, int irq, int dma) +{ + int version; + + DEBUG( 0, __FUNCTION__ "()\n"); + + /* Enter PnP configuration mode */ + w977_efm_enter(); + + w977_select_device(W977_DEVICE_IR); + + /* Configure PnP port, IRQ, and DMA channel */ + w977_write_reg(0x60, (iobase >> 8) & 0xff); + w977_write_reg(0x61, (iobase) & 0xff); + w977_write_reg(0x70, 0x06); +#ifdef NETWINDER + w977_write_reg(0x74, dma+1); /* Netwinder uses 1 higher than Linux */ +#else + w977_write_reg(0x74, dma); +#endif + w977_write_reg(0x75, dma); /* Disable Tx DMA */ + + /* Set append hardware CRC, enable IR bank selection */ + w977_write_reg(0xf0, APEDCRC|ENBNKSEL); + + /* Activate device */ + w977_write_reg(0x30, 0x01); + + w977_efm_exit(); + + /* Disable Advanced mode */ + switch_bank( iobase, SET2); + outb(iobase+2, 0x00); + + /* Turn on UART (global) interrupts */ + switch_bank( iobase, SET0); + outb( HCR_EN_IRQ, iobase+HCR); + + /* Switch to advanced mode */ + switch_bank( iobase, SET2); + outb( inb( iobase+ADCR1) | ADCR1_ADV_SL, iobase+ADCR1); + + /* Set default IR-mode */ + switch_bank( iobase, SET0); + outb( HCR_SIR, iobase+HCR); + + /* Read the Advanced IR ID */ + switch_bank(iobase, SET3); + version = inb( iobase+AUID); + + /* Should be 0x1? */ + if (0x10 != (version & 0xf0)) { + DEBUG( 0, __FUNCTION__ "(), Wrong chip version"); + return -1; + } + + /* Set FIFO size to 32 */ + switch_bank( iobase, SET2); + outb( ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2); + + /* Set FIFO threshold to TX17, RX16 */ + switch_bank(iobase, SET0); + outb(UFR_RXTL|UFR_TXTL|UFR_TXF_RST|UFR_RXF_RST|UFR_EN_FIFO,iobase+UFR); +/* outb( 0xa7, iobase+UFR); */ + + /* Receiver frame length */ + switch_bank( iobase, SET4); + outb( 2048 & 0xff, iobase+6); + outb(( 2048 >> 8) & 0x1f, iobase+7); + + /* + * Init HP HSDL-1100 transceiver. + * + * Set IRX_MSL since we have 2 * receive paths IRRX, and + * IRRXH. Clear IRSL0D since we want IRSL0 * to be a input pin used + * for IRRXH + * + * IRRX pin 37 connected to receiver + * IRTX pin 38 connected to transmitter + * FIRRX pin 39 connected to receiver (IRSL0) + * CIRRX pin 40 connected to pin 37 + */ + switch_bank( iobase, SET7); + outb( 0x40, iobase+7); + + DEBUG(0, "W83977AF (IR) driver loaded. Version: 0x%02x\n", version); + + return 0; +} + +/* + * Function w83977af_change_speed (idev, baud) + * + * Change the speed of the device + * + */ +void w83977af_change_speed( struct irda_device *idev, int speed) +{ + int ir_mode = HCR_SIR; + int iobase; + __u8 set; + + DEBUG( 0, __FUNCTION__ "()\n"); + + ASSERT( idev != NULL, return;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); + + iobase = idev->io.iobase; + + /* Update accounting for new speed */ + idev->io.baudrate = speed; + + /* Save current bank */ + set = inb( iobase+SSR); + + /* Disable interrupts */ + switch_bank( iobase, SET0); + outb( 0, iobase+ICR); + + /* Select Set 2 */ + switch_bank( iobase, SET2); + + outb( 0x00, iobase+ABHL); + switch ( speed) { + case 9600: outb( 0x0c, iobase+ABLL); break; + case 19200: outb( 0x06, iobase+ABLL); break; + case 37600: outb( 0x03, iobase+ABLL); break; + case 57600: outb( 0x02, iobase+ABLL); break; + case 115200: outb( 0x01, iobase+ABLL); break; + case 576000: + ir_mode = HCR_MIR_576; + DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n"); + break; + case 1152000: + ir_mode = HCR_MIR_1152; + DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n"); + break; + case 4000000: + ir_mode = HCR_FIR; + DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n"); + break; + default: + ir_mode = HCR_FIR; + DEBUG( 0, __FUNCTION__ "(), unknown baud rate of %d\n", speed); + break; + } + + /* Set speed mode */ + switch_bank(iobase, SET0); + outb( ir_mode, iobase+HCR); + + /* set FIFO size to 32 */ + switch_bank( iobase, SET2); + outb( ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2); + + /* set FIFO threshold to TX17, RX16 */ + switch_bank(iobase, SET0); + outb( UFR_RXTL|UFR_TXTL|UFR_TXF_RST|UFR_RXF_RST|UFR_EN_FIFO, iobase+UFR); + + idev->netdev.tbusy = 0; + + /* Enable some interrupts so we can receive frames */ + switch_bank(iobase, SET0); + if ( speed > 115200) { + outb( ICR_EFSFI, iobase+ICR); + w83977af_dma_receive( idev); + } else + outb( ICR_ERBRI, iobase+ICR); + + /* Restore SSR */ + outb( set, iobase+SSR); +} + +/* + * Function w83977af_hard_xmit (skb, dev) + * + * Sets up a DMA transfer to send the current frame. + * + */ +int w83977af_hard_xmit( struct sk_buff *skb, struct device *dev) +{ + struct irda_device *idev; + int iobase; + __u8 set; + int mtt; + + idev = (struct irda_device *) dev->priv; + + ASSERT( idev != NULL, return 0;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;); + + iobase = idev->io.iobase; + + DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len); + + if ( dev->tbusy) { + DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n"); + + return -EBUSY; + } + + /* Lock transmit buffer */ + if ( irda_lock( (void *) &dev->tbusy) == FALSE) + return -EBUSY; + + /* Save current set */ + set = inb( iobase+SSR); + + /* Decide if we should use PIO or DMA transfer */ + if ( idev->io.baudrate > 115200) { + memcpy( idev->tx_buff.data, skb->data, skb->len); + idev->tx_buff.len = skb->len; + idev->tx_buff.head = idev->tx_buff.data; + idev->tx_buff.offset = 0; + + mtt = irda_get_mtt( skb); + if ( mtt > 50) { + /* Adjust for timer resolution */ + mtt /= 1000+1; + + /* Setup timer */ + switch_bank( iobase, SET4); + outb( mtt & 0xff, iobase+TMRL); + outb(( mtt >> 8) & 0x0f, iobase+TMRH); + + /* Start timer */ + outb( IR_MSL_EN_TMR, iobase+IR_MSL); + idev->io.direction = IO_XMIT; + + /* Enable timer interrupt */ + switch_bank( iobase, SET0); + outb( ICR_ETMRI, iobase+ICR); + } else { + if ( mtt) + udelay( mtt); + + /* Enable DMA interrupt */ + switch_bank( iobase, SET0); + outb( ICR_EDMAI, iobase+ICR); + w83977af_dma_write( idev, iobase); + } + } else { + idev->tx_buff.len = async_wrap_skb( skb, idev->tx_buff.data, + idev->tx_buff.truesize); + + idev->tx_buff.offset = 0; + idev->tx_buff.head = idev->tx_buff.data; + + /* Add interrupt on tx low level (will fire immediately) */ + switch_bank( iobase, SET0); + outb( ICR_ETXTHI, iobase+ICR); + } + dev_kfree_skb( skb); + + /* Restore set register */ + outb( set, iobase+SSR); + + return 0; +} + + +/* + * Function w83977af_dma_write (idev, iobase) + * + * + * + */ +static void w83977af_dma_write( struct irda_device *idev, int iobase) +{ + __u8 set; + + DEBUG( 4, __FUNCTION__ "()\n"); + + /* Save current set */ + set = inb( iobase+SSR); + + /* Disable DMA */ + switch_bank(iobase, SET0); + outb( inb( iobase+HCR) & ~HCR_EN_DMA, iobase+HCR); + + setup_dma( idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, + DMA_MODE_WRITE); + + /* idev->media_busy = TRUE; */ + idev->io.direction = IO_XMIT; + + /* Choose transmit DMA channel */ + switch_bank(iobase, SET2); + outb( inb( iobase+ADCR1) | ADCR1_D_CHSW|ADCR1_DMA_F|ADCR1_ADV_SL, + iobase+ADCR1); + + /* Enable DMA */ + switch_bank( iobase, SET0); + outb( inb( iobase+HCR) | HCR_EN_DMA, iobase+HCR); + + /* Restore set register */ + outb( set, iobase+SSR); +} + +/* + * Function w83977af_pio_write (iobase, buf, len, fifo_size) + * + * + * + */ +static int w83977af_pio_write( int iobase, __u8 *buf, int len, int fifo_size) +{ + int actual = 0; + __u8 set; + + DEBUG( 4, __FUNCTION__ "()\n"); + + /* Save current bank */ + set = inb( iobase+SSR); + + switch_bank( iobase, SET0); + if (!( inb_p( iobase+USR) & USR_TSRE)) { + DEBUG( 4, __FUNCTION__ "(), warning, FIFO not empty yet!\n"); + + fifo_size -= 17; + DEBUG( 4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size); + } + + /* Fill FIFO with current frame */ + while (( fifo_size-- > 0) && (actual < len)) { + /* Transmit next byte */ + outb( buf[actual++], iobase+TBR); + } + + DEBUG( 4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", + fifo_size, actual, len); + + /* Restore bank */ + outb( set, iobase+SSR); + + return actual; +} + +/* + * Function w83977af_dma_xmit_complete (idev) + * + * The transfer of a frame in finished. So do the necessary things + * + * + */ +void w83977af_dma_xmit_complete( struct irda_device *idev) +{ + int iobase; + __u8 set; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( idev != NULL, return;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); + + iobase = idev->io.iobase; + + /* Save current set */ + set = inb( iobase+SSR); + + /* Disable DMA */ + switch_bank(iobase, SET0); + outb( inb(iobase+HCR) & ~HCR_EN_DMA, iobase+HCR); + + /* Check for underrrun! */ + if ( inb( iobase+AUDR) & AUDR_UNDR) { + DEBUG( 0, __FUNCTION__ "(), Transmit underrun!\n"); + + idev->stats.tx_errors++; + idev->stats.tx_fifo_errors++; + + /* Clear bit, by writing 1 to it */ + outb( AUDR_UNDR, iobase+AUDR); + } else + idev->stats.tx_packets++; + + /* Unlock tx_buff and request another frame */ + idev->netdev.tbusy = 0; /* Unlock */ + idev->media_busy = FALSE; + + /* Tell the network layer, that we want more frames */ + mark_bh( NET_BH); + + /* Restore set */ + outb( set, iobase+SSR); +} + +/* + * Function w83977af_dma_receive (idev) + * + * Get ready for receiving a frame. The device will initiate a DMA + * if it starts to receive a frame. + * + */ +int w83977af_dma_receive( struct irda_device *idev) +{ + int iobase; + __u8 set; +#ifdef NETWINDER + unsigned long flags; + __u8 hcr; +#endif + + ASSERT( idev != NULL, return -1;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;); + + DEBUG( 0, __FUNCTION__ "\n"); + + iobase= idev->io.iobase; + + /* Save current set */ + set = inb( iobase+SSR); + + /* Disable DMA */ + switch_bank( iobase, SET0); + outb( inb( iobase+HCR) & ~HCR_EN_DMA, iobase+HCR); + +#ifdef NETWINDER + save_flags(flags); + cli(); + + disable_dma( idev->io.dma); + clear_dma_ff( idev->io.dma); + set_dma_mode( idev->io.dma, DMA_MODE_READ); + set_dma_addr( idev->io.dma, virt_to_bus(idev->rx_buff.data)); + set_dma_count( idev->io.dma, idev->rx_buff.truesize); +#else + setup_dma( idev->io.dma, idev->rx_buff.data, idev->rx_buff.truesize, + DMA_MODE_READ); +#endif + /* driver->media_busy = FALSE; */ + idev->io.direction = IO_RECV; + idev->rx_buff.head = idev->rx_buff.data; + idev->rx_buff.offset = 0; + + /* + * Reset Rx FIFO. This will also flush the ST_FIFO, it's very + * important that we don't reset the Tx FIFO since it might not + * be finished transmitting yet + */ + outb( UFR_RXTL|UFR_TXTL|UFR_RXF_RST|UFR_EN_FIFO, iobase+UFR); + prev.status = 0; + + /* Choose DMA Rx, DMA Fairness, and Advanced mode */ + switch_bank(iobase, SET2); + outb(( inb( iobase+ADCR1) & ~ADCR1_D_CHSW)|ADCR1_DMA_F|ADCR1_ADV_SL, + iobase+ADCR1); + + /* Enable DMA */ + switch_bank(iobase, SET0); +#ifdef NETWINDER + hcr = inb( iobase+HCR); + enable_dma( idev->io.dma); + outb( hcr | HCR_EN_DMA, iobase+HCR); + restore_flags(flags); +#else + outb( inb( iobase+HCR) | HCR_EN_DMA, iobase+HCR); +#endif + + /* Restore set */ + outb( set, iobase+SSR); + + DEBUG( 4, __FUNCTION__ "(), done!\n"); + + return 0; +} + +/* + * Function w83977af_receive_complete (idev) + * + * Finished with receiving a frame + * + */ +int w83977af_dma_receive_complete(struct irda_device *idev) +{ + struct sk_buff *skb; + int len; + int iobase; + __u8 set; + __u8 status; + + DEBUG( 0, __FUNCTION__ "\n"); + + iobase = idev->io.iobase; + + /* Save current set */ + set = inb( iobase+SSR); + + iobase = idev->io.iobase; + + switch_bank(iobase, SET5); + if ( prev.status & FS_FO_FSFDR) { + status = prev.status; + len = prev.len; + + prev.status = 0; + } else { + status = inb( iobase+FS_FO); + len = inb( iobase+RFLFL); + len |= inb( iobase+RFLFH) << 8; + } + + while ( status & FS_FO_FSFDR) { + /* Check for errors */ + if ( status & FS_FO_ERR_MSK) { + if ( status & FS_FO_LST_FR) { + /* Add number of lost frames to stats */ + idev->stats.rx_errors += len; + } else { + /* Skip frame */ + idev->stats.rx_errors++; + + idev->rx_buff.offset += len; + idev->rx_buff.head += len; + + if ( status & FS_FO_MX_LEX) + idev->stats.rx_length_errors++; + + if ( status & FS_FO_PHY_ERR) + idev->stats.rx_frame_errors++; + + if ( status & FS_FO_CRC_ERR) + idev->stats.rx_crc_errors++; + } + /* The errors below can be reported in both cases */ + if ( status & FS_FO_RX_OV) + idev->stats.rx_fifo_errors++; + + if ( status & FS_FO_FSF_OV) + idev->stats.rx_fifo_errors++; + + } else { + /* Check if we have transfered all data to memory */ + switch_bank(iobase, SET0); + if ( inb( iobase+USR) & USR_RDR) { + /* Put this entry back in fifo */ + prev.status = status; + prev.len = len; + + /* Restore set register */ + outb( set, iobase+SSR); + + return FALSE; /* I'll be back! */ + } + + skb = dev_alloc_skb( len+1); + if (skb == NULL) { + printk( KERN_INFO __FUNCTION__ + "(), memory squeeze, dropping frame.\n"); + /* Restore set register */ + outb( set, iobase+SSR); + + return FALSE; + } + + /* Align to 20 bytes */ + skb_reserve( skb, 1); + + /* Copy frame without CRC */ + if ( idev->io.baudrate < 4000000) { + skb_put( skb, len-2); + memcpy( skb->data, idev->rx_buff.head, len-2); + } else { + skb_put( skb, len-4); + memcpy( skb->data, idev->rx_buff.head, len-4); + } + + /* Move to next frame */ + idev->rx_buff.offset += len; + idev->rx_buff.head += len; + + skb->dev = &idev->netdev; + skb->mac.raw = skb->data; + skb->protocol = htons(ETH_P_IRDA); + netif_rx( skb); + idev->stats.rx_packets++; + } + /* Read next entry in ST_FIFO */ + switch_bank(iobase, SET5); + status = inb( iobase+FS_FO); + len = inb( iobase+RFLFL); + len |= inb( iobase+RFLFH) << 8; + } + /* Restore set register */ + outb( set, iobase+SSR); + + return TRUE; +} + +/* + * Function pc87108_pio_receive (idev) + * + * Receive all data in receiver FIFO + * + */ +static void w83977af_pio_receive( struct irda_device *idev) +{ + __u8 byte = 0x00; + int iobase; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( idev != NULL, return;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); + + iobase = idev->io.iobase; + + if ( idev->rx_buff.len == 0) { + idev->rx_buff.head = idev->rx_buff.data; + } + + /* Receive all characters in Rx FIFO */ + do { + byte = inb( iobase+RBR); + async_unwrap_char( idev, byte); + + } while ( inb( iobase+USR) & USR_RDR); /* Data available */ +} + +/* + * Function w83977af_sir_interrupt (idev, eir) + * + * Handle SIR interrupt + * + */ +static __u8 w83977af_sir_interrupt( struct irda_device *idev, int isr) +{ + int len; + int actual; + __u8 new_icr = 0; + + DEBUG( 4, __FUNCTION__ "(), isr=%#x\n", isr); + + /* Transmit FIFO low on data */ + if ( isr & ISR_TXTH_I) { + /* Write data left in transmit buffer */ + len = idev->tx_buff.len - idev->tx_buff.offset; + + ASSERT( len > 0, return 0;); + actual = w83977af_pio_write( idev->io.iobase, + idev->tx_buff.head, + len, idev->io.fifo_size); + idev->tx_buff.offset += actual; + idev->tx_buff.head += actual; + + idev->io.direction = IO_XMIT; + ASSERT( actual <= len, return 0;); + /* Check if finished */ + if ( actual == len) { + DEBUG( 4, __FUNCTION__ "(), finished with frame!\n"); + idev->netdev.tbusy = 0; /* Unlock */ + idev->stats.tx_packets++; + + /* Schedule network layer */ + mark_bh(NET_BH); + + new_icr |= ICR_ETBREI; + } else + new_icr |= ICR_ETXTHI; + } + /* Check if transmission has completed */ + if ( isr & ISR_TXEMP_I) { + + /* Turn around and get ready to receive some data */ + idev->io.direction = IO_RECV; + new_icr |= ICR_ERBRI; + } + + /* Rx FIFO threshold or timeout */ + if ( isr & ISR_RXTH_I) { + w83977af_pio_receive( idev); + + /* Keep receiving */ + new_icr |= ICR_ERBRI; + } + return new_icr; +} + +/* + * Function pc87108_fir_interrupt (idev, eir) + * + * Handle MIR/FIR interrupt + * + */ +static __u8 w83977af_fir_interrupt( struct irda_device *idev, int isr) +{ + __u8 new_icr = 0; + __u8 set; + int iobase; + + DEBUG( 4, __FUNCTION__ "(), isr=%#x\n", isr); + + iobase = idev->io.iobase; + + set = inb( iobase+SSR); + + /* End of frame detected in FIFO */ + if ( isr & (ISR_FEND_I|ISR_FSF_I)) { + if ( w83977af_dma_receive_complete( idev)) { + + new_icr |= ICR_EFSFI; + } else { + /* DMA not finished yet */ + + /* Set timer value, resolution 1 ms */ + switch_bank( iobase, SET4); + outb( 0x01, iobase+TMRL); /* 1 ms */ + outb( 0x00, iobase+TMRH); + + /* Start timer */ + outb( IR_MSL_EN_TMR, iobase+IR_MSL); + + new_icr |= ICR_ETMRI; + } + } + /* Timer finished */ + if ( isr & ISR_TMR_I) { + /* Disable timer */ + switch_bank( iobase, SET4); + outb( 0, iobase+IR_MSL); + + /* Clear timer event */ + /* switch_bank(iobase, SET0); */ +/* outb( ASCR_CTE, iobase+ASCR); */ + + /* Check if this is a TX timer interrupt */ + if ( idev->io.direction == IO_XMIT) { + w83977af_dma_write( idev, iobase); + + new_icr |= ICR_EDMAI; + } else { + /* Check if DMA has now finished */ + w83977af_dma_receive_complete( idev); + + new_icr |= ICR_EFSFI; + } + } + /* Finished with DMA */ + if ( isr & ISR_DMA_I) { + w83977af_dma_xmit_complete( idev); + + /* Check if there are more frames to be transmitted */ + if ( irda_device_txqueue_empty( idev)) { + + /* Prepare for receive */ + w83977af_dma_receive( idev); + new_icr = ICR_EFSFI; + } + } + + /* Restore set */ + outb( set, iobase+SSR); + + return new_icr; +} + +/* + * Function pc87108_interrupt (irq, dev_id, regs) + * + * An interrupt from the chip has arrived. Time to do some work + * + */ +static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + __u8 set, icr, isr; + int iobase; + + struct irda_device *idev = (struct irda_device *) dev_id; + + if ( idev == NULL) { + printk( KERN_WARNING "%s: irq %d for unknown device.\n", + driver_name, irq); + return; + } + + idev->netdev.interrupt = 1; + + iobase = idev->io.iobase; + + /* Save current bank */ + set = inb( iobase+SSR); + switch_bank( iobase, SET0); + + icr = inb( iobase+ICR); + isr = inb( iobase+ISR) & icr; /* Mask out the interesting ones */ + + outb( 0, iobase+ICR); /* Disable interrupts */ + + if ( isr) { + /* Dispatch interrupt handler for the current speed */ + if ( idev->io.baudrate > 115200) + icr = w83977af_fir_interrupt( idev, isr); + else + icr = w83977af_sir_interrupt( idev, isr); + } + + outb( icr, iobase+ICR); /* Restore (new) interrupts */ + outb( set, iobase+SSR); /* Restore bank register */ + + idev->netdev.interrupt = 0; +} + +/* + * Function w83977af_wait_until_sent (idev) + * + * This function should put the current thread to sleep until all data + * have been sent, so it is safe to f.eks. change the speed. + */ +static void w83977af_wait_until_sent( struct irda_device *idev) +{ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(6); +} + +/* + * Function w83977af_is_receiving (idev) + * + * Return TRUE is we are currently receiving a frame + * + */ +static int w83977af_is_receiving( struct irda_device *idev) +{ + int status = FALSE; + int iobase; + __u8 set; + + ASSERT( idev != NULL, return FALSE;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return FALSE;); + + if ( idev->io.baudrate > 115200) { + iobase = idev->io.iobase; + + /* Check if rx FIFO is not empty */ + set = inb( iobase+SSR); + switch_bank( iobase, SET2); + if (( inb( iobase+RXFDTH) & 0x3f) != 0) { + /* We are receiving something */ + status = TRUE; + } + outb( set, iobase+SSR); + } else + status = ( idev->rx_buff.state != OUTSIDE_FRAME); + + return status; +} + +/* + * Function w83977af_net_init (dev) + * + * + * + */ +static int w83977af_net_init( struct device *dev) +{ + DEBUG( 0, __FUNCTION__ "()\n"); + + /* Set up to be a normal IrDA network device driver */ + irda_device_setup( dev); + + /* Insert overrides below this line! */ + + return 0; +} + + +/* + * Function w83977af_net_open (dev) + * + * Start the device + * + */ +static int w83977af_net_open( struct device *dev) +{ + struct irda_device *idev; + int iobase; + __u8 set; + + DEBUG( 0, __FUNCTION__ "()\n"); + + ASSERT( dev != NULL, return -1;); + idev = (struct irda_device *) dev->priv; + + ASSERT( idev != NULL, return 0;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;); + + iobase = idev->io.iobase; + + if (request_irq( idev->io.irq, w83977af_interrupt, 0, idev->name, + (void *) idev)) { + return -EAGAIN; + } + /* + * Always allocate the DMA channel after the IRQ, + * and clean up on failure. + */ + if (request_dma(idev->io.dma, idev->name)) { + free_irq( idev->io.irq, idev); + return -EAGAIN; + } + + /* Ready to play! */ + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + /* Save current set */ + set = inb( iobase+SSR); + + /* Enable some interrupts so we can receive frames again */ + switch_bank(iobase, SET0); + if ( idev->io.baudrate > 115200) { + outb( ICR_EFSFI, iobase+ICR); + w83977af_dma_receive( idev); + } else + outb( ICR_ERBRI, iobase+ICR); + + /* Restore bank register */ + outb( set, iobase+SSR); + + MOD_INC_USE_COUNT; + + return 0; +} + +/* + * Function w83977af_net_close (dev) + * + * Stop the device + * + */ +static int w83977af_net_close(struct device *dev) +{ + struct irda_device *idev; + int iobase; + __u8 set; + + DEBUG( 0, __FUNCTION__ "()\n"); + + /* Stop device */ + dev->tbusy = 1; + dev->start = 0; + + ASSERT( dev != NULL, return -1;); + idev = (struct irda_device *) dev->priv; + + ASSERT( idev != NULL, return 0;); + ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;); + + iobase = idev->io.iobase; + + disable_dma( idev->io.dma); + + /* Save current set */ + set = inb( iobase+SSR); + + /* Disable interrupts */ + switch_bank( iobase, SET0); + outb( 0, iobase+ICR); + + free_irq( idev->io.irq, idev); + free_dma( idev->io.dma); + + /* Restore bank register */ + outb( set, iobase+SSR); + + MOD_DEC_USE_COUNT; + + return 0; +} + +#ifdef MODULE + +/* + * Function init_module (void) + * + * + * + */ +int init_module(void) +{ + w83977af_init(); + + return(0); +} + +/* + * Function cleanup_module (void) + * + * + * + */ +void cleanup_module(void) +{ + w83977af_cleanup(); +} + +#endif diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c index 8d053abf692e..9b175bffaa06 100644 --- a/drivers/net/rrunner.c +++ b/drivers/net/rrunner.c @@ -39,9 +39,11 @@ #include #include #include +#include #include "rrunner.h" + /* * Implementation notes: * @@ -57,7 +59,7 @@ * stack will need to know about I/O vectors or something similar. */ -static const char *version = "rrunner.c: v0.06 09/02/98 Jes Sorensen (Jes.Sorensen@cern.ch)\n"; +static const char *version = "rrunner.c: v0.09 12/14/98 Jes Sorensen (Jes.Sorensen@cern.ch)\n"; static unsigned int read_eeprom(struct rr_private *rrpriv, unsigned long offset, @@ -68,6 +70,14 @@ static u32 read_eeprom_word(struct rr_private *rrpriv, static int rr_load_firmware(struct device *dev); +/* + * These are checked at init time to see if they are at least 256KB + * and increased to 256KB if they are not. This is done to avoid ending + * up with socket buffers smaller than the MTU size, + */ +extern __u32 sysctl_wmem_max; +extern __u32 sysctl_rmem_max; + __initfunc(int rr_hippi_probe (struct device *dev)) { static int i = 0; @@ -116,6 +126,9 @@ __initfunc(int rr_hippi_probe (struct device *dev)) if (dev == NULL) break; + if (!dev->priv) + dev->priv = kmalloc(sizeof(*rrpriv), GFP_KERNEL); + rrpriv = (struct rr_private *)dev->priv; /* Read register base address from @@ -194,12 +207,8 @@ __initfunc(int rr_hippi_probe (struct device *dev)) rr_init(dev); boards_found++; - - /* - * This is bollocks, but we need to tell the net-init - * code that it shall go for the next device. - */ dev->base_addr = 0; + dev = NULL; } /* @@ -347,6 +356,7 @@ static int rr_reset(struct device *dev) return 0; } + /* * Read a string from the EEPROM. */ @@ -356,18 +366,21 @@ static unsigned int read_eeprom(struct rr_private *rrpriv, unsigned long length) { struct rr_regs *regs = rrpriv->regs; - u32 misc, io, i; + u32 misc, io, host, i; io = regs->ExtIo; regs->ExtIo = 0; misc = regs->LocalCtrl; regs->LocalCtrl = 0; + host = regs->HostCtrl; + regs->HostCtrl |= HALT_NIC; for (i = 0; i < length; i++){ regs->WinBase = (EEPROM_BASE + ((offset+i) << 3)); buf[i] = (regs->WinData >> 24) & 0xff; } + regs->HostCtrl = host; regs->LocalCtrl = misc; regs->ExtIo = io; @@ -391,6 +404,58 @@ static u32 read_eeprom_word(struct rr_private *rrpriv, } +/* + * Write a string to the EEPROM. + * + * This is only called when the firmware is not running. + */ +static unsigned int write_eeprom(struct rr_private *rrpriv, + unsigned long offset, + unsigned char *buf, + unsigned long length) +{ + struct rr_regs *regs = rrpriv->regs; + u32 misc, io, data, i, j, ready, error = 0; + + io = regs->ExtIo; + regs->ExtIo = 0; + misc = regs->LocalCtrl; + regs->LocalCtrl = ENABLE_EEPROM_WRITE; + + for (i = 0; i < length; i++){ + regs->WinBase = (EEPROM_BASE + ((offset+i) << 3)); + data = buf[i] << 24; + /* + * Only try to write the data if it is not the same + * value already. + */ + if ((regs->WinData & 0xff000000) != data){ + regs->WinData = data; + ready = 0; + j = 0; + mb(); + while(!ready){ + udelay(1000); + if ((regs->WinData & 0xff000000) == data) + ready = 1; + if (j++ > 5000){ + printk("data mismatch: %08x, " + "WinData %08x\n", data, + regs->WinData); + ready = 1; + error = 1; + } + } + } + } + + regs->LocalCtrl = misc; + regs->ExtIo = io; + + return error; +} + + __initfunc(static int rr_init(struct device *dev)) { struct rr_private *rrpriv; @@ -404,8 +469,13 @@ __initfunc(static int rr_init(struct device *dev)) if (rev > 0x00020024) printk(" Firmware revision: %i.%i.%i\n", (rev >> 16), ((rev >> 8) & 0xff), (rev & 0xff)); - else{ - printk(" Firmware revision too old: %i.%i.%i, please upgrade to 2.0.37 or later.\n", + else if (rev >= 0x00020000) { + printk(" Firmware revision: %i.%i.%i (2.0.37 or " + "later is recommended)\n", (rev >> 16), + ((rev >> 8) & 0xff), (rev & 0xff)); + }else{ + printk(" Firmware revision too old: %i.%i.%i, please " + "upgrade to 2.0.37 or later.\n", (rev >> 16), ((rev >> 8) & 0xff), (rev & 0xff)); return -EFAULT; @@ -416,6 +486,18 @@ __initfunc(static int rr_init(struct device *dev)) sram_size = read_eeprom_word(rrpriv, (void *)8); printk(" SRAM size 0x%06x\n", sram_size); + if (sysctl_rmem_max < 262144){ + printk(" Receive socket buffer limit too low (%i), " + "setting to 262144\n", sysctl_rmem_max); + sysctl_rmem_max = 262144; + } + + if (sysctl_wmem_max < 262144){ + printk(" Transmit socket buffer limit too low (%i), " + "setting to 262144\n", sysctl_wmem_max); + sysctl_wmem_max = 262144; + } + return 0; } @@ -574,7 +656,9 @@ static int rr_init1(struct device *dev) } #endif dev->tbusy = 0; +#if 0 dev->interrupt = 0; +#endif dev->start = 1; return 0; } @@ -590,9 +674,6 @@ static u32 rr_handle_event(struct device *dev, u32 prodidx) struct rr_private *rrpriv; struct rr_regs *regs; u32 tmp, eidx; -#if 0 - short i; -#endif rrpriv = (struct rr_private *)dev->priv; regs = rrpriv->regs; @@ -710,7 +791,8 @@ static int rx_int(struct device *dev, u32 rxlimit) if (pkt_len < PKT_COPY_THRESHOLD) { skb = alloc_skb(pkt_len, GFP_ATOMIC); if (skb == NULL){ - printk("%s: Out of memory deferring packet\n", dev->name); + printk("%s: Out of memory deferring " + "packet\n", dev->name); rrpriv->stats.rx_dropped++; goto defer; }else @@ -720,14 +802,16 @@ static int rx_int(struct device *dev, u32 rxlimit) }else{ struct sk_buff *newskb; - newskb = alloc_skb(dev->mtu + HIPPI_HLEN, GFP_ATOMIC); + newskb = alloc_skb(dev->mtu + HIPPI_HLEN, + GFP_ATOMIC); if (newskb){ skb = rrpriv->rx_skbuff[index]; skb_put(skb, pkt_len); rrpriv->rx_skbuff[index] = newskb; rrpriv->rx_ring[index].addr = virt_to_bus(newskb->data); }else{ - printk("%s: Out of memory, deferring packet\n", dev->name); + printk("%s: Out of memory, deferring " + "packet\n", dev->name); rrpriv->stats.rx_dropped++; goto defer; } @@ -766,18 +850,15 @@ static void rr_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) rrpriv = (struct rr_private *)dev->priv; regs = rrpriv->regs; - if (!(regs->HostCtrl & RR_INT)){ -#if 0 - /* These are harmless */ - printk("%s: spurious interrupt detected\n", dev->name); -#endif + if (!(regs->HostCtrl & RR_INT)) return; - } +#if 0 if (test_and_set_bit(0, (void*)&dev->interrupt) != 0) { printk("%s: Re-entering the interrupt handler.\n", dev->name); return; } +#endif spin_lock_irqsave(&rrpriv->lock, flags); @@ -828,7 +909,9 @@ static void rr_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) spin_unlock_irqrestore(&rrpriv->lock, flags); +#if 0 dev->interrupt = 0; +#endif } @@ -844,7 +927,7 @@ static int rr_open(struct device *dev) regs->HostCtrl |= (HALT_NIC | RR_CLEAR_INT); #endif - if (request_irq(dev->irq, rr_interrupt, 0, rrpriv->name, dev)) + if (request_irq(dev->irq, rr_interrupt, SA_SHIRQ, rrpriv->name, dev)) { printk(KERN_WARNING "%s: Requested IRQ %d is busy\n", dev->name, dev->irq); @@ -858,7 +941,9 @@ static int rr_open(struct device *dev) rr_init1(dev); dev->tbusy = 0; +#if 0 dev->interrupt = 0; +#endif dev->start = 1; MOD_INC_USE_COUNT; @@ -942,6 +1027,12 @@ static int rr_close(struct device *dev) rrpriv = (struct rr_private *)dev->priv; regs = rrpriv->regs; + /* + * Lock to make sure we are not cleaning up while another CPU + * handling interrupts. + */ + spin_lock(&rrpriv->lock); + tmp = regs->HostCtrl; if (tmp & NIC_HALTED){ printk("%s: NIC already halted\n", dev->name); @@ -950,11 +1041,7 @@ static int rr_close(struct device *dev) tmp |= HALT_NIC; regs->HostCtrl = tmp; - /* - * Lock to make sure we are not cleaning up while another CPU - * handling interrupts. - */ - spin_lock(&rrpriv->lock); + rrpriv->fw_running = 0; regs->TxPi = 0; regs->IpRxPi = 0; @@ -1080,9 +1167,6 @@ static int rr_load_firmware(struct device *dev) { struct rr_private *rrpriv; struct rr_regs *regs; -#if 0 - unsigned long flags; -#endif int i, j; u32 localctrl, eptr, sptr, segptr, len, tmp; u32 p2len, p2size, nr_seg, revision, io, sram_size; @@ -1179,30 +1263,117 @@ out: static int rr_ioctl(struct device *dev, struct ifreq *rq, int cmd) { struct rr_private *rrpriv; + unsigned char *image, *oldimage; + unsigned int i; + int error = -EOPNOTSUPP; rrpriv = (struct rr_private *)dev->priv; + spin_lock(&rrpriv->lock); + switch(cmd){ + case SIOCRRGFW: + if (!suser()){ + error = -EPERM; + goto out; + } + + if (rrpriv->fw_running){ + printk("%s: Firmware already running\n", dev->name); + error = -EPERM; + goto out; + } + + image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL); + if (!image){ + printk(KERN_ERR "%s: Unable to allocate memory " + "for EEPROM image\n", dev->name); + error = -ENOMEM; + goto out; + } + i = read_eeprom(rrpriv, 0, image, EEPROM_BYTES); + if (i != EEPROM_BYTES){ + kfree(image); + printk(KERN_ERR "%s: Error reading EEPROM\n", + dev->name); + error = -EFAULT; + goto out; + } + error = copy_to_user(rq->ifr_data, image, EEPROM_BYTES); + if (error) + error = -EFAULT; + kfree(image); + break; case SIOCRRPFW: - if (!suser()) - return -EPERM; + if (!suser()){ + error = -EPERM; + goto out; + } if (rrpriv->fw_running){ - printk("%s: firmware already running\n", dev->name); - return -EPERM; + printk("%s: Firmware already running\n", dev->name); + error = -EPERM; + goto out; } - printk("%s: updating firmware", dev->name); + + image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL); + if (!image){ + printk(KERN_ERR "%s: Unable to allocate memory " + "for EEPROM image\n", dev->name); + error = -ENOMEM; + goto out; + } + + oldimage = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL); + if (!image){ + printk(KERN_ERR "%s: Unable to allocate memory " + "for old EEPROM image\n", dev->name); + error = -ENOMEM; + goto out; + } + + error = copy_from_user(image, rq->ifr_data, EEPROM_BYTES); + if (error) + error = -EFAULT; + + printk("%s: Updating EEPROM firmware\n", dev->name); + + error = write_eeprom(rrpriv, 0, image, EEPROM_BYTES); + if (error) + printk(KERN_ERR "%s: Error writing EEPROM\n", + dev->name); + + i = read_eeprom(rrpriv, 0, oldimage, EEPROM_BYTES); + if (i != EEPROM_BYTES) + printk(KERN_ERR "%s: Error reading back EEPROM " + "image\n", dev->name); + + error = memcmp(image, oldimage, EEPROM_BYTES); + if (error){ + printk(KERN_ERR "%s: Error verifying EEPROM image\n", + dev->name); + error = -EFAULT; + } + + kfree(image); + kfree(oldimage); + break; + case SIOCRRID: + error = put_user(0x52523032, (int *)(&rq->ifr_data[0])); + if (error) + error = -EFAULT; break; default: - return -EOPNOTSUPP; } - return 0; + out: + spin_unlock(&rrpriv->lock); + return error; } /* * Local variables: - * compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -pipe -fomit-frame-pointer -fno-strength-reduce -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2 -DCPU=686 -c rrunner.c" + * compile-command: "gcc -D__SMP__ -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -pipe -fomit-frame-pointer -fno-strength-reduce -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2 -DCPU=686 -c rrunner.c" * End: */ diff --git a/drivers/net/rrunner.h b/drivers/net/rrunner.h index f6e6b3c31f80..d475137007c9 100644 --- a/drivers/net/rrunner.h +++ b/drivers/net/rrunner.h @@ -550,6 +550,7 @@ struct rx_desc{ #define SIOCRRPFW SIOCDEVPRIVATE /* put firmware */ #define SIOCRRGFW SIOCDEVPRIVATE+1 /* get firmware */ +#define SIOCRRID SIOCDEVPRIVATE+2 /* identify */ struct seg_hdr { @@ -560,6 +561,8 @@ struct seg_hdr { #define EEPROM_BASE 0x80000000 +#define EEPROM_WORDS 8192 +#define EEPROM_BYTES (EEPROM_WORDS * sizeof(u32)) struct eeprom_boot { u32 key1; diff --git a/drivers/net/wd.c b/drivers/net/wd.c index 52cc5815a543..99d2318d0ce0 100644 --- a/drivers/net/wd.c +++ b/drivers/net/wd.c @@ -508,7 +508,6 @@ cleanup_module(void) int ioaddr = dev->base_addr - WD_NIC_OFFSET; free_irq(dev->irq, dev); release_region(ioaddr, WD_IO_EXTENT); - dev->priv = NULL; unregister_netdev(dev); kfree(priv); unlock_8390_module(); diff --git a/drivers/pci/oldproc.c b/drivers/pci/oldproc.c index 78e3b33ac224..b52fea887a77 100644 --- a/drivers/pci/oldproc.c +++ b/drivers/pci/oldproc.c @@ -139,7 +139,11 @@ struct pci_dev_info dev_info[] = { DEVICE( MATROX, MATROX_MYS, "Mystique"), DEVICE( MATROX, MATROX_MIL_2, "Millennium II"), DEVICE( MATROX, MATROX_MIL_2_AGP,"Millennium II AGP"), + DEVICE( MATROX, MATROX_G200_PCI,"Matrox G200 PCI"), + DEVICE( MATROX, MATROX_G200_AGP,"Matrox G200 AGP"), DEVICE( MATROX, MATROX_MGA_IMP, "MGA Impression"), + DEVICE( MATROX, MATROX_G100_MM, "Matrox G100 multi monitor"), + DEVICE( MATROX, MATROX_G100_AGP,"Matrox G100 AGP"), DEVICE( CT, CT_65545, "65545"), DEVICE( CT, CT_65548, "65548"), DEVICE( CT, CT_65550, "65550"), @@ -325,6 +329,7 @@ struct pci_dev_info dev_info[] = { DEVICE( VIA, VIA_82C586_0, "VT 82C586 Apollo ISA"), DEVICE( VIA, VIA_82C595, "VT 82C595 Apollo VP2"), DEVICE( VIA, VIA_82C597_0, "VT 82C597 Apollo VP3"), + DEVICE( VIA, VIA_82C598_0, "VT 82C598 Apollo MVP3"), DEVICE( VIA, VIA_82C926, "VT 82C926 Amazon"), DEVICE( VIA, VIA_82C416, "VT 82C416MV"), DEVICE( VIA, VIA_82C595_97, "VT 82C595 Apollo VP2/97"), @@ -332,6 +337,7 @@ struct pci_dev_info dev_info[] = { DEVICE( VIA, VIA_82C586_3, "VT 82C586B Apollo ACPI"), DEVICE( VIA, VIA_86C100A, "VT 86C100A"), DEVICE( VIA, VIA_82C597_1, "VT 82C597 Apollo VP3 AGP"), + DEVICE( VIA, VIA_82C598_1, "VT 82C598 Apollo MVP3 AGP"), DEVICE( VORTEX, VORTEX_GDT60x0, "GDT 60x0"), DEVICE( VORTEX, VORTEX_GDT6000B,"GDT 6000b"), DEVICE( VORTEX, VORTEX_GDT6x10, "GDT 6110/6510"), diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in index a49b16805c40..dc8beb9610c3 100644 --- a/drivers/sound/Config.in +++ b/drivers/sound/Config.in @@ -201,13 +201,14 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then int 'CS4232 MIDI IRQ 5, 7, 9, 11, 12 or 15' CONFIG_CS4232_MPU_IRQ 9 fi - dep_tristate 'Support for Yamaha OPL3-SA[2,3,x] based (PnP) cards' CONFIG_SOUND_OPL3SA2 $CONFIG_SOUND_OSS + dep_tristate 'Support for Yamaha OPL3-SA2, SA3, and SAx based PnP cards' CONFIG_SOUND_OPL3SA2 $CONFIG_SOUND_OSS if [ "$CONFIG_SOUND_OPL3SA2" = "y" ]; then - hex 'OPL3SA2 audio I/O base 530, 604, E80 or F40' CONFIG_OPL3SA2_BASE 530 - int 'OPL3SA2 audio IRQ 5, 7, 9, 11, 12 or 15' CONFIG_OPL3SA2_IRQ 11 + hex 'OPL3SA2 audio I/O base (530 - F48 valid)' CONFIG_OPL3SA2_BASE 530 + int 'OPL3SA2 audio IRQ 5, 7, 9, 11, 12 or 15' CONFIG_OPL3SA2_IRQ 9 int 'OPL3SA2 audio DMA 0, 1 or 3' CONFIG_OPL3SA2_DMA 0 int 'OPL3SA2 second (duplex) DMA 0, 1 or 3' CONFIG_OPL3SA2_DMA2 1 - hex 'OPL3SA2 MIDI I/O base 330, 370, 3B0 or 3F0' CONFIG_OPL3SA2_MPU_BASE 330 + hex 'OPL3SA2 control I/O base (100 - FFE valid)' CONFIG_OPL3SA2_CTRL_BASE 370 + hex 'OPL3SA2 MIDI I/O base (300 - 334 valid)' CONFIG_OPL3SA2_MPU_BASE 330 int 'OPL3SA2 MIDI IRQ 5, 7, 9, 11, 12 or 15' CONFIG_OPL3SA2_MPU_IRQ 9 fi diff --git a/drivers/sound/dmasound.c b/drivers/sound/dmasound.c index aaf21e2bad40..5fa5910dedbe 100644 --- a/drivers/sound/dmasound.c +++ b/drivers/sound/dmasound.c @@ -90,7 +90,7 @@ History: #include #include -#ifdef __mc68000__ +#if defined(__mc68000__) || defined(CONFIG_APUS) #include #endif #include @@ -686,9 +686,9 @@ static struct sound_settings sound; #ifdef CONFIG_ATARI -static void *AtaAlloc(unsigned int size, int flags) __init; -static void AtaFree(void *, unsigned int size) __init; -static int AtaIrqInit(void) __init; +static void *AtaAlloc(unsigned int size, int flags); +static void AtaFree(void *, unsigned int size); +static int AtaIrqInit(void); #ifdef MODULE static void AtaIrqCleanUp(void); #endif /* MODULE */ @@ -709,9 +709,9 @@ static void ata_sq_interrupt(int irq, void *dummy, struct pt_regs *fp); #endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA -static void *AmiAlloc(unsigned int size, int flags) __init; -static void AmiFree(void *, unsigned int) __init; -static int AmiIrqInit(void) __init; +static void *AmiAlloc(unsigned int size, int flags); +static void AmiFree(void *, unsigned int); +static int AmiIrqInit(void); #ifdef MODULE static void AmiIrqCleanUp(void); #endif /* MODULE */ @@ -726,9 +726,9 @@ static void ami_sq_interrupt(int irq, void *dummy, struct pt_regs *fp); #endif /* CONFIG_AMIGA */ #ifdef CONFIG_PPC -static void *PMacAlloc(unsigned int size, int flags) __init; -static void PMacFree(void *ptr, unsigned int size) __init; -static int PMacIrqInit(void) __init; +static void *PMacAlloc(unsigned int size, int flags); +static void PMacFree(void *ptr, unsigned int size); +static int PMacIrqInit(void); #ifdef MODULE static void PMacIrqCleanup(void); #endif /* MODULE */ @@ -2223,7 +2223,7 @@ static void AtaFree(void *obj, unsigned int size) atari_stram_free( obj ); } -static int AtaIrqInit(void) +static int __init AtaIrqInit(void) { /* Set up timer A. Timer A will receive a signal upon end of playing from the sound @@ -2720,7 +2720,7 @@ static void AmiFree(void *obj, unsigned int size) amiga_chip_free (obj); } -static int AmiIrqInit(void) +static int __init AmiIrqInit(void) { /* turn off DMA for audio channels */ custom.dmacon = AMI_AUDIO_OFF; @@ -2988,7 +2988,7 @@ static void PMacFree(void *ptr, unsigned int size) kfree(ptr); } -static int PMacIrqInit(void) +static int __init PMacIrqInit(void) { if (request_irq(awacs_irq, pmac_awacs_intr, 0, "AWACS", 0) || request_irq(awacs_tx_irq, pmac_awacs_tx_intr, 0, "AWACS out", 0)) @@ -3850,7 +3850,7 @@ static struct file_operations mixer_fops = }; -__initfunc(static void mixer_init(void)) +static void __init mixer_init(void) { #ifndef MODULE int mixer_unit; @@ -3898,6 +3898,42 @@ __initfunc(static void mixer_init(void)) */ +static int sq_allocate_buffers(void) +{ + int i; + + if (sound_buffers) + return 0; + sound_buffers = kmalloc (numBufs * sizeof(char *), GFP_KERNEL); + if (!sound_buffers) + return -ENOMEM; + for (i = 0; i < numBufs; i++) { + sound_buffers[i] = sound.mach.dma_alloc (bufSize << 10, GFP_KERNEL); + if (!sound_buffers[i]) { + while (i--) + sound.mach.dma_free (sound_buffers[i], bufSize << 10); + kfree (sound_buffers); + sound_buffers = 0; + return -ENOMEM; + } + } + return 0; +} + + +static void sq_release_buffers(void) +{ + int i; + + if (sound_buffers) { + for (i = 0; i < numBufs; i++) + sound.mach.dma_free (sound_buffers[i], bufSize << 10); + kfree (sound_buffers); + sound_buffers = 0; + } +} + + static void sq_setup(int numBufs, int bufSize, char **buffers) { #ifdef CONFIG_PPC @@ -3913,7 +3949,6 @@ static void sq_setup(int numBufs, int bufSize, char **buffers) sq.front = sq.count = 0; sq.rear = -1; sq.write_queue = sq.open_queue = sq.sync_queue = 0; - sq.busy = 0; sq.syncing = 0; sq.playing = 0; @@ -4033,9 +4068,12 @@ static int sq_open(struct inode *inode, struct file *file) } rc = 0; } + sq.busy = 1; + rc = sq_allocate_buffers(); + if (rc) + goto err_out_nobusy; sq_setup(numBufs, bufSize << 10, sound_buffers); sq.open_mode = file->f_flags; - sq.busy = 1; #ifdef CONFIG_ATARI sq.ignore_int = 1; #endif /* CONFIG_ATARI */ @@ -4049,6 +4087,9 @@ static int sq_open(struct inode *inode, struct file *file) sound_set_format(AFMT_MU_LAW); } return 0; +err_out_nobusy: + sq.busy = 0; + WAKE_UP(sq.open_queue); err_out: MOD_DEC_USE_COUNT; return rc; @@ -4101,8 +4142,10 @@ static int sq_release(struct inode *inode, struct file *file) sound.soft = sound.dsp; sound.hard = sound.dsp; sound_silence(); - if (rc == 0) + if (rc == 0) { + sq_release_buffers(); MOD_DEC_USE_COUNT; + } return rc; } @@ -4212,7 +4255,7 @@ static struct file_operations sq_fops = }; -__initfunc(static void sq_init(void)) +static void __init sq_init(void) { #ifndef MODULE int sq_unit; @@ -4407,7 +4450,7 @@ static struct file_operations state_fops = }; -__initfunc(static void state_init(void)) +static void __init state_init(void) { #ifndef MODULE int state_unit; @@ -4430,15 +4473,14 @@ static long long sound_lseek(struct file *file, long long offset, int orig) /*** Config & Setup **********************************************************/ -__initfunc(void dmasound_init(void)) +void __init dmasound_init(void) { int has_sound = 0; - int i; #ifdef CONFIG_PPC struct device_node *np; #endif -#ifdef __mc68000__ +#if defined(__mc68000__) || defined(CONFIG_APUS) switch (m68k_machtype) { #ifdef CONFIG_ATARI case MACH_ATARI: @@ -4466,7 +4508,7 @@ __initfunc(void dmasound_init(void)) break; #endif /* CONFIG_AMIGA */ } -#endif /* __mc68000__ */ +#endif /* __mc68000__||CONFIG_APUS */ #ifdef CONFIG_PPC awacs_subframe = 0; @@ -4501,8 +4543,10 @@ __initfunc(void dmasound_init(void)) awacs_rx_irq = np->intrs[2].line; awacs_tx_cmd_space = kmalloc((numBufs + 4) * sizeof(struct dbdma_cmd), GFP_KERNEL); - if (awacs_tx_cmd_space == NULL) - goto out_of_memory; + if (awacs_tx_cmd_space == NULL) { + printk("DMA sound driver: Not enough buffer memory, driver disabled!\n"); + return; + } awacs_tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(awacs_tx_cmd_space); awacs_reg[0] = MASK_MUX_CD; @@ -4543,24 +4587,6 @@ __initfunc(void dmasound_init(void)) return; /* Set up sound queue, /dev/audio and /dev/dsp. */ - sound_buffers = kmalloc (numBufs * sizeof(char *), GFP_KERNEL); - if (!sound_buffers) { - out_of_memory: - printk("DMA sound driver: Not enough buffer memory, driver disabled!\n"); - return; - } - for (i = 0; i < numBufs; i++) { - sound_buffers[i] = sound.mach.dma_alloc (bufSize << 10, GFP_KERNEL); - if (!sound_buffers[i]) { - while (i--) - sound.mach.dma_free (sound_buffers[i], bufSize << 10); - kfree (sound_buffers); - sound_buffers = 0; - goto out_of_memory; - } - } - - sq_setup(numBufs, bufSize << 10, sound_buffers); /* Set default settings. */ sq_init(); @@ -4588,7 +4614,7 @@ __initfunc(void dmasound_init(void)) #define MAXARGS 8 /* Should be sufficient for now */ -__initfunc(void dmasound_setup(char *str, int *ints)) +void __init dmasound_setup(char *str, int *ints) { /* check the bootstrap parameter for "dmasound=" */ @@ -4628,18 +4654,12 @@ int init_module(void) void cleanup_module(void) { - int i; - if (irq_installed) { sound_silence(); sound.mach.irqcleanup(); } - if (sound_buffers) { - for (i = 0; i < numBufs; i++) - sound.mach.dma_free(sound_buffers[i], bufSize << 10); - kfree(sound_buffers); - } + sq_release_buffers(); if (mixer_unit >= 0) unregister_sound_mixer(mixer_unit); diff --git a/drivers/sound/es1370.c b/drivers/sound/es1370.c index d644e8bc1ddd..7471afcc3010 100644 --- a/drivers/sound/es1370.c +++ b/drivers/sound/es1370.c @@ -79,6 +79,7 @@ * 31.08.98 0.13 Fix realplayer problems - dac.count issues * 08.10.98 0.14 Joystick support fixed * -- Oliver Neukum + * 10.12.98 0.15 Fix drain_dac trying to wait on not yet initialized DMA * * some important things missing in Ensoniq documentation: * @@ -998,7 +999,7 @@ static int drain_dac1(struct es1370_state *s, int nonblock) unsigned long flags; int count, tmo; - if (s->dma_dac1.mapped) + if (s->dma_dac1.mapped || !s->dma_dac1.ready) return 0; current->state = TASK_INTERRUPTIBLE; add_wait_queue(&s->dma_dac1.wait, &wait); @@ -1033,7 +1034,7 @@ static int drain_dac2(struct es1370_state *s, int nonblock) unsigned long flags; int count, tmo; - if (s->dma_dac2.mapped) + if (s->dma_dac2.mapped || !s->dma_dac2.ready) return 0; current->state = TASK_INTERRUPTIBLE; add_wait_queue(&s->dma_dac2.wait, &wait); @@ -2276,7 +2277,7 @@ __initfunc(int init_es1370(void)) if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "es1370: version v0.13 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "es1370: version v0.15 time " __TIME__ " " __DATE__ "\n"); while (index < NR_DEVICE && (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) { if (pcidev->base_address[0] == 0 || diff --git a/drivers/sound/es1371.c b/drivers/sound/es1371.c index a6e8a9d92f6c..3a4ceb8c9ca6 100644 --- a/drivers/sound/es1371.c +++ b/drivers/sound/es1371.c @@ -49,6 +49,7 @@ * 31.08.98 0.4 Fix realplayer problems - dac.count issues * 27.10.98 0.5 Fix joystick support * -- Oliver Neukum (c188@org.chemie.uni-muenchen.de) + * 10.12.98 0.6 Fix drain_dac trying to wait on not yet initialized DMA * */ @@ -1444,7 +1445,7 @@ static int drain_dac1(struct es1371_state *s, int nonblock) unsigned long flags; int count, tmo; - if (s->dma_dac1.mapped) + if (s->dma_dac1.mapped || !s->dma_dac1.ready) return 0; current->state = TASK_INTERRUPTIBLE; add_wait_queue(&s->dma_dac1.wait, &wait); @@ -1479,7 +1480,7 @@ static int drain_dac2(struct es1371_state *s, int nonblock) unsigned long flags; int count, tmo; - if (s->dma_dac2.mapped) + if (s->dma_dac2.mapped || !s->dma_dac2.ready) return 0; current->state = TASK_INTERRUPTIBLE; add_wait_queue(&s->dma_dac2.wait, &wait); @@ -2715,7 +2716,7 @@ __initfunc(int init_es1371(void)) if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "es1371: version v0.4 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "es1371: version v0.6 time " __TIME__ " " __DATE__ "\n"); while (index < NR_DEVICE && (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, pcidev))) { if (pcidev->base_address[0] == 0 || diff --git a/drivers/sound/opl3sa2.c b/drivers/sound/opl3sa2.c index 05823f689ed2..d2237ffe04e8 100644 --- a/drivers/sound/opl3sa2.c +++ b/drivers/sound/opl3sa2.c @@ -1,23 +1,32 @@ /* * sound/opl3sa2.c * - * A low level driver for Yamaha OPL3-SA[2,3,x] based cards. + * A low level driver for Yamaha OPL3-SA2 and SA3 cards. + * SAx cards should work, as they are just variants of the SA3. * - * Scott Murray, Jun 14, 1998 + * Copyright 1998 Scott Murray * + * Originally based on the CS4232 driver (in cs4232.c) by Hannu Savolainen + * and others. Now incorporates code/ideas from pss.c, also by Hannu + * Savolainen. Both of those files are distributed with the following + * license: * - * Changes - * Paul J.Y. Lahaie Changed probing / attach code order + * "Copyright (C) by Hannu Savolainen 1993-1997 * - */ - -/* Based on the CS4232 driver: + * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) + * Version 2 (June 1991). See the "COPYING" file distributed with this software + * for more info." * - * Copyright (C) by Hannu Savolainen 1993-1997 + * As such, in accordance with the above license, this file, opl3sa2.c, is + * distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2 (June 1991). + * See the "COPYING" file distributed with this software for more information. + * + * Change History + * -------------- + * Scott Murray Original driver (Jun 14, 1998) + * Paul J.Y. Lahaie Changed probing / attach code order + * Scott Murray Added mixer support (Dec 03, 1998) * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. */ #include @@ -26,8 +35,369 @@ #include "sound_config.h" #include "soundmodule.h" +/* Useful control port indexes: */ +#define OPL3SA2_MASTER_LEFT 0x07 +#define OPL3SA2_MASTER_RIGHT 0x08 +#define OPL3SA2_MIC 0x09 +#define OPL3SA2_MISC 0x0A + +#define OPL3SA3_WIDE 0x14 +#define OPL3SA3_BASS 0x15 +#define OPL3SA3_TREBLE 0x16 + +/* Useful constants: */ +#define DEFAULT_VOLUME 50 +#define DEFAULT_MIC 50 +#define DEFAULT_TIMBRE 0 + +#define CHIPSET_UNKNOWN -1 +#define CHIPSET_OPL3SA2 1 +#define CHIPSET_OPL3SA3 2 +#define CHIPSET_OPL3SAX 4 + + #ifdef CONFIG_OPL3SA2 +/* What's my version? */ +static int chipset_version = CHIPSET_UNKNOWN; + +/* Oh well, let's just cache the name */ +static char chipset_name[16]; + +/* Where's my mixer */ +static int opl3sa2_mixer = -1; + +/* Bag o' mixer data */ +typedef struct opl3sa2_mixerdata { + unsigned short cfg_port; + unsigned short padding; + int ad_mixer_dev; + unsigned int volume_l; + unsigned int volume_r; + unsigned int mic; + unsigned int bass; + unsigned int treble; +} opl3sa2_mixerdata; + +#ifdef CONFIG_OPL3SA2_CTRL_BASE +/* Set control port if compiled into the kernel */ +static opl3sa2_mixerdata opl3sa2_data = { CONFIG_OPL3SA2_CTRL_BASE, }; +#else +static opl3sa2_mixerdata opl3sa2_data; +#endif + +static opl3sa2_mixerdata *devc = &opl3sa2_data; + + +/* Standard read and write functions */ + +static void opl3sa2_write(unsigned short port, + unsigned char index, + unsigned char data) +{ + outb_p(index, port); + outb(data, port + 1); +} + + +static void opl3sa2_read(unsigned short port, + unsigned char index, + unsigned char* data) +{ + outb_p(index, port); + *data = inb(port + 1); +} + + +/* All of the mixer functions... */ + +static void opl3sa2_set_volume(opl3sa2_mixerdata *devc, int left, int right) +{ + static unsigned char scale[101] = { + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00 + }; + unsigned char vol; + + vol = scale[left]; + + /* If level is zero, turn on mute */ + if(!left) + vol |= 0x80; + + opl3sa2_write(devc->cfg_port, OPL3SA2_MASTER_LEFT, vol); + + vol = scale[right]; + + /* If level is zero, turn on mute */ + if(!right) + vol |= 0x80; + + opl3sa2_write(devc->cfg_port, OPL3SA2_MASTER_RIGHT, vol); +} + + +static void opl3sa2_set_mic(opl3sa2_mixerdata *devc, int level) +{ + unsigned char vol = 0x1F; + + if((level >= 0) && (level <= 100)) + vol = 0x1F - (unsigned char) (0x1F * level / 100L); + + /* If level is zero, turn on mute */ + if(!level) + vol |= 0x80; + + opl3sa2_write(devc->cfg_port, OPL3SA2_MIC, vol); +} + + +static void opl3sa3_set_bass(opl3sa2_mixerdata *devc, int level) +{ + unsigned char bass; + + bass = level ? ((unsigned char) (0x07 * level / 100L)) : 0; + bass |= (bass << 4); + + opl3sa2_write(devc->cfg_port, OPL3SA3_BASS, bass); +} + + +static void opl3sa3_set_treble(opl3sa2_mixerdata *devc, int level) +{ + unsigned char treble; + + treble = level ? ((unsigned char) (0x07 * level / 100L)) : 0; + treble |= (treble << 4); + + opl3sa2_write(devc->cfg_port, OPL3SA3_TREBLE, treble); +} + + +static void opl3sa2_mixer_reset(opl3sa2_mixerdata *devc) +{ + if(devc) + { + opl3sa2_set_volume(devc, DEFAULT_VOLUME, DEFAULT_VOLUME); + devc->volume_l = devc->volume_r = DEFAULT_VOLUME; + + opl3sa2_set_mic(devc, DEFAULT_MIC); + devc->mic = DEFAULT_MIC; + + opl3sa3_set_bass(devc, DEFAULT_TIMBRE); + opl3sa3_set_treble(devc, DEFAULT_TIMBRE); + devc->bass = devc->treble = DEFAULT_TIMBRE; + } +} + + +static void arg_to_volume_mono(unsigned int volume, int *aleft) +{ + int left; + + left = volume & 0x00ff; + if (left > 100) + left = 100; + *aleft = left; +} + + +static void arg_to_volume_stereo(unsigned int volume, int *aleft, int *aright) +{ + arg_to_volume_mono(volume, aleft); + arg_to_volume_mono(volume >> 8, aright); +} + + +static int ret_vol_mono(int left) +{ + return ((left << 8) | left); +} + + +static int ret_vol_stereo(int left, int right) +{ + return ((right << 8) | left); +} + + +static int call_ad_mixer(opl3sa2_mixerdata *devc, unsigned int cmd, caddr_t arg) +{ + if(devc->ad_mixer_dev != -1) + return mixer_devs[devc->ad_mixer_dev]->ioctl(devc->ad_mixer_dev, + cmd, + arg); + else + return -EINVAL; +} + + +static int opl3sa2_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg) +{ + int cmdf = cmd & 0xff; + + opl3sa2_mixerdata* devc = (opl3sa2_mixerdata*) mixer_devs[dev]->devc; + + switch(cmdf) + { + case SOUND_MIXER_VOLUME: + case SOUND_MIXER_MIC: + case SOUND_MIXER_BASS: + case SOUND_MIXER_TREBLE: + case SOUND_MIXER_DEVMASK: + case SOUND_MIXER_STEREODEVS: + case SOUND_MIXER_RECMASK: + case SOUND_MIXER_CAPS: + case SOUND_MIXER_RECSRC: + break; + + default: + return call_ad_mixer(devc, cmd, arg); + } + + if(((cmd >> 8) & 0xff) != 'M') + return -EINVAL; + + if(_SIOC_DIR (cmd) & _SIOC_WRITE) + { + switch (cmdf) + { + case SOUND_MIXER_RECSRC: + if(devc->ad_mixer_dev != -1) + return call_ad_mixer(devc, cmd, arg); + else + { + if(*(int *)arg != 0) + return -EINVAL; + return 0; + } + + case SOUND_MIXER_VOLUME: + arg_to_volume_stereo(*(unsigned int *)arg, + &devc->volume_l, + &devc->volume_r); + opl3sa2_set_volume(devc, devc->volume_l, + devc->volume_r); + return ret_vol_stereo(devc->volume_l, + devc->volume_r); + + case SOUND_MIXER_MIC: + arg_to_volume_mono(*(unsigned int *)arg, + &devc->mic); + opl3sa2_set_mic(devc, devc->mic); + return ret_vol_mono(devc->mic); + + case SOUND_MIXER_BASS: + if(chipset_version != CHIPSET_OPL3SA2) + { + arg_to_volume_mono(*(unsigned int *)arg, + &devc->bass); + opl3sa3_set_bass(devc, devc->bass); + return ret_vol_mono(devc->bass); + } + return -EINVAL; + + case SOUND_MIXER_TREBLE: + if(chipset_version != CHIPSET_OPL3SA2) + { + arg_to_volume_mono(*(unsigned int *)arg, + &devc->treble); + opl3sa3_set_treble(devc, devc->treble); + return ret_vol_mono(devc->treble); + } + return -EINVAL; + + default: + return -EINVAL; + } + } + else + { + /* + * Return parameters + */ + switch (cmdf) + { + case SOUND_MIXER_DEVMASK: + if(call_ad_mixer(devc, cmd, arg) == -EINVAL) + *(int*)arg = 0; /* no mixer devices */ + + if(chipset_version != CHIPSET_OPL3SA2) + return (*(int*)arg |= SOUND_MASK_VOLUME | + SOUND_MASK_MIC | + SOUND_MASK_BASS | + SOUND_MASK_TREBLE); + /* OPL3-SA2 has no bass and treble mixers */ + return (*(int*)arg |= SOUND_MASK_VOLUME | + SOUND_MASK_MIC); + + case SOUND_MIXER_STEREODEVS: + if(call_ad_mixer(devc, cmd, arg) == -EINVAL) + *(int*)arg = 0; /* no stereo devices */ + return (*(int*)arg |= SOUND_MASK_VOLUME); + + case SOUND_MIXER_RECMASK: + if(devc->ad_mixer_dev != -1) + return call_ad_mixer(devc, cmd, arg); + else + return (*(int*)arg = 0); /* no record devices */ + + case SOUND_MIXER_CAPS: + if(devc->ad_mixer_dev != -1) + return call_ad_mixer(devc, cmd, arg); + else + return (*(int*)arg = SOUND_CAP_EXCL_INPUT); + + case SOUND_MIXER_RECSRC: + if(devc->ad_mixer_dev != -1) + return call_ad_mixer(devc, cmd, arg); + else + return (*(int*)arg = 0); /* no record source */ + + case SOUND_MIXER_VOLUME: + return (*(int*)arg = ret_vol_stereo(devc->volume_l, + devc->volume_r)); + + case SOUND_MIXER_MIC: + return (*(int*)arg = ret_vol_mono(devc->mic)); + + case SOUND_MIXER_BASS: + if(chipset_version != CHIPSET_OPL3SA2) + return (*(int*)arg = ret_vol_mono(devc->bass)); + return -EINVAL; + + + case SOUND_MIXER_TREBLE: + if(chipset_version != CHIPSET_OPL3SA2) + return (*(int*)arg = ret_vol_mono(devc->treble)); + return -EINVAL; + + default: + return -EINVAL; + } + } +} + + +static struct mixer_operations opl3sa2_mixer_operations = +{ + "Yamaha", + "", + opl3sa2_mixer_ioctl +}; + +/* End of mixer-related stuff */ + + int probe_opl3sa2_mpu(struct address_info *hw_config) { #if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) @@ -54,82 +424,126 @@ void unload_opl3sa2_mpu(struct address_info *hw_config) } -int probe_opl3sa2_mss(struct address_info *hw_config) +static int probe_opl3sa2_mss(struct address_info *hw_config) { return probe_ms_sound(hw_config); } -void attach_opl3sa2_mss(struct address_info *hw_config) +static void attach_opl3sa2_mss(struct address_info *hw_config) { - printk(KERN_INFO "opl3sa2.c: trying to init WSS\n"); - - attach_ms_sound(hw_config); + char mixer_name[64]; + + /* Create pretty names for mixer stuff */ + strncpy(mixer_name, chipset_name, 16); + strncat(mixer_name, " and AD1848 (through MSS)", 64); + + strncpy(opl3sa2_mixer_operations.name, chipset_name, 16); + strncat(opl3sa2_mixer_operations.name, "-AD1848", 64); + + /* Install master mixer */ + devc->ad_mixer_dev = -1; + if((opl3sa2_mixer = sound_install_mixer(MIXER_DRIVER_VERSION, + mixer_name, + &opl3sa2_mixer_operations, + sizeof(struct mixer_operations), + devc)) < 0) + { + printk(KERN_ERR "Could not install %s master mixer\n", chipset_name); + return; + } - /* request_region(hw_config->io_base, 4, "Yamaha 7xx WSS Config"); */ - - if (hw_config->slots[0] != -1 && - audio_devs[hw_config->slots[0]]->mixer_dev != -1) + opl3sa2_mixer_reset(devc); + + attach_ms_sound(hw_config); /* Slot 0 */ + if(hw_config->slots[0] != -1) { - AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD); - AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH); - /* GSM! test the following: */ - AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE); + /* Did the MSS driver install? */ + if(num_mixers == (opl3sa2_mixer + 2)) + { + /* The MSS mixer is installed */ + devc->ad_mixer_dev = audio_devs[hw_config->slots[0]]->mixer_dev; + + /* Reroute mixers appropiately */ + AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD); + AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH); + AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE); + } } } -void unload_opl3sa2_mss(struct address_info *hw_config) +static void unload_opl3sa2_mss(struct address_info *hw_config) { - int mixer; - - /* Find mixer */ - mixer = audio_devs[hw_config->slots[0]]->mixer_dev; - - /* Unload MSS audio codec */ unload_ms_sound(hw_config); - - sound_unload_audiodev(hw_config->slots[0]); - - /* Unload mixer if there */ - if(mixer >= 0) - { - sound_unload_mixerdev(mixer); - } - - /* Release MSS config ports */ - release_region(hw_config->io_base, 4); } int probe_opl3sa2(struct address_info *hw_config) { + char tag; + /* * Verify that the I/O port range is free. */ - - printk(KERN_INFO "opl3sa2.c: Control using I/O port 0x%03x\n", hw_config->io_base); - - if (check_region(hw_config->io_base, 2)) + if(check_region(hw_config->io_base, 2)) { - printk(KERN_ERR "opl3sa2.c: Control I/O port 0x%03x not free\n", hw_config->io_base); + printk(KERN_ERR + "opl3sa2.c: Control I/O port 0x%03x not free\n", + hw_config->io_base); return 0; } - /* GSM!: Add some kind of other test here... */ + /* + * Look at chipset version in lower 3 bits of index 0x0A, miscellaneous + */ + chipset_version = 0; + opl3sa2_read(hw_config->io_base, + OPL3SA2_MISC, + (unsigned char*) &chipset_version); + chipset_version &= 0x0007; + switch(chipset_version) + { + case CHIPSET_OPL3SA2: + printk(KERN_INFO "Found OPL3-SA2 (YMF711)\n"); + tag = '2'; + break; + + case CHIPSET_OPL3SA3: + printk(KERN_INFO "Found OPL3-SA3 (YMF715)\n"); + tag = '3'; + break; + + case CHIPSET_OPL3SAX: + printk(KERN_INFO "Found OPL3-SAx (YMF719)\n"); + tag = 'x'; + break; + + default: + printk(KERN_ERR "No Yamaha audio controller found\n"); + printk(KERN_INFO + "opl3sa2.c: chipset version = %x\n", + chipset_version); + chipset_version = CHIPSET_UNKNOWN; + tag = '?'; + break; + } - return 1; + if(chipset_version != CHIPSET_UNKNOWN) { + /* Generate a pretty name */ + sprintf(chipset_name, "OPL3-SA%c", tag); + return 1; + } + return 0; } void attach_opl3sa2(struct address_info *hw_config) { - printk(KERN_INFO "opl3sa2.c: trying to init!\n"); - - request_region(hw_config->io_base, 2, "Yamaha 7xx Control"); + request_region(hw_config->io_base, 2, chipset_name); - /* GSM! Mixer stuff should go here... */ -} + devc->cfg_port = hw_config->io_base; +} void unload_opl3sa2(struct address_info *hw_config) @@ -137,7 +551,9 @@ void unload_opl3sa2(struct address_info *hw_config) /* Release control ports */ release_region(hw_config->io_base, 2); - /* GSM! Mixer stuff should go here... */ + /* Unload mixer */ + if(opl3sa2_mixer >= 0) + sound_unload_mixerdev(opl3sa2_mixer); } @@ -150,12 +566,26 @@ int irq = -1; int dma = -1; int dma2 = -1; -MODULE_PARM(io,"i"); -MODULE_PARM(mss_io,"i"); -MODULE_PARM(mpu_io,"i"); -MODULE_PARM(irq,"i"); -MODULE_PARM(dma,"i"); +MODULE_PARM(io, "i"); +MODULE_PARM_DESC(io, "Set i/o base of OPL3-SA2 or SA3 card (usually 0x370)"); + +MODULE_PARM(mss_io, "i"); +MODULE_PARM_DESC(mss_io, "Set MSS (audio) I/O base (0x530, 0xE80, or other. Address must end in 0 or 4 and must be from 0x530 to 0xF48)"); + +MODULE_PARM(mpu_io, "i"); +MODULE_PARM_DESC(mpu_io, "Set MIDI I/O base (0x330 or other. Address must be on 4 location boundaries and must be from 0x300 to 0x334)"); + +MODULE_PARM(irq, "i"); +MODULE_PARM_DESC(mss_irq, "Set MSS (audio) IRQ (5, 7, 9, 10, 11, 12)"); + +MODULE_PARM(dma, "i"); +MODULE_PARM_DESC(dma, "Set MSS (audio) first DMA channel (0, 1, 3)"); + MODULE_PARM(dma2,"i"); +MODULE_PARM_DESC(dma2, "Set MSS (audio) second DMA channel (0, 1, 3)"); + +MODULE_DESCRIPTION("Module for OPL3-SA2 and SA3 sound cards (uses AD1848 MSS driver)."); +MODULE_AUTHOR("Scott Murray "); EXPORT_NO_SYMBOLS; @@ -163,17 +593,19 @@ struct address_info cfg; struct address_info mss_cfg; struct address_info mpu_cfg; + /* - * Install a OPL3SA2 based card. Need to have ad1848 and mpu401 - * loaded ready. + * Install a OPL3SA2 based card. + * + * Need to have ad1848 and mpu401 loaded ready. */ int init_module(void) { int i; - if (io == -1 || irq == -1 || dma == -1 || dma2 == -1 || mss_io == -1) + if(io == -1 || irq == -1 || dma == -1 || dma2 == -1 || mss_io == -1) { - printk(KERN_ERR "opl3sa2: io, mss_io, irq, dma, and dma2 must be set.\n"); + printk(KERN_ERR "opl3sa2.c: io, mss_io, irq, dma, and dma2 must be set.\n"); return -EINVAL; } @@ -193,21 +625,20 @@ int init_module(void) /* Call me paranoid: */ for(i = 0; i < 6; i++) { - cfg.slots[i] = mss_cfg.slots[i] = mpu_cfg.slots[i] = -1; + cfg.slots[i] = mss_cfg.slots[i] = mpu_cfg.slots[i] = -1; } - if (probe_opl3sa2(&cfg) == 0) + if(probe_opl3sa2(&cfg) == 0) { - return -ENODEV; + return -ENODEV; } - if (probe_opl3sa2_mss(&mss_cfg) == 0) - { - return -ENODEV; - } + if(probe_opl3sa2_mss(&mss_cfg) == 0) + { + return -ENODEV; + } attach_opl3sa2(&cfg); - attach_opl3sa2_mss(&mss_cfg); #if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) @@ -219,9 +650,9 @@ int init_module(void) mpu_cfg.dma = dma; mpu_cfg.always_detect = 1; /* It's there, so use shared IRQs */ - if (probe_opl3sa2_mpu(&mpu_cfg)) + if(probe_opl3sa2_mpu(&mpu_cfg)) { - attach_opl3sa2_mpu(&mpu_cfg); + attach_opl3sa2_mpu(&mpu_cfg); } } #endif @@ -235,7 +666,7 @@ void cleanup_module(void) #if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) if(mpu_cfg.slots[1] != -1) { - unload_opl3sa2_mpu(&mpu_cfg); + unload_opl3sa2_mpu(&mpu_cfg); } #endif unload_opl3sa2_mss(&mss_cfg); @@ -243,5 +674,5 @@ void cleanup_module(void) SOUND_LOCK_END; } -#endif -#endif +#endif /* MODULE */ +#endif /* CONFIG_OPL3SA2 */ diff --git a/drivers/sound/sonicvibes.c b/drivers/sound/sonicvibes.c index b57cd186a7d9..20d273eeaa50 100644 --- a/drivers/sound/sonicvibes.c +++ b/drivers/sound/sonicvibes.c @@ -47,6 +47,7 @@ * Now mixer behaviour can basically be selected between * "OSS documented" and "OSS actual" behaviour * 31.08.98 0.7 Fix realplayer problems - dac.count issues + * 10.12.98 0.8 Fix drain_dac trying to wait on not yet initialized DMA * */ @@ -1226,7 +1227,7 @@ static int drain_dac(struct sv_state *s, int nonblock) unsigned long flags; int count, tmo; - if (s->dma_dac.mapped) + if (s->dma_dac.mapped || !s->dma_dac.ready) return 0; current->state = TASK_INTERRUPTIBLE; add_wait_queue(&s->dma_dac.wait, &wait); @@ -2277,7 +2278,7 @@ __initfunc(int init_sonicvibes(void)) if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "sv: version v0.7 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "sv: version v0.8 time " __TIME__ " " __DATE__ "\n"); #if 0 if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT))) printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n"); diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c index 8461645fbe22..1f791efef88f 100644 --- a/fs/autofs/inode.c +++ b/fs/autofs/inode.c @@ -300,8 +300,11 @@ static void autofs_read_inode(struct inode *inode) struct autofs_sb_info *sbi = (struct autofs_sb_info *) inode->i_sb->u.generic_sbp; + /* Initialize to the default case (stub directory) */ + inode->i_op = NULL; - inode->i_mode = 0; + inode->i_op = &autofs_dir_inode_operations; + inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO; inode->i_nlink = 2; inode->i_size = 0; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; @@ -324,7 +327,7 @@ static void autofs_read_inode(struct inode *inode) n = ino - AUTOFS_FIRST_SYMLINK; if ( n >= AUTOFS_MAX_SYMLINKS || !test_bit(n,sbi->symlink_bitmap)) { - printk("autofs: Looking for bad symlink inode 0x%08x\n", (unsigned int) ino); + printk("autofs: Looking for bad symlink inode %u\n", (unsigned int) ino); return; } @@ -335,10 +338,6 @@ static void autofs_read_inode(struct inode *inode) inode->i_mtime = inode->i_ctime = sl->mtime; inode->i_size = sl->len; inode->i_nlink = 1; - } else { - /* All non-root directory inodes look the same */ - inode->i_op = &autofs_dir_inode_operations; - inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO; } } diff --git a/fs/autofs/root.c b/fs/autofs/root.c index a3d41fb33db1..5d40e22c12f2 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c @@ -223,7 +223,8 @@ static int autofs_root_lookup(struct inode *dir, struct dentry * dentry) sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp; oz_mode = autofs_oz_mode(sbi); - DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d\n", current->pid, current->pgrp, sbi->catatonic, oz_mode)); + DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d\n", + current->pid, current->pgrp, sbi->catatonic, oz_mode)); /* * Mark the dentry incomplete, but add it. This is needed so @@ -395,6 +396,7 @@ static int autofs_root_mkdir(struct inode *dir, struct dentry *dentry, int mode) struct autofs_sb_info *sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp; struct autofs_dirhash *dh = &sbi->dirhash; struct autofs_dir_ent *ent; + ino_t ino; if ( !autofs_oz_mode(sbi) ) return -EPERM; @@ -407,6 +409,7 @@ static int autofs_root_mkdir(struct inode *dir, struct dentry *dentry, int mode) printk("autofs: Out of inode numbers -- what the heck did you do??\n"); return -ENOSPC; } + ino = sbi->next_dir_ino++; ent = kmalloc(sizeof(struct autofs_dir_ent), GFP_KERNEL); if ( !ent ) @@ -418,15 +421,15 @@ static int autofs_root_mkdir(struct inode *dir, struct dentry *dentry, int mode) return -ENOSPC; } - dir->i_nlink++; - d_instantiate(dentry, iget(dir->i_sb,ent->ino)); - ent->hash = dentry->d_name.hash; memcpy(ent->name, dentry->d_name.name, 1+(ent->len = dentry->d_name.len)); - ent->ino = sbi->next_dir_ino++; + ent->ino = ino; ent->dentry = dentry; autofs_hash_insert(dh,ent); + dir->i_nlink++; + d_instantiate(dentry, iget(dir->i_sb,ino)); + return 0; } diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 6b4e344339bc..b8bbb3919eb4 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -597,8 +597,10 @@ printk("nfs_notify_change: revalidate failed, error=%d\n", error); sattr.gid = attr->ia_gid; sattr.size = (u32) -1; - if ((attr->ia_valid & ATTR_SIZE) && S_ISREG(inode->i_mode)) + if ((attr->ia_valid & ATTR_SIZE) && S_ISREG(inode->i_mode)) { sattr.size = attr->ia_size; + nfs_flush_trunc(inode, sattr.size); + } sattr.mtime.seconds = sattr.mtime.useconds = (u32) -1; if (attr->ia_valid & ATTR_MTIME) { @@ -624,7 +626,6 @@ printk("nfs_notify_change: revalidate failed, error=%d\n", error); if (sattr.size != fattr.size) printk("nfs_notify_change: sattr=%d, fattr=%d??\n", sattr.size, fattr.size); - nfs_truncate_dirty_pages(inode, sattr.size); inode->i_size = sattr.size; inode->i_mtime = fattr.mtime.seconds; } diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 33b4dd16a67f..516863b539a6 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -583,39 +583,22 @@ nfs_wb_pid(struct inode *inode, pid_t pid) NFS_WB(inode, req->wb_pid == pid); } -void -nfs_inval(struct inode *inode) -{ - nfs_cancel_dirty(inode,0); -} - /* - * Cancel any pending write requests after a given offset - * (called from nfs_notify_change). + * Flush all write requests for truncation: + * Simplification of the comparison has the side-effect of + * causing all writes in an infested page to be waited upon. */ int -nfs_truncate_dirty_pages(struct inode *inode, unsigned long offset) +nfs_flush_trunc(struct inode *inode, unsigned long from) { - struct nfs_wreq *req, *head; - unsigned long rqoffset; - - dprintk("NFS: truncate_dirty_pages(%d/%ld, %ld)\n", - inode->i_dev, inode->i_ino, offset); - - req = head = NFS_WRITEBACK(inode); - while (req != NULL) { - rqoffset = req->wb_page->offset + req->wb_offset; - - if (rqoffset >= offset) { - nfs_cancel_request(req); - } else if (rqoffset + req->wb_bytes >= offset) { - req->wb_bytes = offset - rqoffset; - } - if ((req = WB_NEXT(req)) == head) - break; - } + from &= PAGE_MASK; + NFS_WB(inode, req->wb_page->offset >= from); +} - return 0; +void +nfs_inval(struct inode *inode) +{ + nfs_cancel_dirty(inode,0); } /* @@ -648,6 +631,7 @@ nfs_wback_begin(struct rpc_task *task) task->tk_status = 0; /* Setup the task struct for a writeback call */ + req->wb_flags |= NFS_WRITE_INPROGRESS; req->wb_args.fh = NFS_FH(dentry); req->wb_args.offset = page->offset + req->wb_offset; req->wb_args.count = req->wb_bytes; @@ -655,7 +639,6 @@ nfs_wback_begin(struct rpc_task *task) rpc_call_setup(task, NFSPROC_WRITE, &req->wb_args, &req->wb_fattr, 0); - req->wb_flags |= NFS_WRITE_INPROGRESS; return; } diff --git a/fs/nls/Config.in b/fs/nls/Config.in index a2924b53b697..17df1d30ca15 100644 --- a/fs/nls/Config.in +++ b/fs/nls/Config.in @@ -13,31 +13,31 @@ fi if [ "$CONFIG_NLS" = "y" ]; then mainmenu_option next_comment comment 'Native Language Support' - tristate 'Codepage 437' CONFIG_NLS_CODEPAGE_437 - tristate 'Codepage 737' CONFIG_NLS_CODEPAGE_737 - tristate 'Codepage 775' CONFIG_NLS_CODEPAGE_775 - tristate 'Codepage 850' CONFIG_NLS_CODEPAGE_850 - tristate 'Codepage 852' CONFIG_NLS_CODEPAGE_852 - tristate 'Codepage 855' CONFIG_NLS_CODEPAGE_855 - tristate 'Codepage 857' CONFIG_NLS_CODEPAGE_857 - tristate 'Codepage 860' CONFIG_NLS_CODEPAGE_860 - tristate 'Codepage 861' CONFIG_NLS_CODEPAGE_861 - tristate 'Codepage 862' CONFIG_NLS_CODEPAGE_862 - tristate 'Codepage 863' CONFIG_NLS_CODEPAGE_863 - tristate 'Codepage 864' CONFIG_NLS_CODEPAGE_864 - tristate 'Codepage 865' CONFIG_NLS_CODEPAGE_865 - tristate 'Codepage 866' CONFIG_NLS_CODEPAGE_866 - tristate 'Codepage 869' CONFIG_NLS_CODEPAGE_869 - tristate 'Codepage 874' CONFIG_NLS_CODEPAGE_874 - tristate 'NLS ISO 8859-1' CONFIG_NLS_ISO8859_1 - tristate 'NLS ISO 8859-2' CONFIG_NLS_ISO8859_2 - tristate 'NLS ISO 8859-3' CONFIG_NLS_ISO8859_3 - tristate 'NLS ISO 8859-4' CONFIG_NLS_ISO8859_4 - tristate 'NLS ISO 8859-5' CONFIG_NLS_ISO8859_5 - tristate 'NLS ISO 8859-6' CONFIG_NLS_ISO8859_6 - tristate 'NLS ISO 8859-7' CONFIG_NLS_ISO8859_7 - tristate 'NLS ISO 8859-8' CONFIG_NLS_ISO8859_8 - tristate 'NLS ISO 8859-9' CONFIG_NLS_ISO8859_9 - tristate 'NLS KOI8-R' CONFIG_NLS_KOI8_R + tristate 'Codepage 437 (United States, Canada)' CONFIG_NLS_CODEPAGE_437 + tristate 'Codepage 737 (Greek)' CONFIG_NLS_CODEPAGE_737 + tristate 'Codepage 775 (Baltic Rim)' CONFIG_NLS_CODEPAGE_775 + tristate 'Codepage 850 (Europe)' CONFIG_NLS_CODEPAGE_850 + tristate 'Codepage 852 (Central/Eastern Europe)' CONFIG_NLS_CODEPAGE_852 + tristate 'Codepage 855 (Cyrillic)' CONFIG_NLS_CODEPAGE_855 + tristate 'Codepage 857 (Turkish)' CONFIG_NLS_CODEPAGE_857 + tristate 'Codepage 860 (Portugese)' CONFIG_NLS_CODEPAGE_860 + tristate 'Codepage 861 (Icelandic)' CONFIG_NLS_CODEPAGE_861 + tristate 'Codepage 862 (Hebrew)' CONFIG_NLS_CODEPAGE_862 + tristate 'Codepage 863 (Canadian French)' CONFIG_NLS_CODEPAGE_863 + tristate 'Codepage 864 (Arabic)' CONFIG_NLS_CODEPAGE_864 + tristate 'Codepage 865 (Nordic European)' CONFIG_NLS_CODEPAGE_865 + tristate 'Codepage 866 (Cyrillic/Russian)' CONFIG_NLS_CODEPAGE_866 + tristate 'Codepage 869 (Greek)' CONFIG_NLS_CODEPAGE_869 + tristate 'Codepage 874 (Thai)' CONFIG_NLS_CODEPAGE_874 + tristate 'NLS ISO 8859-1 (Latin 1; Western European Languages)' CONFIG_NLS_ISO8859_1 + tristate 'NLS ISO 8859-2 (Latin 2; Slavic/Central European)' CONFIG_NLS_ISO8859_2 + tristate 'NLS ISO 8859-3 (Latin 3; Esperanto, Galician, Maltese, Turkish)' CONFIG_NLS_ISO8859_3 + tristate 'NLS ISO 8859-4 (Latin 4; Estonian, Latvian, Lithuanian)' CONFIG_NLS_ISO8859_4 + tristate 'NLS ISO 8859-5 (Cyrillic)' CONFIG_NLS_ISO8859_5 + tristate 'NLS ISO 8859-6 (Arabic)' CONFIG_NLS_ISO8859_6 + tristate 'NLS ISO 8859-7 (Modern Greek)' CONFIG_NLS_ISO8859_7 + tristate 'NLS ISO 8859-8 (Hebrew)' CONFIG_NLS_ISO8859_8 + tristate 'NLS ISO 8859-9 (Latin 5; Turkey)' CONFIG_NLS_ISO8859_9 + tristate 'NLS KOI8-R (Russian)' CONFIG_NLS_KOI8_R endmenu fi diff --git a/fs/umsdos/mangle.c b/fs/umsdos/mangle.c index 98a5c25abf7d..08de621e7afc 100644 --- a/fs/umsdos/mangle.c +++ b/fs/umsdos/mangle.c @@ -69,14 +69,8 @@ void umsdos_manglename (struct umsdos_info *info) * ever think of using such a name in real life. This is not * fool proof. I don't think there is a total solution to this. */ - union { - int entry_num; - struct { - unsigned num1:5, num2:5, num3:5; - } num; - } u; + int entry_num; char *pt = info->fake.fname + info->fake.len; - /* lookup for encoding the last character of the extension * It contains valid character after the ugly one to make sure * even if someone overflows the 32 * 32 * 9 limit, it still @@ -93,17 +87,17 @@ void umsdos_manglename (struct umsdos_info *info) }; #define lookup12 (lookup3+9) - u.entry_num = info->f_pos / UMSDOS_REC_SIZE; - if (u.entry_num > (9 * 32 * 32)) { + entry_num = info->f_pos / UMSDOS_REC_SIZE; + if (entry_num > (9* 32 * 32)){ printk (KERN_WARNING "UMSDOS: more than 9216 files in a directory.\n" "This may break the mangling strategy.\n" "Not a killer problem. See doc.\n"); } *pt++ = '.'; - *pt++ = lookup3[u.num.num3]; - *pt++ = lookup12[u.num.num2]; - *pt++ = lookup12[u.num.num1]; - *pt = '\0'; /* help doing printk */ + *pt++ = lookup3 [(entry_num >> 10) & 31]; + *pt++ = lookup12[(entry_num >> 5) & 31]; + *pt++ = lookup12[entry_num & 31]; + *pt = '\0'; /* help doing printk */ info->fake.len += 4; info->msdos_reject = 0; /* Avoid mangling twice */ } diff --git a/include/asm-arm/arch-arc/dma.h b/include/asm-arm/arch-arc/dma.h index 3420d7d6d817..459c2ba11c9e 100644 --- a/include/asm-arm/arch-arc/dma.h +++ b/include/asm-arm/arch-arc/dma.h @@ -24,14 +24,19 @@ typedef enum { DMA_MODE_WRITE } dmamode_t; -#define MAX_DMA_CHANNELS 4 +#ifdef CONFIG_ARCH_ARC +#define MAX_DMA_CHANNELS 3 -#define DMA_0 0 -#define DMA_1 1 -#define DMA_VIRTUAL_FLOPPY 2 -#define DMA_VIRTUAL_SOUND 3 +#define DMA_VIRTUAL_FLOPPY0 0 +#define DMA_VIRTUAL_FLOPPY1 1 +#define DMA_VIRTUAL_SOUND 2 +#endif #ifdef CONFIG_ARCH_A5K +#define MAX_DMA_CHANNELS 2 + +#define DMA_VIRTUAL_FLOPPY 0 +#define DMA_VIRTUAL_SOUND 1 #define DMA_FLOPPY DMA_VIRTUAL_FLOPPY #endif diff --git a/include/asm-arm/arch-arc/hardware.h b/include/asm-arm/arch-arc/hardware.h index 4990ca132ed9..07b3679e0b22 100644 --- a/include/asm-arm/arch-arc/hardware.h +++ b/include/asm-arm/arch-arc/hardware.h @@ -24,29 +24,45 @@ #define HAS_MEMC1A #define HAS_VIDC -#ifdef CONFIG_ARCH_A5K -#define HAS_PCIO -#endif - /* * Optional hardware */ #define HAS_EXPMASK +/* Hardware addresses of major areas. + * *_START is the physical address + * *_SIZE is the size of the region + * *_BASE is the virtual address + */ +#define IO_START 0x03000000 +#define IO_SIZE 0x01000000 +#define IO_BASE 0x03000000 + +/* + * Screen mapping information + */ +#define SCREEN_START 0x02000000 +#define SCREEN2_END 0x02078000 +#define SCREEN2_BASE 0x02000000 +#define SCREEN1_END 0x02000000 +#define SCREEN1_BASE 0x01f88000 + + #ifndef __ASSEMBLER__ /* * for use with inb/outb */ -#define VIDC_BASE 0x80100000 -#define IOCEC4IO_BASE 0x8009c000 +#define IO_VIDC_BASE 0x80100000 #ifdef CONFIG_ARCH_ARC #define LATCHAADDR 0x80094010 #define LATCHBADDR 0x80094006 #endif -#define IOCECIO_BASE 0x80090000 #define IOC_BASE 0x80080000 -#define MEMCECIO_BASE 0x80000000 + +#define IO_EC_IOC4_BASE 0x8009c000 +#define IO_EC_IOC_BASE 0x80090000 +#define IO_EC_MEMC_BASE 0x80000000 /* * IO definitions @@ -56,23 +72,6 @@ #define PCIO_FLOPPYDMABASE ((volatile unsigned char *)0x0302a000) #define PCIO_BASE 0x03010000 -/* - * Mapping areas - */ -#define IO_END 0x03ffffff -#define IO_BASE 0x03000000 -#define IO_SIZE (IO_END - IO_BASE) -#define IO_START 0x03000000 - -/* - * Screen mapping information - */ -#define SCREEN2_END 0x02078000 -#define SCREEN2_BASE 0x02000000 -#define SCREEN1_END SCREEN2_BASE -#define SCREEN1_BASE 0x01f88000 -#define SCREEN_START 0x02000000 - /* * RAM definitions */ @@ -88,7 +87,6 @@ #define IOC_BASE 0x03200000 #define PCIO_FLOPPYDMABASE 0x0302a000 #define PCIO_BASE 0x03010000 -#define IO_BASE 0x03000000 #endif #endif diff --git a/include/asm-arm/arch-arc/ide.h b/include/asm-arm/arch-arc/ide.h index 24bc4899d231..2fc6ce282855 100644 --- a/include/asm-arm/arch-arc/ide.h +++ b/include/asm-arm/arch-arc/ide.h @@ -8,50 +8,44 @@ * * Modifications: * 04-04-1998 PJB Merged `arc' and `a5k' versions + * 01-07-1998 RMK Added new ide_ioregspec_t + * 29-07-1998 RMK Major re-work of IDE architecture specific code */ #include #include -static __inline__ int -ide_default_irq(ide_ioreg_t base) +/* + * Set up a hw structure for a specified data port, control port and IRQ. + * This should follow whatever the default interface uses. + */ +static __inline__ void +ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq) { -#ifdef CONFIG_ARCH_A5K - if (base == 0x1f0) - return IRQ_HARDDISK; -#endif - return 0; -} + ide_ioreg_t reg = (ide_ioreg_t) data_port; + int i; -static __inline__ ide_ioreg_t -ide_default_io_base(int index) -{ -#ifdef CONFIG_ARCH_A5K - if (index == 0) - return 0x1f0; -#endif - return 0; -} + memset(hw, 0, sizeof(*hw)); -static __inline__ int -ide_default_stepping(int index) -{ - return 0; + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { + hw->io_ports[i] = reg; + reg += 1; + } + hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port; + hw->irq = irq; } +/* + * This registers the standard ports for this architecture with the IDE + * driver. + */ static __inline__ void -ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int stepping, int *irq) +ide_init_default_hwifs(void) { - ide_ioreg_t port = base; - ide_ioreg_t ctrl = base + 0x206; - int i; +#ifdef CONFIG_ARCH_A5K + hw_regs_t hw; - i = 8; - while (i--) { - *p++ = port; - port += 1 << stepping; - } - *p++ = ctrl; - if (irq != NULL) - *irq = 0; + ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, IRQ_HARDDISK); + ide_register_hw(&hw, NULL); +#endif } diff --git a/include/asm-arm/arch-arc/keyboard.h b/include/asm-arm/arch-arc/keyboard.h index 59272e269c24..388014703703 100644 --- a/include/asm-arm/arch-arc/keyboard.h +++ b/include/asm-arm/arch-arc/keyboard.h @@ -35,3 +35,5 @@ extern unsigned char a5kkbd_sysrq_xlate[NR_SCANCODES]; #define kbd_sysrq_xlate a5kkbd_sysrq_xlate #define kbd_disable_irq() disable_irq(IRQ_KEYBOARDRX) #define kbd_enable_irq() enable_irq(IRQ_KEYBOARDRX) + +#define SYSRQ_KEY 13 diff --git a/include/asm-arm/arch-arc/processor.h b/include/asm-arm/arch-arc/processor.h index 314525eefd3f..33462ca98feb 100644 --- a/include/asm-arm/arch-arc/processor.h +++ b/include/asm-arm/arch-arc/processor.h @@ -26,11 +26,7 @@ /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#if 0 -#define TASK_UNMAPPED_BASE(off) (TASK_SIZE / 3) -#else #define TASK_UNMAPPED_BASE (TASK_SIZE / 3) -#endif #define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr) #define INIT_MMAP \ diff --git a/include/asm-arm/arch-ebsa110/hardware.h b/include/asm-arm/arch-ebsa110/hardware.h index 61ac7492ebbb..d04eb9835b0d 100644 --- a/include/asm-arm/arch-ebsa110/hardware.h +++ b/include/asm-arm/arch-ebsa110/hardware.h @@ -28,9 +28,8 @@ /* * Mapping areas */ -#define IO_END 0xffffffff #define IO_BASE 0xe0000000 -#define IO_SIZE (IO_END - IO_BASE) +#define IO_SIZE 0x20000000 #define IO_START 0xe0000000 /* diff --git a/include/asm-arm/arch-ebsa110/processor.h b/include/asm-arm/arch-ebsa110/processor.h index bf1f6d384158..95ce641c4281 100644 --- a/include/asm-arm/arch-ebsa110/processor.h +++ b/include/asm-arm/arch-ebsa110/processor.h @@ -23,11 +23,7 @@ /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#if 0 -#define TASK_UNMAPPED_BASE(off) (TASK_SIZE / 3) -#else #define TASK_UNMAPPED_BASE (TASK_SIZE / 3) -#endif #define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr) #define INIT_MMAP \ diff --git a/include/asm-arm/arch-ebsa285/hardware.h b/include/asm-arm/arch-ebsa285/hardware.h index a9bc6f0a45a9..4884821e38db 100644 --- a/include/asm-arm/arch-ebsa285/hardware.h +++ b/include/asm-arm/arch-ebsa285/hardware.h @@ -20,11 +20,9 @@ * */ -#define IO_END 0xffffffff #define IO_BASE 0xe0000000 -#define IO_SIZE (IO_END - IO_BASE) - -#define HAS_PCIO +#define PCIO_BASE 0xffe00000 + #define XBUS_LEDS ((volatile unsigned char *)0xfff12000) #define XBUS_LED_AMBER (1 << 0) @@ -38,8 +36,6 @@ #define XBUS_SWITCH_J17_11 ((*XBUS_SWITCH) & (1 << 5)) #define XBUS_SWITCH_J17_9 ((*XBUS_SWITCH) & (1 << 6)) -#define PCIO_BASE 0xffe00000 - #define CSR_SA110_CNTL ((volatile unsigned long *)0xfe00013c) #define CSR_PCIADDR_EXTN ((volatile unsigned long *)0xfe000140) #define CSR_PREFETCHMEMRANGE ((volatile unsigned long *)0xfe000144) diff --git a/include/asm-arm/arch-ebsa285/ide.h b/include/asm-arm/arch-ebsa285/ide.h index 35eff5c28fe5..b0071a45b2b0 100644 --- a/include/asm-arm/arch-ebsa285/ide.h +++ b/include/asm-arm/arch-ebsa285/ide.h @@ -1 +1,38 @@ -/* no ide */ +/* + * linux/include/asm-arm/arch-ebsa285/ide.h + * + * Copyright (c) 1998 Russell King + * + * Modifications: + * 29-07-1998 RMK Major re-work of IDE architecture specific code + */ +#include + +/* + * Set up a hw structure for a specified data port, control port and IRQ. + * This should follow whatever the default interface uses. + */ +static __inline__ void +ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq) +{ + ide_ioreg_t reg = (ide_ioreg_t) data_port; + int i; + + memset(hw, 0, sizeof(*hw)); + + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { + hw->io_ports[i] = reg; + reg += 1; + } + hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port; + hw->irq = irq; +} + +/* + * This registers the standard ports for this architecture with the IDE + * driver. + */ +static __inline__ void +ide_init_default_hwifs(void) +{ +} diff --git a/include/asm-arm/arch-ebsa285/irq.h b/include/asm-arm/arch-ebsa285/irq.h index 029b1b1a6ad1..03b5e3c0d6f0 100644 --- a/include/asm-arm/arch-ebsa285/irq.h +++ b/include/asm-arm/arch-ebsa285/irq.h @@ -5,8 +5,11 @@ * * Changelog: * 22-08-1998 RMK Restructured IRQ routines + * 03-09-1998 PJB Merged CATS support */ +#include + static void ebsa285_mask_irq(unsigned int irq) { *CSR_IRQ_DISABLE = 1 << irq; @@ -16,7 +19,73 @@ static void ebsa285_unmask_irq(unsigned int irq) { *CSR_IRQ_ENABLE = 1 << irq; } + +#ifdef CONFIG_CATS + +/* + * This contains the irq mask for both 8259A irq controllers, + */ +static unsigned int isa_irq_mask = 0xffff; + +#define cached_21 (isa_irq_mask & 0xff) +#define cached_A1 ((isa_irq_mask >> 8) & 0xff) + +#define update_8259(_irq) \ + if ((_irq) & 8) \ + outb(cached_A1, 0xa1); \ + else \ + outb(cached_21, 0x21); + +static void isa_interrupt(int irq, void *h, struct pt_regs *regs) +{ + asmlinkage void do_IRQ(int irq, struct pt_regs * regs); + unsigned int irqbits = inb(0x20) | (inb(0xa0) << 8), irqnr = 0; + irqbits &= ~(1<<2); /* don't try to service the cascade */ + while (irqbits) { + if (irqbits & 1) + do_IRQ(32 + irqnr, regs); + irqbits >>= 1; + irqnr++; + } +} + +static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } + +static struct irqaction irq_isa = + { isa_interrupt, SA_INTERRUPT, 0, "ISA PIC", NULL, NULL }; +static struct irqaction irq_cascade = + { no_action, 0, 0, "cascade", NULL, NULL }; + +static void cats_mask_and_ack_isa_irq(unsigned int irq) +{ + isa_irq_mask |= (1 << (irq - 32)); + update_8259(irq); + if (irq & 8) { + inb(0xA1); /* DUMMY */ + outb(cached_A1,0xA1); + outb(0x62,0x20); /* Specific EOI to cascade */ + outb(0x20,0xA0); + } else { + inb(0x21); /* DUMMY */ + outb(cached_21,0x21); + outb(0x20,0x20); + } +} + +static void cats_mask_isa_irq(unsigned int irq) +{ + isa_irq_mask |= (1 << (irq - 32)); + update_8259(irq); +} + +static void cats_unmask_isa_irq(unsigned int irq) +{ + isa_irq_mask &= ~(1 << (irq - 32)); + update_8259(irq); +} +#endif + static __inline__ void irq_init_irq(void) { int irq; @@ -27,8 +96,45 @@ static __inline__ void irq_init_irq(void) for (irq = 0; irq < NR_IRQS; irq++) { irq_desc[irq].valid = 1; irq_desc[irq].probe_ok = 1; - irq_desc[irq].mask_ack = ebsa285_mask_irq; - irq_desc[irq].mask = ebsa285_mask_irq; - irq_desc[irq].unmask = ebsa285_unmask_irq; +#ifdef CONFIG_CATS + if (machine_is_cats() && IRQ_IS_ISA(irq)) { + irq_desc[irq].mask_ack = cats_mask_and_ack_isa_irq; + irq_desc[irq].mask = cats_mask_isa_irq; + irq_desc[irq].unmask = cats_unmask_isa_irq; + } else +#endif + { + irq_desc[irq].mask_ack = ebsa285_mask_irq; + irq_desc[irq].mask = ebsa285_mask_irq; + irq_desc[irq].unmask = ebsa285_unmask_irq; + } + } + +#ifdef CONFIG_CATS + if (machine_is_cats()) { + request_region(0x20, 2, "pic1"); + request_region(0xa0, 2, "pic2"); + + /* set up master 8259 */ + outb(0x11, 0x20); + outb(0, 0x21); + outb(1<<2, 0x21); + outb(0x1, 0x21); + outb(0xff, 0x21); + outb(0x68, 0x20); + outb(0xa, 0x20); + + /* set up slave 8259 */ + outb(0x11, 0xa0); + outb(0, 0xa1); + outb(2, 0xa1); + outb(0x1, 0xa1); + outb(0xff, 0xa1); + outb(0x68, 0xa0); + outb(0xa, 0xa0); + + setup_arm_irq(IRQ_ISA_PIC, &irq_isa); + setup_arm_irq(IRQ_ISA_CASCADE, &irq_cascade); } +#endif } diff --git a/include/asm-arm/arch-ebsa285/irqs.h b/include/asm-arm/arch-ebsa285/irqs.h index f2ef06c9ddd5..6021bee6ea1b 100644 --- a/include/asm-arm/arch-ebsa285/irqs.h +++ b/include/asm-arm/arch-ebsa285/irqs.h @@ -2,9 +2,10 @@ * linux/include/asm-arm/arch-ebsa285/irqs.h * * Copyright (C) 1998 Russell King + * Copyright (C) 1998 Phil Blundell */ -#define NR_IRQS 32 +#define NR_IRQS 48 /* * This is a list of all interrupts that the 21285 @@ -39,10 +40,18 @@ #define IRQ_PCITARGETABORT 30 #define IRQ_PCIPARITY 31 +/* IRQs 32-47 are the 16 ISA interrupts on a CATS board. */ +#define IRQ_ISA_PIC IRQ_IN2 +#define IRQ_IS_ISA(_x) (((_x) >= 32) && ((_x) <= 47)) +#define IRQ_ISA(_x) ((_x) + 0x20) +#define IRQ_ISA_CASCADE IRQ_ISA(2) + /* * Now map them to the Linux interrupts */ #define IRQ_TIMER IRQ_TIMER1 +#define IRQ_FLOPPYDISK IRQ_ISA(6) +#define IRQ_HARDDISK IRQ_ISA(14) +#define IRQ_HARDDISK_SECONDARY IRQ_ISA(15) -#define irq_cannonicalize(i) (i) - +#define irq_cannonicalize(_i) (((_i) == IRQ_ISA_CASCADE) ? IRQ_ISA(9) : _i) diff --git a/include/asm-arm/arch-ebsa285/keyboard.h b/include/asm-arm/arch-ebsa285/keyboard.h index 4620ff16588c..ad6eb0e5a572 100644 --- a/include/asm-arm/arch-ebsa285/keyboard.h +++ b/include/asm-arm/arch-ebsa285/keyboard.h @@ -4,16 +4,48 @@ * Keyboard driver definitions for EBSA285 architecture * * (C) 1998 Russell King + * (C) 1998 Phil Blundell */ #include #include +#include #define NR_SCANCODES 128 -#ifdef CONFIG_MAGIC_SYSRQ -static unsigned char kbd_sysrq_xlate[NR_SCANCODES]; -#endif +#ifdef CONFIG_CATS + +#define KEYBOARD_IRQ IRQ_ISA(1) + +extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); +extern int pckbd_getkeycode(unsigned int scancode); +extern int pckbd_pretranslate(unsigned char scancode, char raw_mode); +extern int pckbd_translate(unsigned char scancode, unsigned char *keycode, + char raw_mode); +extern char pckbd_unexpected_up(unsigned char keycode); +extern void pckbd_leds(unsigned char leds); +extern void pckbd_init_hw(void); +extern unsigned char pckbd_sysrq_xlate[128]; + +#define kbd_setkeycode pckbd_setkeycode +#define kbd_getkeycode pckbd_getkeycode +#define kbd_pretranslate pckbd_pretranslate +#define kbd_translate(sc, kcp, ufp, rm) ({ *ufp = sc & 0200; \ + pckbd_translate(sc & 0x7f, kcp, rm);}) + +#define kbd_unexpected_up pckbd_unexpected_up +#define kbd_leds pckbd_leds +#define kbd_init_hw() \ + do { if (machine_is_cats()) pckbd_init_hw(); } while (0) +#define kbd_sysrq_xlate pckbd_sysrq_xlate +#define kbd_disable_irq() +#define kbd_enable_irq() + +#define SYSRQ_KEY 0x54 + +#else + +/* Dummy keyboard definitions */ #define kbd_setkeycode(sc,kc) (-EINVAL) #define kbd_getkeycode(sc) (-EINVAL) @@ -35,3 +67,6 @@ static unsigned char kbd_sysrq_xlate[NR_SCANCODES]; #define kbd_disable_irq() #define kbd_enable_irq() +#define SYSRQ_KEY 13 + +#endif diff --git a/include/asm-arm/arch-ebsa285/mmu.h b/include/asm-arm/arch-ebsa285/mmu.h index 8e2e98ef63e8..ad7b2f558428 100644 --- a/include/asm-arm/arch-ebsa285/mmu.h +++ b/include/asm-arm/arch-ebsa285/mmu.h @@ -7,6 +7,7 @@ * 20-10-1996 RMK Created * 31-12-1997 RMK Fixed definitions to reduce warnings * 17-05-1998 DAG Added __virt_to_bus and __bus_to_virt functions. + * 21-11-1998 RMK Changed __virt_to_bus and __bus_to_virt to macros. */ #ifndef __ASM_ARCH_MMU_H #define __ASM_ARCH_MMU_H @@ -19,7 +20,9 @@ #define __phys_to_virt__is_a_macro #define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET) -extern unsigned long __virt_to_bus(unsigned long); -extern unsigned long __bus_to_virt(unsigned long); +#define __virt_to_bus__is_a_macro +#define __virt_to_bus(x) (x - 0xe0000000) +#define __bus_to_virt__is_a_macro +#define __bus_to_virt(x) (x + 0xe0000000) #endif diff --git a/include/asm-arm/arch-ebsa285/processor.h b/include/asm-arm/arch-ebsa285/processor.h index bf1f6d384158..95ce641c4281 100644 --- a/include/asm-arm/arch-ebsa285/processor.h +++ b/include/asm-arm/arch-ebsa285/processor.h @@ -23,11 +23,7 @@ /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#if 0 -#define TASK_UNMAPPED_BASE(off) (TASK_SIZE / 3) -#else #define TASK_UNMAPPED_BASE (TASK_SIZE / 3) -#endif #define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr) #define INIT_MMAP \ diff --git a/include/asm-arm/arch-ebsa285/serial.h b/include/asm-arm/arch-ebsa285/serial.h index 0e8479ff8ec0..fa4fc73c054d 100644 --- a/include/asm-arm/arch-ebsa285/serial.h +++ b/include/asm-arm/arch-ebsa285/serial.h @@ -5,10 +5,14 @@ * * Changelog: * 15-10-1996 RMK Created + * 25-05-1998 PJB CATS support */ #ifndef __ASM_ARCH_SERIAL_H #define __ASM_ARCH_SERIAL_H +#include +#include + /* * This assumes you have a 1.8432 MHz clock for your UART. * @@ -18,23 +22,31 @@ */ #define BASE_BAUD (1843200 / 16) +#ifdef CONFIG_CATS +#define _SER_IRQ0 IRQ_ISA(4) +#define _SER_IRQ1 IRQ_ISA(3) +#else +#define _SER_IRQ0 0 +#define _SER_IRQ1 0 +#endif + #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) /* UART CLK PORT IRQ FLAGS */ #define SERIAL_PORT_DFNS \ - { 0, BASE_BAUD, 0x3F8, 0, STD_COM_FLAGS }, /* ttyS0 */ \ - { 0, BASE_BAUD, 0x2F8, 0, STD_COM_FLAGS }, /* ttyS1 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS2 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS3 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS4 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS5 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS6 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS7 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS8 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS9 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS10 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS11 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS12 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS13 */ + { 0, BASE_BAUD, 0x3F8, _SER_IRQ0, STD_COM_FLAGS }, /* ttyS0 */ \ + { 0, BASE_BAUD, 0x2F8, _SER_IRQ1, STD_COM_FLAGS }, /* ttyS1 */ \ + { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS2 */ \ + { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS3 */ \ + { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS4 */ \ + { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS5 */ \ + { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS6 */ \ + { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS7 */ \ + { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS8 */ \ + { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS9 */ \ + { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS10 */ \ + { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS11 */ \ + { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS12 */ \ + { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS13 */ #endif diff --git a/include/asm-arm/arch-ebsa285/time.h b/include/asm-arm/arch-ebsa285/time.h index cbc53293af5a..ff14bdf68280 100644 --- a/include/asm-arm/arch-ebsa285/time.h +++ b/include/asm-arm/arch-ebsa285/time.h @@ -2,14 +2,21 @@ * linux/include/asm-arm/arch-ebsa285/time.h * * Copyright (c) 1998 Russell King. + * Copyright (c) 1998 Phil Blundell * - * No real time clock on the evalulation board! + * CATS has a real-time clock, though the evaluation board doesn't. * * Changelog: * 21-Mar-1998 RMK Created + * 27-Aug-1998 PJB CATS support */ +#define RTC_PORT(x) (0x72+(x)) +#define RTC_ALWAYS_BCD 1 + #include +#include +#include extern __inline__ unsigned long gettimeoffset (void) { @@ -18,22 +25,27 @@ extern __inline__ unsigned long gettimeoffset (void) extern __inline__ int reset_timer (void) { - static unsigned int count = 50; - static int last_pid; - *CSR_TIMER1_CLR = 0; - if (current->pid != last_pid) { - last_pid = current->pid; - if (last_pid) - leds_event(led_idle_end); - else - leds_event(led_idle_start); - } + /* + * Do the LEDs thing on EBSA-285 hardware. + */ + if (!machine_is_cats()) { + static unsigned int count = 50; + static int last_pid; - if (--count == 0) { - count = 50; - leds_event(led_timer); + if (current->pid != last_pid) { + last_pid = current->pid; + if (last_pid) + leds_event(led_idle_end); + else + leds_event(led_idle_start); + } + + if (--count == 0) { + count = 50; + leds_event(led_timer); + } } return 1; @@ -49,9 +61,59 @@ extern __inline__ int reset_timer (void) */ extern __inline__ unsigned long setup_timer (void) { + int year, mon, day, hour, min, sec; + + /* + * Default the date to 1 Jan 1970 0:0:0 + */ + year = 1970; mon = 1; day = 1; + hour = 0; min = 0; sec = 0; + *CSR_TIMER1_CLR = 0; *CSR_TIMER1_LOAD = LATCH; *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16; - return mktime(1970, 1, 1, 0, 0, 0); + if (machine_is_cats()) + { + int i; + /* + * Read the real time from the Dallas chip. (Code borrowed + * from arch/i386/kernel/time.c). + */ + + /* The Linux interpretation of the CMOS clock register contents: + * When the Update-In-Progress (UIP) flag goes from 1 to 0, the + * RTC registers show the second which has precisely just started. + * Let's hope other operating systems interpret the RTC the same way. + */ + + /* read RTC exactly on falling edge of update flag */ + for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ + if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) + break; + for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ + if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) + break; + do { /* Isn't this overkill ? UIP above should guarantee consistency */ + sec = CMOS_READ(RTC_SECONDS); + min = CMOS_READ(RTC_MINUTES); + hour = CMOS_READ(RTC_HOURS); + day = CMOS_READ(RTC_DAY_OF_MONTH); + mon = CMOS_READ(RTC_MONTH); + year = CMOS_READ(RTC_YEAR); + } while (sec != CMOS_READ(RTC_SECONDS)); + if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) + { + BCD_TO_BIN(sec); + BCD_TO_BIN(min); + BCD_TO_BIN(hour); + BCD_TO_BIN(day); + BCD_TO_BIN(mon); + BCD_TO_BIN(year); + } + if ((year += 1900) < 1970) + year += 100; + } + + return mktime(year, mon, day, hour, min, sec); } diff --git a/include/asm-arm/arch-nexuspci/hardware.h b/include/asm-arm/arch-nexuspci/hardware.h index 997569748df1..57607681c301 100644 --- a/include/asm-arm/arch-nexuspci/hardware.h +++ b/include/asm-arm/arch-nexuspci/hardware.h @@ -27,9 +27,7 @@ /* * Mapping areas */ -#define IO_END 0xffffffff #define IO_BASE 0xfe000000 -#define IO_SIZE (IO_END - IO_BASE) /* * RAM definitions diff --git a/include/asm-arm/arch-nexuspci/processor.h b/include/asm-arm/arch-nexuspci/processor.h index da9fdd583c9f..5489c8267842 100644 --- a/include/asm-arm/arch-nexuspci/processor.h +++ b/include/asm-arm/arch-nexuspci/processor.h @@ -24,11 +24,7 @@ /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#if 0 -#define TASK_UNMAPPED_BASE(off) (TASK_SIZE / 3) -#else #define TASK_UNMAPPED_BASE (TASK_SIZE / 3) -#endif #define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr) #define INIT_MMAP \ diff --git a/include/asm-arm/arch-rpc/hardware.h b/include/asm-arm/arch-rpc/hardware.h index 706992b787ee..a846834fca5a 100644 --- a/include/asm-arm/arch-rpc/hardware.h +++ b/include/asm-arm/arch-rpc/hardware.h @@ -13,33 +13,45 @@ * What hardware must be present */ #define HAS_IOMD -#define HAS_PCIO #define HAS_VIDC20 -/* - * Optional hardware - */ -#define HAS_EXPMASK - -/* - * Physical definitions +/* Hardware addresses of major areas. + * *_START is the physical address + * *_SIZE is the size of the region + * *_BASE is the virtual address */ +#define RAM_SIZE 0x10000000 #define RAM_START 0x10000000 -#define IO_START 0x03000000 + +#define EASI_SIZE 0x08000000 /* EASI I/O */ +#define EASI_START 0x08000000 +#define EASI_BASE 0xe8000000 + +#define IO_START 0x03000000 /* I/O */ +#define IO_SIZE 0x01000000 +#define IO_BASE 0xe0000000 + #define SCREEN_START 0x02000000 /* VRAM */ +#define SCREEN2_END 0xe0000000 +#define SCREEN2_BASE 0xd8000000 +#define SCREEN1_END 0xd8000000 +#define SCREEN1_BASE 0xd0000000 + #ifndef __ASSEMBLER__ /* * for use with inb/outb */ -#define VIDC_AUDIO_BASE 0x80140000 -#define VIDC_BASE 0x80100000 -#define IOCEC4IO_BASE 0x8009c000 -#define IOCECIO_BASE 0x80090000 -#define IOMD_BASE 0x80080000 -#define MEMCEC8IO_BASE 0x8000ac00 -#define MEMCECIO_BASE 0x80000000 +#define IO_VIDC_AUDIO_BASE 0x80140000 +#define IO_VIDC_BASE 0x80100000 +#define IO_IOMD_BASE 0x80080000 + +#define IO_EC_EASI_BASE 0x82000000 +#define IO_EC_IOC4_BASE 0x8009c000 +#define IO_EC_IOC_BASE 0x80090000 +#define IO_EC_MEMC8_BASE 0x8000ac00 +#define IO_EC_MEMC_BASE 0x80000000 /* * IO definitions @@ -50,21 +62,6 @@ #define PCIO_FLOPPYDMABASE ((volatile unsigned char *)0xe002a000) #define PCIO_BASE 0xe0010000 -/* - * Mapping areas - */ -#define IO_END 0xe1000000 -#define IO_BASE 0xe0000000 -#define IO_SIZE (IO_END - IO_BASE) - -/* - * Screen mapping information - */ -#define SCREEN2_END 0xe0000000 -#define SCREEN2_BASE 0xd8000000 -#define SCREEN1_END SCREEN2_BASE -#define SCREEN1_BASE 0xd0000000 - /* * Offsets from RAM base */ @@ -95,7 +92,6 @@ #define IOC_BASE 0xe0200000 #define PCIO_FLOPPYDMABASE 0xe002a000 #define PCIO_BASE 0xe0010000 -#define IO_BASE 0xe0000000 #endif #endif diff --git a/include/asm-arm/arch-rpc/ide.h b/include/asm-arm/arch-rpc/ide.h index 311a988531ea..ccbc7cf76aa6 100644 --- a/include/asm-arm/arch-rpc/ide.h +++ b/include/asm-arm/arch-rpc/ide.h @@ -2,44 +2,41 @@ * linux/include/asm-arm/arch-rpc/ide.h * * Copyright (c) 1997 Russell King + * + * Modifications: + * 29-07-1998 RMK Major re-work of IDE architecture specific code */ #include -static __inline__ int -ide_default_irq(ide_ioreg_t base) +/* + * Set up a hw structure for a specified data port, control port and IRQ. + * This should follow whatever the default interface uses. + */ +static __inline__ void +ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq) { - if (base == 0x1f0) - return IRQ_HARDDISK; - return 0; -} + ide_ioreg_t reg = (ide_ioreg_t) data_port; + int i; -static __inline__ ide_ioreg_t -ide_default_io_base(int index) -{ - if (index == 0) - return 0x1f0; - return 0; -} + memset(hw, 0, sizeof(*hw)); -static __inline__ int -ide_default_stepping(int index) -{ - return 0; + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { + hw->io_ports[i] = reg; + reg += 1; + } + hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port; + hw->irq = irq; } +/* + * This registers the standard ports for this architecture with the IDE + * driver. + */ static __inline__ void -ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int stepping, int *irq) +ide_init_default_hwifs(void) { - ide_ioreg_t port = base; - ide_ioreg_t ctrl = base + 0x206; - int i; + hw_regs_t hw; - i = 8; - while (i--) { - *p++ = port; - port += 1 << stepping; - } - *p++ = ctrl; - if (irq != NULL) - *irq = 0; + ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, IRQ_HARDDISK); + ide_register_hw(&hw, NULL); } diff --git a/include/asm-arm/arch-rpc/keyboard.h b/include/asm-arm/arch-rpc/keyboard.h index 44090e12263f..6c04cf07495d 100644 --- a/include/asm-arm/arch-rpc/keyboard.h +++ b/include/asm-arm/arch-rpc/keyboard.h @@ -40,3 +40,4 @@ extern unsigned char ps2kbd_sysrq_xlate[NR_SCANCODES]; #define kbd_disable_irq() disable_irq(IRQ_KEYBOARDRX) #define kbd_enable_irq() enable_irq(IRQ_KEYBOARDRX) +#define SYSRQ_KEY 13 diff --git a/include/asm-arm/arch-rpc/processor.h b/include/asm-arm/arch-rpc/processor.h index cdb79eeed70b..86e999db97df 100644 --- a/include/asm-arm/arch-rpc/processor.h +++ b/include/asm-arm/arch-rpc/processor.h @@ -26,11 +26,7 @@ /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#if 0 -#define TASK_UNMAPPED_BASE(off) (TASK_SIZE / 3) -#else #define TASK_UNMAPPED_BASE (TASK_SIZE / 3) -#endif #define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr) #define INIT_MMAP \ diff --git a/include/asm-arm/arch-vnc/hardware.h b/include/asm-arm/arch-vnc/hardware.h index b0021b72441d..4cf253088a54 100644 --- a/include/asm-arm/arch-vnc/hardware.h +++ b/include/asm-arm/arch-vnc/hardware.h @@ -7,84 +7,20 @@ */ /* Logical Physical - * 0xfff00000 0x40000000 X-Bus * 0xffe00000 0x7c000000 PCI I/O space - * * 0xfe000000 0x42000000 CSR * 0xfd000000 0x78000000 Outbound write flush * 0xfc000000 0x79000000 PCI IACK/special space - * - * 0xf9030000 0x7a080000 PCI Config type 1 card 4 - * 0xf9020000 0x7a040000 PCI Config type 1 card 3 - * 0xf9010000 0x7a020000 PCI Config type 1 card 2 - * 0xf9000000 0x7a010000 PCI Config type 1 card 1 - * - * 0xf8030000 0x7b080000 PCI Config type 0 card 4 - * 0xf8020000 0x7b040000 PCI Config type 0 card 3 - * 0xf8010000 0x7b020000 PCI Config type 0 card 2 - * 0xf8000000 0x7b010000 PCI Config type 0 card 1 + * 0xf9000000 0x7a000000 PCI Config type 1 + * 0xf8000000 0x7b000000 PCI Config type 0 * */ - -/* - * DEC21285 - */ -#define CSR_SA110_CNTL ((volatile unsigned long *)0xfe00013c) -#define CSR_PCIADDR_EXTN ((volatile unsigned long *)0xfe000140) -#define CSR_PREFETCHMEMRANGE ((volatile unsigned long *)0xfe000144) -#define CSR_XBUS_CYCLE ((volatile unsigned long *)0xfe000148) -#define CSR_XBUS_IOSTROBE ((volatile unsigned long *)0xfe00014c) -#define CSR_DOORBELL_PCI ((volatile unsigned long *)0xfe000150) -#define CSR_DOORBELL_SA110 ((volatile unsigned long *)0xfe000154) - - -#define CSR_UARTDR ((volatile unsigned long *)0xfe000160) -#define CSR_RXSTAT ((volatile unsigned long *)0xfe000164) -#define CSR_H_UBRLCR ((volatile unsigned long *)0xfe000168) -#define CSR_M_UBRLCR ((volatile unsigned long *)0xfe00016c) -#define CSR_L_UBRLCR ((volatile unsigned long *)0xfe000170) -#define CSR_UARTCON ((volatile unsigned long *)0xfe000174) -#define CSR_UARTFLG ((volatile unsigned long *)0xfe000178) - -#define CSR_IRQ_STATUS ((volatile unsigned long *)0xfe000180) -#define CSR_IRQ_RAWSTATUS ((volatile unsigned long *)0xfe000184) -#define CSR_IRQ_ENABLE ((volatile unsigned long *)0xfe000188) -#define CSR_IRQ_DISABLE ((volatile unsigned long *)0xfe00018c) -#define CSR_IRQ_SOFT ((volatile unsigned long *)0xfe000190) -#define CSR_FIQ_STATUS ((volatile unsigned long *)0xfe000280) -#define CSR_FIQ_RAWSTATUS ((volatile unsigned long *)0xfe000284) -#define CSR_FIQ_ENABLE ((volatile unsigned long *)0xfe000288) -#define CSR_FIQ_DISABLE ((volatile unsigned long *)0xfe00028c) -#define CSR_FIQ_SOFT ((volatile unsigned long *)0xfe000290) - -#define CSR_TIMER1_LOAD ((volatile unsigned long *)0xfe000300) -#define CSR_TIMER1_VALUE ((volatile unsigned long *)0xfe000304) -#define CSR_TIMER1_CNTL ((volatile unsigned long *)0xfe000308) -#define CSR_TIMER1_CLR ((volatile unsigned long *)0xfe00030c) - -#define CSR_TIMER2_LOAD ((volatile unsigned long *)0xfe000320) -#define CSR_TIMER2_VALUE ((volatile unsigned long *)0xfe000324) -#define CSR_TIMER2_CNTL ((volatile unsigned long *)0xfe000328) -#define CSR_TIMER2_CLR ((volatile unsigned long *)0xfe00032c) - -#define CSR_TIMER3_LOAD ((volatile unsigned long *)0xfe000340) -#define CSR_TIMER3_VALUE ((volatile unsigned long *)0xfe000344) -#define CSR_TIMER3_CNTL ((volatile unsigned long *)0xfe000348) -#define CSR_TIMER3_CLR ((volatile unsigned long *)0xfe00034c) - -#define CSR_TIMER4_LOAD ((volatile unsigned long *)0xfe000360) -#define CSR_TIMER4_VALUE ((volatile unsigned long *)0xfe000364) -#define CSR_TIMER4_CNTL ((volatile unsigned long *)0xfe000368) -#define CSR_TIMER4_CLR ((volatile unsigned long *)0xfe00036c) - -#define TIMER_CNTL_ENABLE (1 << 7) -#define TIMER_CNTL_AUTORELOAD (1 << 6) -#define TIMER_CNTL_DIV1 (0) -#define TIMER_CNTL_DIV16 (1 << 2) -#define TIMER_CNTL_DIV256 (2 << 2) -#define TIMER_CNTL_CNTEXT (3 << 2) +#include +#define IO_BASE_ARM_CSR 0xfe000000 +#define PCI_IACK 0xfc000000 + /* LEDs */ #define XBUS_LEDS ((volatile unsigned char *)0xfff12000) #define XBUS_LED_AMBER (1 << 0) @@ -103,18 +39,11 @@ #define IO_SIZE (IO_END - IO_BASE) #define HAS_PCIO - -#define XBUS_SWITCH ((volatile unsigned char *)0xfff12000) -#define XBUS_SWITCH_SWITCH ((*XBUS_SWITCH) & 15) -#define XBUS_SWITCH_J17_13 ((*XBUS_SWITCH) & (1 << 4)) -#define XBUS_SWITCH_J17_11 ((*XBUS_SWITCH) & (1 << 5)) -#define XBUS_SWITCH_J17_9 ((*XBUS_SWITCH) & (1 << 6)) - #define PCIO_BASE 0xffe00000 #define KERNTOPHYS(a) ((unsigned long)(&a)) -#define PARAMS_OFFSET 0x0100 -#define PARAMS_BASE (PAGE_OFFSET + PARAMS_OFFSET) +//#define PARAMS_OFFSET 0x0100 +//#define PARAMS_BASE (PAGE_OFFSET + PARAMS_OFFSET) #define SAFE_ADDR 0x50000000 diff --git a/include/asm-arm/arch-vnc/ide.h b/include/asm-arm/arch-vnc/ide.h index 35eff5c28fe5..c3761ab9074b 100644 --- a/include/asm-arm/arch-vnc/ide.h +++ b/include/asm-arm/arch-vnc/ide.h @@ -1 +1,42 @@ -/* no ide */ +/* + * linux/include/asm-arm/arch-vnc/ide.h + * + * Copyright (c) 1998 Russell King + * + * Modifications: + * 29-07-1998 RMK Major re-work of IDE architecture specific code + */ +#include + +/* + * Set up a hw structure for a specified data port, control port and IRQ. + * This should follow whatever the default interface uses. + */ +static __inline__ void +ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq) +{ + ide_ioreg_t reg = (ide_ioreg_t) data_port; + int i; + + memset(hw, 0, sizeof(*hw)); + + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { + hw->io_ports[i] = reg; + reg += 1; + } + hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port; + hw->irq = irq; +} + +/* + * This registers the standard ports for this architecture with the IDE + * driver. + */ +static __inline__ void +ide_init_default_hwifs(void) +{ + hw_regs_t hw; + + ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, IRQ_HARDDISK); + ide_register_hw(&hw, NULL); +} diff --git a/include/asm-arm/arch-vnc/io.h b/include/asm-arm/arch-vnc/io.h index 83d25d3634e8..f5cd3fd9593b 100644 --- a/include/asm-arm/arch-vnc/io.h +++ b/include/asm-arm/arch-vnc/io.h @@ -163,12 +163,12 @@ static inline unsigned short readw(unsigned int addr) return *(volatile unsigned short *)(0xe0000000 + (addr)); } -static inline void writew(unsigned long b, unsigned int addr) +static inline void writel(unsigned long b, unsigned int addr) { *(volatile unsigned long *)(0xe0000000 + (addr)) = b; } -static inline unsigned long readw(unsigned int addr) +static inline unsigned long readl(unsigned int addr) { return *(volatile unsigned long *)(0xe0000000 + (addr)); } diff --git a/include/asm-arm/arch-vnc/irq.h b/include/asm-arm/arch-vnc/irq.h index abf877dc96f2..10e4d0f9e8f6 100644 --- a/include/asm-arm/arch-vnc/irq.h +++ b/include/asm-arm/arch-vnc/irq.h @@ -7,6 +7,7 @@ * 22-08-1998 RMK Restructured IRQ routines */ +#include #include /* @@ -39,7 +40,7 @@ static void vnc_mask_csr_irq(unsigned int irq) static void vnc_unmask_csr_irq(unsigned int irq) { - *CSR_IRQ_DISABLE = fb_irq_mask[irq]; + *CSR_IRQ_ENABLE = fb_irq_mask[irq]; } static void vnc_mask_pic_lo_irq(unsigned int irq) @@ -49,11 +50,19 @@ static void vnc_mask_pic_lo_irq(unsigned int irq) outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO); } -static void vnc_unmask_pic_lo_irq(unsigned int irq) +static void vnc_mask_ack_pic_lo_irq(unsigned int irq) { unsigned int mask = 1 << (irq & 7); - outb(inb(PIC_MASK_LO) & ~mask, PIC_MASK_LO); + outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO); + outb(0x20, PIC_LO); +} + +static void vnc_unmask_pic_lo_irq(unsigned int irq) +{ + unsigned int mask = ~(1 << (irq & 7)); + + outb(inb(PIC_MASK_LO) & mask, PIC_MASK_LO); } static void vnc_mask_pic_hi_irq(unsigned int irq) @@ -63,6 +72,15 @@ static void vnc_mask_pic_hi_irq(unsigned int irq) outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI); } +static void vnc_mask_ack_pic_hi_irq(unsigned int irq) +{ + unsigned int mask = 1 << (irq & 7); + + outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI); + outb(0x62, PIC_LO); + outb(0x20, PIC_HI); +} + static void vnc_unmask_pic_hi_irq(unsigned int irq) { unsigned int mask = 1 << (irq & 7); @@ -70,6 +88,12 @@ static void vnc_unmask_pic_hi_irq(unsigned int irq) outb(inb(PIC_MASK_HI) & ~mask, PIC_MASK_HI); } +static void no_action(int irq, void *dev_id, struct pt_regs *regs) +{ +} + +static struct irqaction irq_cascade = { no_action, 0, 0, "cascade", NULL, NULL }; + static __inline__ void irq_init_irq(void) { unsigned int irq; @@ -97,13 +121,36 @@ static __inline__ void irq_init_irq(void) irq_desc[irq].mask = vnc_mask_csr_irq; irq_desc[irq].unmask = vnc_unmask_csr_irq; } else if (irq < 24) { - irq_desc[irq].mask_ack = vnc_mask_pic_lo_irq; +irq_desc[irq].probe_ok = 0; + irq_desc[irq].mask_ack = vnc_mask_ack_pic_lo_irq; irq_desc[irq].mask = vnc_mask_pic_lo_irq; irq_desc[irq].unmask = vnc_unmask_pic_lo_irq; } else { - irq_desc[irq].mask_ack = vnc_mask_pic_hi_irq; +irq_desc[irq].probe_ok = 0; + irq_desc[irq].mask_ack = vnc_mask_ack_pic_hi_irq; irq_desc[irq].mask = vnc_mask_pic_hi_irq; irq_desc[irq].unmask = vnc_unmask_pic_hi_irq; } } + + irq_desc[0].probe_ok = 0; + irq_desc[IRQ_SOFTIRQ].probe_ok = 0; + irq_desc[IRQ_CONRX].probe_ok = 0; + irq_desc[IRQ_CONTX].probe_ok = 0; + irq_desc[IRQ_TIMER0].probe_ok = 0; + irq_desc[IRQ_TIMER1].probe_ok = 0; + irq_desc[IRQ_TIMER2].probe_ok = 0; + irq_desc[IRQ_WATCHDOG].probe_ok = 0; + irq_desc[IRQ_DMA1].probe_ok = 0; + irq_desc[13].probe_ok = 0; + irq_desc[14].probe_ok = 0; + irq_desc[IRQ_PCI_ERR].probe_ok = 0; + irq_desc[IRQ_PIC_HI].probe_ok = 0; + irq_desc[29].probe_ok = 0; + irq_desc[31].probe_ok = 0; + + outb(0xff, PIC_MASK_LO); + outb(0xff, PIC_MASK_HI); + + setup_arm_irq(IRQ_PIC_HI, &irq_cascade); } diff --git a/include/asm-arm/arch-vnc/irqs.h b/include/asm-arm/arch-vnc/irqs.h index 37b48c43d82f..715439d1160e 100644 --- a/include/asm-arm/arch-vnc/irqs.h +++ b/include/asm-arm/arch-vnc/irqs.h @@ -47,8 +47,8 @@ #define IRQ_MASK_TIMER1 0x00000020 #define IRQ_MASK_TIMER2 0x00000040 #define IRQ_MASK_WATCHDOG 0x00000080 -#define IRQ_MASK_ETHERH10 0x00000100 -#define IRQ_MASK_ETHERH100 0x00000200 +#define IRQ_MASK_ETHER10 0x00000100 +#define IRQ_MASK_ETHER100 0x00000200 #define IRQ_MASK_VIDCOMP 0x00000400 #define IRQ_MASK_EXTERN_IRQ 0x00000800 #define IRQ_MASK_DMA1 0x00030000 diff --git a/include/asm-arm/arch-vnc/keyboard.h b/include/asm-arm/arch-vnc/keyboard.h index 4498ecc9bde7..2fa371ff9728 100644 --- a/include/asm-arm/arch-vnc/keyboard.h +++ b/include/asm-arm/arch-vnc/keyboard.h @@ -1,36 +1,38 @@ /* - * linux/include/asm-arm/arch-ebsa285/keyboard.h + * linux/include/asm-arm/arch-vnc/keyboard.h * - * Keyboard driver definitions for EBSA285 architecture + * Keyboard driver definitions for VNC architecture * * (C) 1998 Russell King */ -#include #include #define NR_SCANCODES 128 -#ifdef CONFIG_MAGIC_SYSRQ -static unsigned char kbd_sysrq_xlate[NR_SCANCODES]; -#endif +#define KEYBOARD_IRQ IRQ_KEYBOARD -#define kbd_setkeycode(sc,kc) (-EINVAL) -#define kbd_getkeycode(sc) (-EINVAL) +extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); +extern int pckbd_getkeycode(unsigned int scancode); +extern int pckbd_pretranslate(unsigned char scancode, char raw_mode); +extern int pckbd_translate(unsigned char scancode, unsigned char *keycode, + char raw_mode); +extern char pckbd_unexpected_up(unsigned char keycode); +extern void pckbd_leds(unsigned char leds); +extern void pckbd_init_hw(void); +extern unsigned char pckbd_sysrq_xlate[128]; -/* Prototype: int kbd_pretranslate(scancode, raw_mode) - * Returns : 0 to ignore scancode - */ -#define kbd_pretranslate(sc,rm) (1) +#define kbd_setkeycode pckbd_setkeycode +#define kbd_getkeycode pckbd_getkeycode +#define kbd_pretranslate pckbd_pretranslate +#define kbd_translate(sc, kcp, ufp, rm) ({ *ufp = sc & 0200; \ + pckbd_translate(sc & 0x7f, kcp, rm);}) -/* Prototype: int kbd_translate(scancode, *keycode, *up_flag, raw_mode) - * Returns : 0 to ignore scancode, *keycode set to keycode, *up_flag - * set to 0200 if scancode indicates release - */ -#define kbd_translate(sc, kcp, ufp, rm) (1) -#define kbd_unexpected_up(kc) (0200) -#define kbd_leds(leds) -#define kbd_init_hw() -//#define kbd_sysrq_xlate ps2kbd_sysrq_xlate +#define kbd_unexpected_up pckbd_unexpected_up +#define kbd_leds pckbd_leds +#define kbd_init_hw() pckbd_init_hw() +#define kbd_sysrq_xlate pckbd_sysrq_xlate #define kbd_disable_irq() #define kbd_enable_irq() + +#define SYSRQ_KEY 0x54 diff --git a/include/asm-arm/arch-vnc/mmu.h b/include/asm-arm/arch-vnc/mmu.h index 85307d71798b..64e334292988 100644 --- a/include/asm-arm/arch-vnc/mmu.h +++ b/include/asm-arm/arch-vnc/mmu.h @@ -19,8 +19,8 @@ #define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET) #define __virt_to_bus__is_a_macro -#define __virt_to_bus(x) (x) +#define __virt_to_bus(x) (x - 0xe0000000) #define __bus_to_virt__is_a_macro -#define __bus_to_virt(x) (x) +#define __bus_to_virt(x) (x + 0xe0000000) #endif diff --git a/include/asm-arm/arch-vnc/processor.h b/include/asm-arm/arch-vnc/processor.h index 5d84ad49881a..e752df4c01df 100644 --- a/include/asm-arm/arch-vnc/processor.h +++ b/include/asm-arm/arch-vnc/processor.h @@ -24,6 +24,7 @@ * space during mmap's. */ #define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr) #define INIT_MMAP \ { &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap } diff --git a/include/asm-arm/arch-vnc/system.h b/include/asm-arm/arch-vnc/system.h index a3fed312c23b..7fe88446096b 100644 --- a/include/asm-arm/arch-vnc/system.h +++ b/include/asm-arm/arch-vnc/system.h @@ -2,19 +2,36 @@ * linux/include/asm-arm/arch-ebsa285/system.h * * Copyright (c) 1996,1997,1998 Russell King. + * Copyright (c) 1998 Corel Computer Corp. */ #include +#include #include +#include -/* To reboot, we set up the 21285 watchdog and enable it. - * We then wait for it to timeout. - */ extern __inline__ void arch_hard_reset (void) { cli(); - *CSR_TIMER4_LOAD = 0x8000; - *CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16; - *CSR_SA110_CNTL |= 1 << 13; + + /* open up the SuperIO chip + */ + outb(0x87, 0x370); + outb(0x87, 0x370); + + /* aux function group 1 (Logical Device 7) + */ + outb(0x07, 0x370); + outb(0x07, 0x371); + + /* set GP16 for WD-TIMER output + */ + outb(0xE6, 0x370); + outb(0x00, 0x371); + + /* set a RED LED and toggle WD_TIMER for rebooting... + */ + outb(0xC4, 0x338); + while(1); } diff --git a/include/asm-arm/arch-vnc/time.h b/include/asm-arm/arch-vnc/time.h index 73f22844170a..595672e7b0d5 100644 --- a/include/asm-arm/arch-vnc/time.h +++ b/include/asm-arm/arch-vnc/time.h @@ -6,6 +6,11 @@ * -- Russell King. */ +#include + +#undef IRQ_TIMER +#define IRQ_TIMER IRQ_TIMER4 + extern __inline__ unsigned long gettimeoffset (void) { return 0; @@ -13,28 +18,157 @@ extern __inline__ unsigned long gettimeoffset (void) extern __inline__ int reset_timer (void) { - *CSR_TIMER1_CLR = 0; return 1; } +unsigned long set_rtc_mmss(unsigned long nowtime) +{ + int retval = 0; + int real_seconds, real_minutes, cmos_minutes; + unsigned char save_control, save_freq_select; + + save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ + CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); + + save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ + CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); + + cmos_minutes = CMOS_READ(RTC_MINUTES); + if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) + BCD_TO_BIN(cmos_minutes); + + /* + * since we're only adjusting minutes and seconds, + * don't interfere with hour overflow. This avoids + * messing with unknown time zones but requires your + * RTC not to be off by more than 15 minutes + */ + real_seconds = nowtime % 60; + real_minutes = nowtime / 60; + if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) + real_minutes += 30; /* correct for half hour time zone */ + real_minutes %= 60; + + if (abs(real_minutes - cmos_minutes) < 30) { + if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + BIN_TO_BCD(real_seconds); + BIN_TO_BCD(real_minutes); + } + CMOS_WRITE(real_seconds,RTC_SECONDS); + CMOS_WRITE(real_minutes,RTC_MINUTES); + } else + retval = -1; + + /* The following flags have to be released exactly in this order, + * otherwise the DS12887 (popular MC146818A clone with integrated + * battery and quartz) will not reset the oscillator and will not + * update precisely 500 ms later. You won't find this mentioned in + * the Dallas Semiconductor data sheets, but who believes data + * sheets anyway ... -- Markus Kuhn + */ + CMOS_WRITE(save_control, RTC_CONTROL); + CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + + return retval; +} + /* * We don't have a RTC to update! */ -#define update_rtc() +extern __inline__ void update_rtc(void) +{ + static long last_rtc_update = 0; /* last time the cmos clock got updated */ + + /* If we have an externally synchronized linux clock, then update + * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be + * called as close as possible to 500 ms before the new second starts. + */ + if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 && + xtime.tv_usec > 50000 - (tick >> 1) && + xtime.tv_usec < 50000 + (tick >> 1)) { + if (set_rtc_mmss(xtime.tv_sec) == 0) + last_rtc_update = xtime.tv_sec; + else + last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ + } +} + +extern __inline__ unsigned long get_cmos_time(void) +{ + unsigned int year, mon, day, hour, min, sec; + int i; + + // check to see if the RTC makes sense..... + if ((CMOS_READ(RTC_VALID) & RTC_VRT) == 0) + return mktime(1970, 1, 1, 0, 0, 0); + + /* The Linux interpretation of the CMOS clock register contents: + * When the Update-In-Progress (UIP) flag goes from 1 to 0, the + * RTC registers show the second which has precisely just started. + * Let's hope other operating systems interpret the RTC the same way. + */ + /* read RTC exactly on falling edge of update flag */ + for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ + if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) + break; + + for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ + if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) + break; + + do { /* Isn't this overkill ? UIP above should guarantee consistency */ + sec = CMOS_READ(RTC_SECONDS); + min = CMOS_READ(RTC_MINUTES); + hour = CMOS_READ(RTC_HOURS); + day = CMOS_READ(RTC_DAY_OF_MONTH); + mon = CMOS_READ(RTC_MONTH); + year = CMOS_READ(RTC_YEAR); + } while (sec != CMOS_READ(RTC_SECONDS)); + + if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + BCD_TO_BIN(sec); + BCD_TO_BIN(min); + BCD_TO_BIN(hour); + BCD_TO_BIN(day); + BCD_TO_BIN(mon); + BCD_TO_BIN(year); + } + if ((year += 1900) < 1970) + year += 100; + return mktime(year, mon, day, hour, min, sec); +} + +#define mSEC_10_from_14 ((14318180 + 100) / 200) /* * Set up timer interrupt, and return the current time in seconds. */ extern __inline__ unsigned long setup_timer (void) { - *CSR_TIMER1_CLR = 1; - *CSR_TIMER1_LOAD = LATCH; - *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16; + unsigned int c; + + /* Turn on the RTC */ + outb(13, 0x70); + if ((inb(0x71) & 0x80) == 0) + printk("RTC: *** warning: CMOS battery bad\n"); + + outb(10, 0x70); /* select control reg */ + outb(32, 0x71); /* make sure the divider is set */ + outb(11, 0x70); /* select other control reg */ + c = inb(0x71) & 0xfb; /* read it */ + outb(11, 0x70); + outb(c | 2, 0x71); /* turn on BCD counting and 24 hour clock mode */ + + /* enable PIT timer */ + /* set for periodic (4) and LSB/MSB write (0x30) */ + outb(0x34, 0x43); + outb((mSEC_10_from_14/6) & 0xFF, 0x40); + outb((mSEC_10_from_14/6) >> 8, 0x40); /* * Default the date to 1 Jan 1970 00:00:00 * You will have to run a time daemon to set the * clock correctly at bootup */ - return mktime(1970, 1, 1, 0, 0, 0); + return get_cmos_time(); } diff --git a/include/asm-arm/byteorder.h b/include/asm-arm/byteorder.h index 7b232d906d57..14273481bd8f 100644 --- a/include/asm-arm/byteorder.h +++ b/include/asm-arm/byteorder.h @@ -3,7 +3,10 @@ #include -#ifdef __GNUC__ +#if defined(__GNUC__) && __GNUC__ == 2 && __GNUC_MINOR__ < 80 + +/* Recent versions of GCC can do as well or better than this + on their own - we shouldn't interfere. */ static __inline__ __const__ __u32 ___arch__swab32(__u32 x) { diff --git a/include/asm-arm/dec21285.h b/include/asm-arm/dec21285.h new file mode 100644 index 000000000000..eadab0ee667c --- /dev/null +++ b/include/asm-arm/dec21285.h @@ -0,0 +1,127 @@ +/* + * include/asm-arm/dec21285.h + * + * Copyright (C) 1998 Russell King + */ +#define DC21285_PCI_IACK 0x79000000 +#define DC21285_ARMCSR_BASE 0x42000000 +#define DC21285_PCI_TYPE_0_CONFIG 0x7b000000 +#define DC21285_PCI_TYPE_1_CONFIG 0x7a000000 +#define DC21285_OUTBOUND_WRITE_FLUSH 0x78000000 +#define DC21285_FLASH 0x41000000 +#define DC21285_PCI_IO 0x7c000000 +#define DC21285_PCI_MEM 0x80000000 + +#ifndef __ASSEMBLY__ + +/* + * DEC21285 + */ +#define CSR_SA110_CNTL ((volatile unsigned long *)0xfe00013c) +#define CSR_PCIADDR_EXTN ((volatile unsigned long *)0xfe000140) +#define CSR_PREFETCHMEMRANGE ((volatile unsigned long *)0xfe000144) +#define CSR_XBUS_CYCLE ((volatile unsigned long *)0xfe000148) +#define CSR_XBUS_IOSTROBE ((volatile unsigned long *)0xfe00014c) +#define CSR_DOORBELL_PCI ((volatile unsigned long *)0xfe000150) +#define CSR_DOORBELL_SA110 ((volatile unsigned long *)0xfe000154) + +#define CSR_UARTDR ((volatile unsigned long *)0xfe000160) +#define CSR_RXSTAT ((volatile unsigned long *)0xfe000164) +#define CSR_H_UBRLCR ((volatile unsigned long *)0xfe000168) +#define CSR_M_UBRLCR ((volatile unsigned long *)0xfe00016c) +#define CSR_L_UBRLCR ((volatile unsigned long *)0xfe000170) +#define CSR_UARTCON ((volatile unsigned long *)0xfe000174) +#define CSR_UARTFLG ((volatile unsigned long *)0xfe000178) + +#define CSR_IRQ_STATUS ((volatile unsigned long *)0xfe000180) +#define CSR_IRQ_RAWSTATUS ((volatile unsigned long *)0xfe000184) +#define CSR_IRQ_ENABLE ((volatile unsigned long *)0xfe000188) +#define CSR_IRQ_DISABLE ((volatile unsigned long *)0xfe00018c) +#define CSR_IRQ_SOFT ((volatile unsigned long *)0xfe000190) + +#define CSR_FIQ_STATUS ((volatile unsigned long *)0xfe000280) +#define CSR_FIQ_RAWSTATUS ((volatile unsigned long *)0xfe000284) +#define CSR_FIQ_ENABLE ((volatile unsigned long *)0xfe000288) +#define CSR_FIQ_DISABLE ((volatile unsigned long *)0xfe00028c) +#define CSR_FIQ_SOFT ((volatile unsigned long *)0xfe000290) + +#define CSR_TIMER1_LOAD ((volatile unsigned long *)0xfe000300) +#define CSR_TIMER1_VALUE ((volatile unsigned long *)0xfe000304) +#define CSR_TIMER1_CNTL ((volatile unsigned long *)0xfe000308) +#define CSR_TIMER1_CLR ((volatile unsigned long *)0xfe00030c) + +#define CSR_TIMER2_LOAD ((volatile unsigned long *)0xfe000320) +#define CSR_TIMER2_VALUE ((volatile unsigned long *)0xfe000324) +#define CSR_TIMER2_CNTL ((volatile unsigned long *)0xfe000328) +#define CSR_TIMER2_CLR ((volatile unsigned long *)0xfe00032c) + +#define CSR_TIMER3_LOAD ((volatile unsigned long *)0xfe000340) +#define CSR_TIMER3_VALUE ((volatile unsigned long *)0xfe000344) +#define CSR_TIMER3_CNTL ((volatile unsigned long *)0xfe000348) +#define CSR_TIMER3_CLR ((volatile unsigned long *)0xfe00034c) + +#define CSR_TIMER4_LOAD ((volatile unsigned long *)0xfe000360) +#define CSR_TIMER4_VALUE ((volatile unsigned long *)0xfe000364) +#define CSR_TIMER4_CNTL ((volatile unsigned long *)0xfe000368) +#define CSR_TIMER4_CLR ((volatile unsigned long *)0xfe00036c) + +#else + +#define CSR_SA110_CNTL 0x13c +#define CSR_PCIADDR_EXTN 0x140 +#define CSR_PREFETCHMEMRANGE 0x144 +#define CSR_XBUS_CYCLE 0x148 +#define CSR_XBUS_IOSTROBE 0x14c +#define CSR_DOORBELL_PCI 0x150 +#define CSR_DOORBELL_SA110 0x154 + +#define CSR_UARTDR 0x160 +#define CSR_RXSTAT 0x164 +#define CSR_H_UBRLCR 0x168 +#define CSR_M_UBRLCR 0x16c +#define CSR_L_UBRLCR 0x170 +#define CSR_UARTCON 0x174 +#define CSR_UARTFLG 0x178 + +#define CSR_IRQ_STATUS 0x180 +#define CSR_IRQ_RAWSTATUS 0x184 +#define CSR_IRQ_ENABLE 0x188 +#define CSR_IRQ_DISABLE 0x18c +#define CSR_IRQ_SOFT 0x190 + +#define CSR_FIQ_STATUS 0x280 +#define CSR_FIQ_RAWSTATUS 0x284 +#define CSR_FIQ_ENABLE 0x288 +#define CSR_FIQ_DISABLE 0x28c +#define CSR_FIQ_SOFT 0x290 + +#define CSR_TIMER1_LOAD 0x300 +#define CSR_TIMER1_VALUE 0x304 +#define CSR_TIMER1_CNTL 0x308 +#define CSR_TIMER1_CLR 0x30c + +#define CSR_TIMER2_LOAD 0x320 +#define CSR_TIMER2_VALUE 0x324 +#define CSR_TIMER2_CNTL 0x328 +#define CSR_TIMER2_CLR 0x32c + +#define CSR_TIMER3_LOAD 0x340 +#define CSR_TIMER3_VALUE 0x344 +#define CSR_TIMER3_CNTL 0x348 +#define CSR_TIMER3_CLR 0x34c + +#define CSR_TIMER4_LOAD 0x360 +#define CSR_TIMER4_VALUE 0x364 +#define CSR_TIMER4_CNTL 0x368 +#define CSR_TIMER4_CLR 0x36c + +#endif + +#define TIMER_CNTL_ENABLE (1 << 7) +#define TIMER_CNTL_AUTORELOAD (1 << 6) +#define TIMER_CNTL_DIV1 (0) +#define TIMER_CNTL_DIV16 (1 << 2) +#define TIMER_CNTL_DIV256 (2 << 2) +#define TIMER_CNTL_CNTEXT (3 << 2) + + diff --git a/include/asm-arm/dma.h b/include/asm-arm/dma.h index d8b9f1d3a2b1..bb5ab18597ac 100644 --- a/include/asm-arm/dma.h +++ b/include/asm-arm/dma.h @@ -4,6 +4,7 @@ typedef unsigned int dmach_t; #include +#include #include typedef struct { @@ -13,6 +14,20 @@ typedef struct { extern const char dma_str[]; +extern spinlock_t dma_spin_lock; + +extern __inline__ unsigned long claim_dma_lock(void) +{ + unsigned long flags; + spin_lock_irqsave(&dma_spin_lock, flags); + return flags; +} + +extern __inline__ void release_dma_lock(unsigned long flags) +{ + spin_unlock_irqrestore(&dma_spin_lock, flags); +} + /* Clear the 'DMA Pointer Flip Flop'. * Write 0 for LSB/MSB, 1 for MSB/LSB access. * @@ -26,7 +41,7 @@ extern const char dma_str[]; * NOTE: This is an architecture specific function, and should * be hidden from the drivers */ -static __inline__ void set_dma_page(dmach_t channel, char pagenr) +extern __inline__ void set_dma_page(dmach_t channel, char pagenr) { printk(dma_str, "set_dma_page", channel); } diff --git a/include/asm-arm/ecard.h b/include/asm-arm/ecard.h index afc4acc14de0..0f60505f9559 100644 --- a/include/asm-arm/ecard.h +++ b/include/asm-arm/ecard.h @@ -31,6 +31,9 @@ #define MANU_ATOMWIDE 0x0017 #define PROD_ATOMWIDE_3PSERIAL 0x0090 +#define MANU_IRLAM_INSTRUMENTS 0x001f +#define MANU_IRLAM_INSTRUMENTS_ETHERN 0x5678 + #define MANU_OAK 0x0021 #define PROD_OAK_SCSI 0x0058 @@ -75,51 +78,48 @@ #define MAX_ECARDS 8 -/* Type of card's address space */ -typedef enum { +typedef enum { /* Cards address space */ ECARD_IOC, ECARD_MEMC, - ECARD_DEBI + ECARD_EASI } card_type_t; -/* Speed of card for ECARD_IOC address space */ -typedef enum { +typedef enum { /* Speed for ECARD_IOC space */ ECARD_SLOW = 0, ECARD_MEDIUM = 1, ECARD_FAST = 2, ECARD_SYNC = 3 } card_speed_t; -/* Card ID structure */ -typedef struct { +typedef struct { /* Card ID structure */ unsigned short manufacturer; unsigned short product; } card_ids; -/* External view of card ID information */ -struct in_ecld { - unsigned short product; - unsigned short manufacturer; - unsigned char ecld; - unsigned char country; - unsigned char fiqmask; - unsigned char irqmask; - unsigned long fiqaddr; - unsigned long irqaddr; +struct in_ecid { /* Packed card ID information */ + unsigned short product; /* Product code */ + unsigned short manufacturer; /* Manufacturer code */ + unsigned char id:4; /* Simple ID */ + unsigned char cd:1; /* Chunk dir present */ + unsigned char is:1; /* Interrupt status pointers */ + unsigned char w:2; /* Width */ + unsigned char country; /* Country */ + unsigned char irqmask; /* IRQ mask */ + unsigned char fiqmask; /* FIQ mask */ + unsigned long irqoff; /* IRQ offset */ + unsigned long fiqoff; /* FIQ offset */ }; typedef struct expansion_card ecard_t; +typedef unsigned long *loader_t; -/* Card handler routines */ -typedef struct { +typedef struct { /* Card handler routines */ void (*irqenable)(ecard_t *ec, int irqnr); void (*irqdisable)(ecard_t *ec, int irqnr); void (*fiqenable)(ecard_t *ec, int fiqnr); void (*fiqdisable)(ecard_t *ec, int fiqnr); } expansioncard_ops_t; -typedef unsigned long *loader_t; - /* * This contains all the info needed on an expansion card */ @@ -131,17 +131,19 @@ struct expansion_card { unsigned char fiqmask; /* FIQ mask */ unsigned char claimed; /* Card claimed? */ + void *irq_data; /* Data for use for IRQ by card */ + void *fiq_data; /* Data for use for FIQ by card */ + expansioncard_ops_t *ops; /* Enable/Disable Ops for card */ + CONST unsigned char slot_no; /* Slot number */ CONST unsigned char dma; /* DMA number (for request_dma) */ CONST unsigned char irq; /* IRQ number (for request_irq) */ CONST unsigned char fiq; /* FIQ number (for request_irq) */ - - CONST struct in_ecld cld; /* Card Identification */ - void *irq_data; /* Data for use for IRQ by card */ - void *fiq_data; /* Data for use for FIQ by card */ - expansioncard_ops_t *ops; /* Enable/Disable Ops for card */ + CONST card_type_t type; /* Type of card */ + CONST struct in_ecid cid; /* Card Identification */ /* Private internal data */ + const char *card_desc; /* Card description */ CONST unsigned int podaddr; /* Base Linux address for card */ CONST loader_t loader; /* loader program */ }; @@ -170,9 +172,9 @@ struct in_chunk_dir { extern void ecard_startfind (void); /* - * Find an expansion card with the correct cld, product and manufacturer code + * Find an expansion card with the correct cid, product and manufacturer code */ -extern struct expansion_card *ecard_find (int cld, const card_ids *ids); +extern struct expansion_card *ecard_find (int cid, const card_ids *ids); /* * Read a chunk from an expansion card @@ -193,25 +195,31 @@ extern unsigned int ecard_address (struct expansion_card *ec, card_type_t card_t * * External expansion card header as read from the card */ -struct ex_ecld { - unsigned char r_ecld; - unsigned char r_reserved[2]; - unsigned char r_product[2]; - unsigned char r_manufacturer[2]; - unsigned char r_country; - long r_fiqs; - long r_irqs; -#define e_ecld(x) ((x)->r_ecld) -#define e_cd(x) ((x)->r_reserved[0] & 1) -#define e_is(x) ((x)->r_reserved[0] & 2) -#define e_w(x) (((x)->r_reserved[0] & 12)>>2) -#define e_prod(x) ((x)->r_product[0]|((x)->r_product[1]<<8)) -#define e_manu(x) ((x)->r_manufacturer[0]|((x)->r_manufacturer[1]<<8)) -#define e_country(x) ((x)->r_country) -#define e_fiqmask(x) ((x)->r_fiqs & 0xff) -#define e_fiqaddr(x) ((x)->r_fiqs >> 8) -#define e_irqmask(x) ((x)->r_irqs & 0xff) -#define e_irqaddr(x) ((x)->r_irqs >> 8) +struct ex_ecid { + unsigned char r_irq:1; + unsigned char r_zero:1; + unsigned char r_fiq:1; + unsigned char r_id:4; + unsigned char r_a:1; + + unsigned char r_cd:1; + unsigned char r_is:1; + unsigned char r_w:2; + unsigned char r_r1:4; + + unsigned char r_r2:8; + + unsigned char r_prod[2]; + + unsigned char r_manu[2]; + + unsigned char r_country; + + unsigned char r_irqmask; + unsigned char r_irqoff[3]; + + unsigned char r_fiqmask; + unsigned char r_fiqoff[3]; }; /* diff --git a/include/asm-arm/elf.h b/include/asm-arm/elf.h index c99a67292eb5..8b0980053571 100644 --- a/include/asm-arm/elf.h +++ b/include/asm-arm/elf.h @@ -6,6 +6,7 @@ */ #include +#include #include typedef unsigned long elf_greg_t; @@ -20,7 +21,7 @@ typedef struct { void *null; } elf_fpregset_t; /* * This is used to ensure we don't load something for the wrong architecture. */ -#define elf_check_arch(x) ( ((x) == EM_ARM) ) +#define elf_check_arch(x) ( ((x)->e_machine == EM_ARM) && (ELF_PROC_OK((x))) ) /* * These are used to set parameters in the core dumps. @@ -30,7 +31,6 @@ typedef struct { void *null; } elf_fpregset_t; #define ELF_ARCH EM_ARM #define USE_ELF_CORE_DUMP -#define ELF_EXEC_PAGESIZE 4096 /* This is the location that an ET_DYN program is loaded if exec'ed. Typical use of this is to invoke "./ld.so someprog" to test out a new version of @@ -65,9 +65,4 @@ typedef struct { void *null; } elf_fpregset_t; extern char elf_platform[]; #define ELF_PLATFORM (elf_platform) -#ifdef __KERNEL__ -#define SET_PERSONALITY(ex,ibcs2) \ - current->personality = PER_LINUX_32BIT -#endif - #endif diff --git a/include/asm-arm/hardware.h b/include/asm-arm/hardware.h index c21abeed3bec..b83032fcad6c 100644 --- a/include/asm-arm/hardware.h +++ b/include/asm-arm/hardware.h @@ -85,7 +85,7 @@ do { \ #ifdef HAS_IOMD #ifndef __ASSEMBLER__ -#define __IOMD(offset) (IOMD_BASE + (offset >> 2)) +#define __IOMD(offset) (IO_IOMD_BASE + (offset >> 2)) #else #define __IOMD(offset) offset #endif diff --git a/include/asm-arm/ide.h b/include/asm-arm/ide.h index 2ead7b36a13a..76da8806b6a4 100644 --- a/include/asm-arm/ide.h +++ b/include/asm-arm/ide.h @@ -13,8 +13,6 @@ #ifdef __KERNEL__ -typedef unsigned long ide_ioreg_t; - #ifndef MAX_HWIFS #define MAX_HWIFS 4 #endif @@ -34,51 +32,19 @@ typedef union { } b; } select_t; -static __inline__ int ide_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), - unsigned long flags, const char *device, void *dev_id) -{ - return request_irq(irq, handler, flags, device, dev_id); -} - -static __inline__ void ide_free_irq(unsigned int irq, void *dev_id) -{ - free_irq(irq, dev_id); -} - -static __inline__ int ide_check_region (ide_ioreg_t from, unsigned int extent) -{ - return check_region(from, extent); -} - -static __inline__ void ide_request_region (ide_ioreg_t from, unsigned int extent, const char *name) -{ - request_region(from, extent, name); -} - -static __inline__ void ide_release_region (ide_ioreg_t from, unsigned int extent) -{ - release_region(from, extent); -} +#define ide_request_irq(irq,hand,flg,dev,id) request_irq((irq),(hand),(flg),(dev),(id)) +#define ide_free_irq(irq,dev_id) free_irq((irq), (dev_id)) +#define ide_check_region(from,extent) check_region((from), (extent)) +#define ide_request_region(from,extent,name) request_region((from), (extent), (name)) +#define ide_release_region(from,extent) release_region((from), (extent)) /* * The following are not needed for the non-m68k ports */ -static __inline__ int ide_ack_intr (ide_ioreg_t status_port, ide_ioreg_t irq_port) -{ - return(1); -} - -static __inline__ void ide_fix_driveid(struct hd_driveid *id) -{ -} - -static __inline__ void ide_release_lock (int *ide_lock) -{ -} - -static __inline__ void ide_get_lock (int *ide_lock, void (*handler)(int, void *, struct pt_regs *), void *data) -{ -} +#define ide_ack_intr(hwif) (1) +#define ide_fix_driveid(id) do {} while (0) +#define ide_release_lock(lock) do {} while (0) +#define ide_get_lock(lock, hdlr, data) do {} while (0) #endif /* __KERNEL__ */ diff --git a/include/asm-arm/irq.h b/include/asm-arm/irq.h index 59770101ee9e..0e8c4ad27bc9 100644 --- a/include/asm-arm/irq.h +++ b/include/asm-arm/irq.h @@ -3,7 +3,9 @@ #include +#ifndef irq_cannonicalize #define irq_cannonicalize(i) (i) +#endif #ifndef NR_IRQS #define NR_IRQS 128 diff --git a/include/asm-arm/keyboard.h b/include/asm-arm/keyboard.h index 6b64ec6afeb7..9514b470ac0a 100644 --- a/include/asm-arm/keyboard.h +++ b/include/asm-arm/keyboard.h @@ -19,8 +19,6 @@ #include -#define SYSRQ_KEY 13 - #endif /* __KERNEL__ */ #endif /* __ASM_ARM_KEYBOARD_H */ diff --git a/include/asm-arm/linux_logo.h b/include/asm-arm/linux_logo.h index 9eeae361987d..35ee86403650 100644 --- a/include/asm-arm/linux_logo.h +++ b/include/asm-arm/linux_logo.h @@ -11,13 +11,16 @@ #define linux_logo_banner "ARM Linux version " UTS_RELEASE -#define LINUX_LOGO_COLORS 221 +#define LINUX_LOGO_COLORS 214 #ifdef INCLUDE_LINUX_LOGO_DATA +#define INCLUDE_LINUX_LOGOBW #define INCLUDE_LINUX_LOGO16 + #include +#else /* prototypes only */ extern unsigned char linux_logo_red[]; diff --git a/include/asm-arm/md.h b/include/asm-arm/md.h new file mode 100644 index 000000000000..0a2c5dd01c0c --- /dev/null +++ b/include/asm-arm/md.h @@ -0,0 +1,13 @@ +/* $Id: md.h,v 1.1 1997/12/15 15:11:57 jj Exp $ + * md.h: High speed xor_block operation for RAID4/5 + * + */ + +#ifndef __ASM_MD_H +#define __ASM_MD_H + +/* #define HAVE_ARCH_XORBLOCK */ + +#define MD_XORBLOCK_ALIGNMENT sizeof(long) + +#endif /* __ASM_MD_H */ diff --git a/include/asm-arm/posix_types.h b/include/asm-arm/posix_types.h index cff51a2890fe..4c02ac5feab6 100644 --- a/include/asm-arm/posix_types.h +++ b/include/asm-arm/posix_types.h @@ -1,7 +1,7 @@ /* * linux/include/asm-arm/posix_types.h * - * Copyright (c) 1996 Russell King. + * Copyright (c) 1996-1998 Russell King. * * Changelog: * 27-06-1996 RMK Created @@ -9,8 +9,6 @@ #ifndef __ARCH_ARM_POSIX_TYPES_H #define __ARCH_ARM_POSIX_TYPES_H -#include - /* * This file is generally used by user-level software, so you need to * be a little careful about namespace pollution etc. Also, we cannot @@ -26,11 +24,7 @@ typedef int __kernel_pid_t; typedef unsigned short __kernel_ipc_pid_t; typedef unsigned short __kernel_uid_t; typedef unsigned short __kernel_gid_t; -#ifdef CONFIG_BINUTILS_NEW -typedef long unsigned int __kernel_size_t; -#else typedef unsigned int __kernel_size_t; -#endif typedef int __kernel_ssize_t; typedef int __kernel_ptrdiff_t; typedef long __kernel_time_t; diff --git a/include/asm-arm/proc-armo/elf.h b/include/asm-arm/proc-armo/elf.h new file mode 100644 index 000000000000..535deef3163d --- /dev/null +++ b/include/asm-arm/proc-armo/elf.h @@ -0,0 +1,19 @@ +/* + * ELF definitions for 26-bit CPUs + */ + +#define ELF_EXEC_PAGESIZE 32768 + +#if 0 /* not yet */ +#define ELF_PROC_OK(x) \ + ((x)->e_flags & EF_ARM_APCS26) +#else +#define ELF_PROC_OK(x) (1) +#endif + +#ifdef __KERNEL__ + +#define SET_PERSONALITY(ex,ibcs2) \ + current->personality = PER_LINUX + +#endif diff --git a/include/asm-arm/proc-armo/pgtable.h b/include/asm-arm/proc-armo/pgtable.h index 10631f7b2ecc..84bea0982599 100644 --- a/include/asm-arm/proc-armo/pgtable.h +++ b/include/asm-arm/proc-armo/pgtable.h @@ -119,13 +119,6 @@ extern __inline__ void update_memc_addr(struct mm_struct *mm, unsigned long addr #define PTRS_PER_PGD 32 #define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE) -/* Just any arbitrary offset to the start of the vmalloc VM area: the - * current 8MB value just means that there will be a 8MB "hole" after the - * physical memory until the kernel virtual memory starts. That means that - * any out-of-bounds memory accesses will hopefully be caught. - * The vmalloc() routines leaves a hole of 4kB between each vmalloced - * area for the same reason. ;) - */ #define VMALLOC_START 0x01a00000 #define VMALLOC_VMADDR(x) ((unsigned long)(x)) #define VMALLOC_END 0x01c00000 diff --git a/include/asm-arm/proc-armo/processor.h b/include/asm-arm/proc-armo/processor.h index f76b404c5e1b..4a8b60d10450 100644 --- a/include/asm-arm/proc-armo/processor.h +++ b/include/asm-arm/proc-armo/processor.h @@ -9,6 +9,7 @@ * 26-09-1996 RMK Added 'EXTRA_THREAD_STRUCT*' * 28-09-1996 RMK Moved start_thread into the processor dependencies * 11-01-1998 RMK Added new uaccess_t + * 09-09-1998 PJB Delete redundant `wp_works_ok' */ #ifndef __ASM_PROC_PROCESSOR_H #define __ASM_PROC_PROCESSOR_H @@ -20,12 +21,6 @@ #define KERNEL_STACK_SIZE 4096 -/* - * on arm2,3 wp does not work - */ -#define wp_works_ok 0 -#define wp_works_ok__is_a_macro /* for versions in ksyms.c */ - struct context_save_struct { unsigned long r4; unsigned long r5; diff --git a/include/asm-arm/proc-armo/system.h b/include/asm-arm/proc-armo/system.h index a1c2d01cb961..dee91008c277 100644 --- a/include/asm-arm/proc-armo/system.h +++ b/include/asm-arm/proc-armo/system.h @@ -19,6 +19,7 @@ extern __inline__ unsigned long __xchg(unsigned long x, volatile void *ptr, int case 4: return processor.u.armv2._xchg_4(x, ptr); default: arm_invalidptr(xchg_str, size); } + return 0; } /* diff --git a/include/asm-arm/proc-armv/elf.h b/include/asm-arm/proc-armv/elf.h new file mode 100644 index 000000000000..f82a786dbe67 --- /dev/null +++ b/include/asm-arm/proc-armv/elf.h @@ -0,0 +1,21 @@ +/* + * ELF definitions for 32-bit CPUs + */ + +#define ELF_EXEC_PAGESIZE 4096 + +/* We can execute both 32-bit and 26-bit code. */ +#define ELF_PROC_OK(x) (1) + +#ifdef __KERNEL__ + +#if 0 /* not yet */ +#define SET_PERSONALITY(ex,ibcs2) \ + current_personality = (ex->e_flags & EF_ARM_APCS26) ? \ + PER_LINUX : PER_LINUX_32BIT +#else +#define SET_PERSONALITY(ex,ibcs2) \ + current->personality = PER_LINUX_32BIT +#endif + +#endif diff --git a/include/asm-arm/proc-armv/io.h b/include/asm-arm/proc-armv/io.h index 949d41010c8e..461da303f73e 100644 --- a/include/asm-arm/proc-armv/io.h +++ b/include/asm-arm/proc-armv/io.h @@ -22,17 +22,17 @@ #include -#define dma_cache_inv(_start,_size) \ - do { \ - processor.u.armv3v4._cache_purge_area(_start,(_start+_size)); \ - } while (0) +extern inline void dma_cache_inv(unsigned long start, unsigned long size) +{ + processor.u.armv3v4._cache_purge_area(start, start + size); +} -#define dma_cache_wback(_start,_size) \ - do { \ - processor.u.armv3v4._cache_wback_area(_start,(_start+_size)); \ - } while (0) +extern inline void dma_cache_wback(unsigned long start, unsigned long size) +{ + processor.u.armv3v4._cache_wback_area(start, start + size); +} -#define dma_cache_wback_inv(_start,_size) \ - do { \ - processor.u.armv3v4._flush_cache_area(_start,(_start+_size),0); \ - } while (0) +extern inline void dma_cache_wback_inv(unsigned long start, unsigned long size) +{ + processor.u.armv3v4._flush_cache_area(start, start + size, 0); +} diff --git a/include/asm-arm/proc-armv/processor.h b/include/asm-arm/proc-armv/processor.h index 294dead681e8..88b277ea75aa 100644 --- a/include/asm-arm/proc-armv/processor.h +++ b/include/asm-arm/proc-armv/processor.h @@ -7,6 +7,7 @@ * 20-09-1996 RMK Created * 26-09-1996 RMK Added 'EXTRA_THREAD_STRUCT*' * 28-09-1996 RMK Moved start_thread into the processor dependencies + * 09-09-1998 PJB Delete redundant `wp_works_ok' */ #ifndef __ASM_PROC_PROCESSOR_H #define __ASM_PROC_PROCESSOR_H @@ -15,12 +16,6 @@ #define KERNEL_STACK_SIZE PAGE_SIZE -/* - * on arm2,3 wp does not work - */ -#define wp_works_ok 0 -#define wp_works_ok__is_a_macro /* for versions in ksyms.c */ - struct context_save_struct { unsigned long cpsr; unsigned long r4; diff --git a/include/asm-arm/proc-armv/uaccess.h b/include/asm-arm/proc-armv/uaccess.h index acadb35a3478..d5e187407a76 100644 --- a/include/asm-arm/proc-armv/uaccess.h +++ b/include/asm-arm/proc-armv/uaccess.h @@ -11,6 +11,8 @@ * DOMAIN_USER - domain 0 includes all user memory only */ +#include + #define DOMAIN_CLIENT 1 #define DOMAIN_MANAGER 3 @@ -35,7 +37,7 @@ * Note that this is actually 0x1,0000,0000 */ #define KERNEL_DS 0x00000000 -#define USER_DS 0xc0000000 +#define USER_DS PAGE_OFFSET #define get_ds() (KERNEL_DS) #define get_fs() (current->addr_limit) @@ -50,13 +52,10 @@ extern __inline__ void set_fs (mm_segment_t fs) : "r" (fs ? USER_DOMAIN : KERNEL_DOMAIN)); } -/* - * a + s <= 2^32 -> C = 0 || Z = 0 (LS) - * (a + s) <= l -> C = 0 || Z = 0 (LS) - */ +/* We use 33-bit arithmetic here... */ #define __range_ok(addr,size) ({ \ unsigned long flag, sum; \ - __asm__ __volatile__("adds %1, %2, %3; cmpls %1, %0; movls %0, #0" \ + __asm__ __volatile__("adds %1, %2, %3; sbccs %1, %1, %0; movcc %0, #0" \ : "=&r" (flag), "=&r" (sum) \ : "r" (addr), "Ir" (size), "0" (current->addr_limit) \ : "cc"); \ diff --git a/include/asm-arm/signal.h b/include/asm-arm/signal.h index 08b5edb509f3..0045494741c7 100644 --- a/include/asm-arm/signal.h +++ b/include/asm-arm/signal.h @@ -132,6 +132,7 @@ typedef void (*__sighandler_t)(int); #define SIG_IGN ((__sighandler_t)1) /* ignore signal */ #define SIG_ERR ((__sighandler_t)-1) /* error return from signal */ +#ifdef __KERNEL__ struct old_sigaction { __sighandler_t sa_handler; old_sigset_t sa_mask; @@ -150,6 +151,24 @@ struct k_sigaction { struct sigaction sa; }; +#else +/* Here we must cater to libcs that poke about in kernel headers. */ + +struct sigaction { + union { + __sighandler_t _sa_handler; + void (*_sa_sigaction)(int, struct siginfo *, void *); + } _u; + sigset_t sa_mask; + unsigned long sa_flags; + void (*sa_restorer)(void); +}; + +#define sa_handler _u._sa_handler +#define sa_sigaction _u._sa_sigaction + +#endif /* __KERNEL__ */ + typedef struct sigaltstack { void *ss_sp; int ss_flags; diff --git a/include/asm-arm/socket.h b/include/asm-arm/socket.h index 91de70e6ec98..d0d2ddb3625b 100644 --- a/include/asm-arm/socket.h +++ b/include/asm-arm/socket.h @@ -35,4 +35,8 @@ #define SO_BINDTODEVICE 25 +/* Socket filtering */ +#define SO_ATTACH_FILTER 26 +#define SO_DETACH_FILTER 27 + #endif /* _ASM_SOCKET_H */ diff --git a/include/asm-arm/spinlock.h b/include/asm-arm/spinlock.h index e72553f1a6f3..5a53935c0bf3 100644 --- a/include/asm-arm/spinlock.h +++ b/include/asm-arm/spinlock.h @@ -37,8 +37,13 @@ * irq-safe write-lock, but readers can get non-irqsafe * read-locks. */ -typedef struct { } rwlock_t; -#define RW_LOCK_UNLOCKED { } +#if (__GNUC__ > 2) || (__GNUC_MINOR__ >= 8) + typedef struct { } rwlock_t; +# define RW_LOCK_UNLOCKED { } +#else + typedef unsigned char rwlock_t; +# define RW_LOCK_UNLOCKED 0 +#endif #define read_lock(lock) do { } while(0) #define read_unlock(lock) do { } while(0) diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h index 1d7e28b0b004..91c08d668869 100644 --- a/include/asm-arm/system.h +++ b/include/asm-arm/system.h @@ -1,6 +1,8 @@ #ifndef __ASM_ARM_SYSTEM_H #define __ASM_ARM_SYSTEM_H +#include + /* The type of machine we're running on */ extern unsigned int machine_type; #define MACH_TYPE_EBSA110 0 @@ -11,6 +13,29 @@ extern unsigned int machine_type; #define MACH_TYPE_CATS 6 #define MACH_TYPE_TBOX 7 +#ifdef CONFIG_ARCH_EBSA285 +#define machine_is_ebsa285() (1) +#else +#define machine_is_ebsa285() (0) +#endif + +#ifdef CONFIG_ARCH_VNC +#define machine_is_netwinder() (1) +#else +#define machine_is_netwinder() (0) +#endif + +#if defined(CONFIG_CATS) +#define machine_is_cats() (machine_type == MACH_TYPE_CATS) +#else +#define machine_is_cats() (0) +#endif + +#if 0 +#define machine_is_ebsa285() (machine_type == MACH_TYPE_EBSA285) +#define machine_is_netwinder() (machine_type == MACH_TYPE_NETWINDER) +#endif + #include #include diff --git a/include/asm-i386/mca_dma.h b/include/asm-i386/mca_dma.h new file mode 100644 index 000000000000..791152f3d093 --- /dev/null +++ b/include/asm-i386/mca_dma.h @@ -0,0 +1,126 @@ +#ifndef MCA_DMA_H +#define MCA_DMA_H + +#include +#include + +/* + * Microchannel specific DMA stuff. DMA on an MCA machine is fairly similar to + * standard PC dma, but it certainly has its quirks. DMA register addresses + * are in a different place and there are some added functions. Most of this + * should be pretty obvious on inspection. Note that the user must divide + * count by 2 when using 16-bit dma; that is not handled by these functions. + * + * Ramen Noodles are yummy. + * + * 1998 Tymm Twillman + */ + +/* + * Registers that are used by the DMA controller; FN is the function register + * (tell the controller what to do) and EXE is the execution register (how + * to do it) + */ + +#define MCA_DMA_REG_FN 0x18 +#define MCA_DMA_REG_EXE 0x1A + +/* + * Functions that the DMA controller can do + */ + +#define MCA_DMA_FN_SET_IO 0x00 +#define MCA_DMA_FN_SET_ADDR 0x20 +#define MCA_DMA_FN_GET_ADDR 0x30 +#define MCA_DMA_FN_SET_COUNT 0x40 +#define MCA_DMA_FN_GET_COUNT 0x50 +#define MCA_DMA_FN_GET_STATUS 0x60 +#define MCA_DMA_FN_SET_MODE 0x70 +#define MCA_DMA_FN_SET_ARBUS 0x80 +#define MCA_DMA_FN_MASK 0x90 +#define MCA_DMA_FN_RESET_MASK 0xA0 +#define MCA_DMA_FN_MASTER_CLEAR 0xD0 + +/* + * Modes (used by setting MCA_DMA_FN_MODE in the function register) + * + * Note that the MODE_READ is read from memory (write to device), and + * MODE_WRITE is vice-versa. + */ + +#define MCA_DMA_MODE_XFER 0x04 /* read by default */ +#define MCA_DMA_MODE_READ 0x04 /* same as XFER */ +#define MCA_DMA_MODE_WRITE 0x08 /* OR with MODE_XFER to use */ +#define MCA_DMA_MODE_IO 0x01 /* DMA from IO register */ +#define MCA_DMA_MODE_16 0x40 /* 16 bit xfers */ + + + +static __inline__ void mca_enable_dma(unsigned int dmanr) +{ + outb(MCA_DMA_FN_RESET_MASK | dmanr, MCA_DMA_REG_FN); +} + +static __inline__ void mca_disable_dma(unsigned int dmanr) +{ + outb(MCA_DMA_FN_MASK | dmanr, MCA_DMA_REG_FN); +} + +static __inline__ void mca_set_dma_addr(unsigned int dmanr, unsigned int a) +{ + outb(MCA_DMA_FN_SET_ADDR | dmanr, MCA_DMA_REG_FN); + outb(a & 0xff, MCA_DMA_REG_EXE); + outb((a >> 8) & 0xff, MCA_DMA_REG_EXE); + outb((a >> 16) & 0xff, MCA_DMA_REG_EXE); +} + +static __inline__ unsigned int mca_get_dma_addr(unsigned int dmanr) +{ + unsigned int addr; + + outb(MCA_DMA_FN_GET_ADDR | dmanr, MCA_DMA_REG_FN); + addr = inb(MCA_DMA_REG_EXE); + addr |= inb(MCA_DMA_REG_EXE) << 8; + addr |= inb(MCA_DMA_REG_EXE) << 16; + + return addr; +} + +static __inline__ void mca_set_dma_count(unsigned int dmanr, unsigned int count) +{ + count--; /* transfers one more than count -- correct for this */ + + outb(MCA_DMA_FN_SET_COUNT | dmanr, MCA_DMA_REG_FN); + outb(count & 0xff, MCA_DMA_REG_EXE); + outb((count >> 8) & 0xff, MCA_DMA_REG_EXE); +} + +static __inline__ unsigned int mca_get_dma_residue(unsigned int dmanr) +{ + unsigned short count; + + outb(MCA_DMA_FN_GET_COUNT | dmanr, MCA_DMA_REG_FN); + count = 1 + inb(MCA_DMA_REG_EXE); + count += inb(MCA_DMA_REG_EXE) << 8; + + return count; +} + +static __inline__ void mca_set_dma_io(unsigned int dmanr, unsigned int io_addr) +{ + /* + * DMA from a port address -- set the io address + */ + + outb(MCA_DMA_FN_SET_IO | dmanr, MCA_DMA_REG_FN); + outb(io_addr & 0xff, MCA_DMA_REG_EXE); + outb((io_addr >> 8) & 0xff, MCA_DMA_REG_EXE); +} + +static __inline__ void mca_set_dma_mode(unsigned int dmanr, unsigned int mode) +{ + outb(MCA_DMA_FN_SET_MODE | dmanr, MCA_DMA_REG_FN); + outb(mode, MCA_DMA_REG_EXE); +} + +#endif MCA_DMA_H diff --git a/include/asm-i386/smp.h b/include/asm-i386/smp.h index 33dbab5bf650..933470e1c82c 100644 --- a/include/asm-i386/smp.h +++ b/include/asm-i386/smp.h @@ -237,7 +237,7 @@ extern __inline int hard_smp_processor_id(void) * processes are run. */ -#define PROC_CHANGE_PENALTY 20 /* Schedule penalty */ +#define PROC_CHANGE_PENALTY 15 /* Schedule penalty */ #define SMP_FROM_INT 1 #define SMP_FROM_SYSCALL 2 diff --git a/include/asm-m68k/bvme6000hw.h b/include/asm-m68k/bvme6000hw.h index 0218c29dcc73..853120a047f4 100644 --- a/include/asm-m68k/bvme6000hw.h +++ b/include/asm-m68k/bvme6000hw.h @@ -98,7 +98,7 @@ typedef struct { #define BVME_CONFIG_REG 0xff500003 -#define config_reg_ptr (unsigned char *)BVME_CONFIG_REG +#define config_reg_ptr (volatile unsigned char *)BVME_CONFIG_REG #define BVME_CONFIG_SW1 0x08 #define BVME_CONFIG_SW2 0x04 @@ -126,4 +126,24 @@ typedef struct { #define BVME_IRQ_SCCA_RX 0x4c #define BVME_IRQ_SCCA_SPCOND 0x4e +/* Address control registers */ + +#define BVME_ACR_A32VBA 0xff400003 +#define BVME_ACR_A32MSK 0xff410003 +#define BVME_ACR_A24VBA 0xff420003 +#define BVME_ACR_A24MSK 0xff430003 +#define BVME_ACR_A16VBA 0xff440003 +#define BVME_ACR_A32LBA 0xff450003 +#define BVME_ACR_A24LBA 0xff460003 +#define BVME_ACR_ADDRCTL 0xff470003 + +#define bvme_acr_a32vba *(volatile unsigned char *)BVME_ACR_A32VBA +#define bvme_acr_a32msk *(volatile unsigned char *)BVME_ACR_A32MSK +#define bvme_acr_a24vba *(volatile unsigned char *)BVME_ACR_A24VBA +#define bvme_acr_a24msk *(volatile unsigned char *)BVME_ACR_A24MSK +#define bvme_acr_a16vba *(volatile unsigned char *)BVME_ACR_A16VBA +#define bvme_acr_a32lba *(volatile unsigned char *)BVME_ACR_A32LBA +#define bvme_acr_a24lba *(volatile unsigned char *)BVME_ACR_A24LBA +#define bvme_acr_addrctl *(volatile unsigned char *)BVME_ACR_ADDRCTL + #endif diff --git a/include/asm-m68k/ipc.h b/include/asm-m68k/ipc.h index f1a75cc1d89e..96441c86ca30 100644 --- a/include/asm-m68k/ipc.h +++ b/include/asm-m68k/ipc.h @@ -23,6 +23,9 @@ struct ipc_kludge { #define SHMGET 23 #define SHMCTL 24 +/* Used by the DIPC package, try and avoid reusing it */ +#define DIPC 25 + #define IPCCALL(version,op) ((version)<<16 | (op)) #endif diff --git a/include/asm-m68k/pgtable.h b/include/asm-m68k/pgtable.h index 1dbc17608e77..7962dbade5ff 100644 --- a/include/asm-m68k/pgtable.h +++ b/include/asm-m68k/pgtable.h @@ -428,7 +428,7 @@ extern pte_t * __bad_pagetable(void); #define mk_pte(page, pgprot) \ ({ pte_t __pte; pte_val(__pte) = virt_to_phys((void *)page) + pgprot_val(pgprot); __pte; }) #define mk_pte_phys(physpage, pgprot) \ -({ pte_t __pte; pte_val(__pte) = virt_to_phys((void *)physpage) + pgprot_val(pgprot); __pte; }) +({ pte_t __pte; pte_val(__pte) = (unsigned long)physpage + pgprot_val(pgprot); __pte; }) extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; } diff --git a/include/asm-m68k/semaphore.h b/include/asm-m68k/semaphore.h index 50aabc1c8333..ebfaf173a14b 100644 --- a/include/asm-m68k/semaphore.h +++ b/include/asm-m68k/semaphore.h @@ -28,6 +28,7 @@ asmlinkage int __down_failed_interruptible(void /* params in registers */); asmlinkage void __up_wakeup(void /* special register calling convention */); extern void __down(struct semaphore * sem); +extern int __down_interruptible(struct semaphore * sem); extern void __up(struct semaphore * sem); #define sema_init(sem, val) atomic_set(&((sem)->count), val) diff --git a/include/asm-m68k/spinlock.h b/include/asm-m68k/spinlock.h index 6c049a124f78..1c3ace986aaa 100644 --- a/include/asm-m68k/spinlock.h +++ b/include/asm-m68k/spinlock.h @@ -10,10 +10,10 @@ */ #if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8) typedef struct { } spinlock_t; -#define SPIN_LOCK_UNLOCKED { } +#define SPIN_LOCK_UNLOCKED (spinlock_t) { } #else typedef struct { int gcc_is_buggy; } spinlock_t; -#define SPIN_LOCK_UNLOCKED { 0 } +#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } #endif #define spin_lock_init(lock) do { } while(0) @@ -38,9 +38,16 @@ typedef struct { int gcc_is_buggy; } spinlock_t; * can "mix" irq-safe locks - any writer needs to get a * irq-safe write-lock, but readers can get non-irqsafe * read-locks. + * + * Gcc-2.7.x has a nasty bug with empty initializers. */ +#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8) typedef struct { } rwlock_t; -#define RW_LOCK_UNLOCKED { } +#define RW_LOCK_UNLOCKED (rwlock_t) { } +#else +typedef struct { int gcc_is_buggy; } rwlock_t; +#define RW_LOCK_UNLOCKED (rwlock_t) { 0 } +#endif #define read_lock(lock) do { } while(0) #define read_unlock(lock) do { } while(0) diff --git a/include/asm-m68k/string.h b/include/asm-m68k/string.h index 796f6f16ecb0..710288a1a12a 100644 --- a/include/asm-m68k/string.h +++ b/include/asm-m68k/string.h @@ -1,7 +1,7 @@ #ifndef _M68K_STRING_H_ #define _M68K_STRING_H_ -#include +#include #include #define __HAVE_ARCH_STRCPY @@ -315,7 +315,7 @@ extern inline void * __memset_page(void * s,int c,size_t count) data = c | (c << 8); data |= data << 16; -#if defined(CONFIG_OPTIMIZE_040) || defined(CONFIG_OPTIMIZE_060) +#ifdef CPU_M68040_OR_M68060_ONLY if (((unsigned long) s) & 0x0f) memset(s, c, count); @@ -386,7 +386,7 @@ extern inline void * __memcpy_page(void * to, const void * from, size_t count) unsigned long tmp; void *xto = to; -#if defined(CONFIG_OPTIMIZE_040) || defined(CONFIG_OPTIMIZE_060) +#ifdef CPU_M68040_OR_M68060_ONLY if (((unsigned long) to | (unsigned long) from) & 0x0f) return memcpy(to, from, count); diff --git a/include/asm-m68k/uaccess.h b/include/asm-m68k/uaccess.h index a477bce011f2..115219878de0 100644 --- a/include/asm-m68k/uaccess.h +++ b/include/asm-m68k/uaccess.h @@ -233,7 +233,8 @@ __generic_copy_to_user(void *to, const void *from, unsigned long n) " .long 5b,8b\n" ".previous" : "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp) - : "r"(n & 3), "0"(to), "1"(from), "2"(n / 4)); + : "r"(n & 3), "0"(to), "1"(from), "2"(n / 4) + : "memory"); return n; } @@ -514,7 +515,7 @@ __constant_copy_from_user(void *to, const void *from, unsigned long n) "13:" \ : "=a"(to), "=a"(from), "=d"(n) \ : "0"(to), "1"(from), "2"(n/4) \ - : "d0") + : "d0", "memory") static inline unsigned long __constant_copy_to_user(void *to, const void *from, unsigned long n) diff --git a/include/linux/isicom.h b/include/linux/isicom.h index e61aa08388fd..82325a9b8754 100644 --- a/include/linux/isicom.h +++ b/include/linux/isicom.h @@ -298,4 +298,5 @@ extern inline void kill_queue(struct isi_port * port, short queue) #endif /* __KERNEL__ */ -#endif /* ISICOM_H */ \ No newline at end of file +#endif /* ISICOM_H */ + diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 9a9297cac376..afd52c619ef0 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -222,13 +222,13 @@ extern int nfs_check_error(struct inode *); extern int nfs_wb_all(struct inode *); extern int nfs_wb_page(struct inode *, struct page *); extern int nfs_wb_pid(struct inode *, pid_t); +extern int nfs_flush_trunc(struct inode *, unsigned long); /* * Invalidate write-backs, possibly trying to write them * back first.. */ extern void nfs_inval(struct inode *); -extern int nfs_truncate_dirty_pages(struct inode *, unsigned long); extern int nfs_updatepage(struct file *, struct page *, unsigned long, unsigned int, int); /* diff --git a/include/linux/pci.h b/include/linux/pci.h index ce29e37d5778..066d9c20a142 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -408,7 +408,11 @@ #define PCI_DEVICE_ID_MATROX_MYS 0x051A #define PCI_DEVICE_ID_MATROX_MIL_2 0x051b #define PCI_DEVICE_ID_MATROX_MIL_2_AGP 0x051f +#define PCI_DEVICE_ID_MATROX_G200_PCI 0x0520 +#define PCI_DEVICE_ID_MATROX_G200_AGP 0x0521 #define PCI_DEVICE_ID_MATROX_MGA_IMP 0x0d10 +#define PCI_DEVICE_ID_MATROX_G100_MM 0x1000 +#define PCI_DEVICE_ID_MATROX_G100_AGP 0x1001 #define PCI_VENDOR_ID_CT 0x102c #define PCI_DEVICE_ID_CT_65545 0x00d8 @@ -720,6 +724,7 @@ #define PCI_DEVICE_ID_VIA_82C586_0 0x0586 #define PCI_DEVICE_ID_VIA_82C595 0x0595 #define PCI_DEVICE_ID_VIA_82C597_0 0x0597 +#define PCI_DEVICE_ID_VIA_82C598_0 0x0598 #define PCI_DEVICE_ID_VIA_82C926 0x0926 #define PCI_DEVICE_ID_VIA_82C416 0x1571 #define PCI_DEVICE_ID_VIA_82C595_97 0x1595 @@ -727,6 +732,7 @@ #define PCI_DEVICE_ID_VIA_82C586_3 0x3040 #define PCI_DEVICE_ID_VIA_86C100A 0x6100 #define PCI_DEVICE_ID_VIA_82C597_1 0x8597 +#define PCI_DEVICE_ID_VIA_82C598_1 0x8598 #define PCI_VENDOR_ID_VORTEX 0x1119 #define PCI_DEVICE_ID_VORTEX_GDT60x0 0x0000 diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 2bd5c1f71efc..aa27407730e5 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -139,10 +139,13 @@ enum net_directory_inos { PROC_NET_DN_L2, PROC_NET_DN_CACHE, PROC_NET_DN_SKT, + PROC_NET_DN_FW, + PROC_NET_DN_RAW, PROC_NET_NETSTAT, PROC_NET_IPFW_CHAINS, PROC_NET_IPFW_CHAIN_NAMES, PROC_NET_AT_AARP, + PROC_NET_BRIDGE, PROC_NET_LAST }; diff --git a/include/net/br.h b/include/net/br.h index 8f47d3c12586..d9f6d109b72f 100644 --- a/include/net/br.h +++ b/include/net/br.h @@ -293,6 +293,8 @@ void requeue_fdb(struct fdb *node, int new_port); struct fdb *br_avl_find_addr(unsigned char addr[6]); struct fdb *br_avl_insert (struct fdb * new_node); +void sprintf_avl (char **pbuffer, struct fdb * tree, off_t *pos,int* len, off_t offset, int length); +int br_tree_get_info(char *buffer, char **start, off_t offset, int length, int dummy); /* externs */ diff --git a/include/net/irda/crc.h b/include/net/irda/crc.h new file mode 100644 index 000000000000..ef61f85a4cc4 --- /dev/null +++ b/include/net/irda/crc.h @@ -0,0 +1,30 @@ +/********************************************************************* + * + * Filename: crc.h + * Version: + * Description: CRC routines + * Status: Experimental. + * Author: Dag Brattli + * Created at: Mon Aug 4 20:40:53 1997 + * Modified at: Sat Dec 12 23:09:29 1998 + * Modified by: Dag Brattli + * + ********************************************************************/ + +#ifndef IR_CRC_H +#define IR_CRC_H + +#include + +#define INIT_FCS 0xffff /* Initial FCS value */ +#define GOOD_FCS 0xf0b8 /* Good final FCS value */ + +/* Recompute the FCS with one more character appended. */ +#define IR_FCS(fcs, byte) (((fcs)>>8)^irda_crc16_table[((fcs)^(byte)) & 0xff]) + +/* Recompute the FCS with len bytes appended. */ +unsigned short crc_calc( __u16 fcs, __u8 const *buf, size_t len); + +extern __u16 const irda_crc16_table[]; + +#endif diff --git a/include/net/irda/dongle.h b/include/net/irda/dongle.h new file mode 100644 index 000000000000..8498f41767a4 --- /dev/null +++ b/include/net/irda/dongle.h @@ -0,0 +1,48 @@ +/********************************************************************* + * + * Filename: dongle.h + * Version: + * Description: + * Status: Experimental. + * Author: Dag Brattli + * Created at: Wed Oct 21 22:47:12 1998 + * Modified at: Mon Dec 14 11:47:25 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef DONGLE_H +#define DONGLE_H + +#include +#include + +/* These are the currently known dongles */ +typedef enum { + TEKRAM_DONGLE, + ESI_DONGLE, + ACTISYS_DONGLE, + ACTISYS_PLUS_DONGLE, +} DONGLE_T; + +struct dongle { + DONGLE_T type; + void (*open)(struct irda_device *, int type); + void (*close)(struct irda_device *); + void (*reset)( struct irda_device *, int unused); + void (*change_speed)( struct irda_device *, int baudrate); + void (*qos_init)( struct irda_device *, struct qos_info *); +}; + +#endif diff --git a/include/net/irda/ircomm_common.h b/include/net/irda/ircomm_common.h new file mode 100644 index 000000000000..a092d98082cd --- /dev/null +++ b/include/net/irda/ircomm_common.h @@ -0,0 +1,233 @@ +/********************************************************************* + * + * Filename: ircomm_common.h + * Version: + * Description: An implementation of IrCOMM service interface and state machine + * Status: Experimental. + * Author: Takahide Higuchi + * + * Copyright (c) 1998, Takahide Higuchi, , + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * I, Takahide Higuchi, provide no warranty for any of this software. + * This material is provided "AS-IS" and at no charge. + * + ********************************************************************/ + +/* #define DEBUG(n, args...) printk( KERN_DEBUG args) */ /* enable all debug message */ + +#include +#include + +typedef enum { + COMM_DISCOVERY, + COMM_IDLE, + COMM_WAITI, + COMM_WAITR, + COMM_CONN, +} IRCOMM_STATE; + +/* IrCOMM Events */ +typedef enum { + IRCOMM_CONNECT_REQUEST, + TTP_CONNECT_INDICATION, + LMP_CONNECT_INDICATION, + + TTP_CONNECT_CONFIRM, + TTP_DISCONNECT_INDICATION, + LMP_CONNECT_CONFIRM, + LMP_DISCONNECT_INDICATION, + + IRCOMM_CONNECT_RESPONSE, + IRCOMM_DISCONNECT_REQUEST, + + TTP_DATA_INDICATION, + IRCOMM_DATA_REQUEST, + LMP_DATA_INDICATION, + IRCOMM_CONTROL_REQUEST, +} IRCOMM_EVENT; + + +#define IRCOMM_MAGIC 0x434f4d4d +#define COMM_INIT_CTRL_PARAM 3 /* length of initial control parameters */ +#define COMM_CTRL_MIN 1 /* length of clen field */ +#define COMM_HEADER_SIZE (LAP_HEADER+LMP_HEADER+TTP_HEADER+COMM_CTRL_MIN) +#define COMM_DEFAULT_DATA_SIZE 64 +#define IRCOMM_MAX_CONNECTION 1 /* Don't change */ + +#define IAS_PARAM 1 +#define CONTROL_CHANNEL 2 + + + +#define UNKNOWN 0x00 /* not defined yet. */ +/* we use 9wire if servicetype=DEFAULT, but is it good? */ +#define DEFAULT 0x0a /* private number */ +#define THREE_WIRE_RAW 0x01 /* bit 0 */ +#define THREE_WIRE 0x02 /* bit 1 */ +#define NINE_WIRE 0x04 /* bit 2 */ +#define CENTRONICS 0x08 /* bit 3 */ + +#define SERIAL 0x01 /* bit 0 */ +#define PARALLEL 0x02 /* bit 1 */ + + +#define SERVICETYPE 0x00 +#define PORT_TYPE 0x02 +#define PORT_NAME 0x02 +#define FIXED_PORT_NAME 0x82 + +#define DATA_RATE 0x10 +#define DATA_FORMAT 0x11 +#define FLOW_CONTROL 0x12 +#define XON_XOFF_CHAR 0x13 +#define ENQ_ACK_CHAR 0x14 +#define LINESTATUS 0x15 +#define BREAK_SIGNAL 0x16 + +#define DTELINE_STATE 0x20 +#define DCELINE_STATE 0x21 +#define POLL_FOR_LINE_SETTINGS 0x22 + +#define STATUS_QUERY 0x30 +#define SET_BUSY_TIMEOUT 0x31 +#define IEEE1284_MODE_SUPPORT 0x32 +#define IEEE1284_DEVICEID 0x33 +#define IEEE1284_MODE 0x34 +#define IEEE1284_ECP_EPP_DATA_TRANSFER 0x35 + +#define TX_READY 0xFE /* FIXME: this is not defined in IrCOMM spec */ +#define TX_BUSY 0XFF /* so we should find another way */ + + +/* parameters of FLOW_CONTROL */ + +#define USE_RTS 0x08 /* use RTS on output */ +#define USE_CTS 0x04 /* use CTS on input */ +#define USE_DTR 0x20 /* use DTR on output */ + +/* parameters of DTELINE_STATE */ + +#define DELTA_DTR 0x01 +#define DELTA_RTS 0x02 +#define MCR_DTR 0x04 +#define MCR_RTS 0x08 + +/* parameters of DCELINE_STATE */ + +#define DELTA_CTS 0x01 +#define DELTA_DSR 0x02 +#define DELTA_RI 0x04 +#define DELTA_DCD 0x08 +#define MSR_CTS 0x10 +#define MSR_DSR 0x20 +#define MSR_RI 0x40 +#define MSR_DCD 0x80 + +/* parameters of DATA_FORMAT */ + +#define LSR_OE 0x02 /* Overrun error indicator */ +#define LSR_PE 0x04 /* Parity error indicator */ +#define LSR_FE 0x08 /* Frame error indicator */ +#define LSR_BI 0x01 /* Break interrupt indicator */ + + +struct ircomm_cb{ + int magic; + int state; /* Current state of IrCOMM layer: + * DISCOVERY,COMM_IDLE, COMM_WAITR, + * COMM_WAITI, COMM_CONN + */ + int in_use; + int null_modem_mode; /* switch for null modem emulation */ + int ttp_stop; + int max_txbuff_size; + int maxsdusize; + __u32 daddr; /* Device address of the peer device */ + + void (*d_handler)(struct ircomm_cb *self); + struct notify_t notify; /* container of callbacks */ + + struct sk_buff *ctrl_skb; /* queue of control channel */ + + struct tsap_cb *tsap; /* IrTTP/LMP handle */ + struct qos_info *qos; /* Quality of Service */ + + int reason; /* I don't know about reason: + see Irlmp.c or somewhere :p)*/ + + __u8 dlsap; /* IrLMP dlsap */ + __u8 lsap; /* sap of local device */ + + __u8 pi ; /* instruction of control channel*/ + __u8 port_type; + __u8 peer_port_type; + + __u8 servicetype; + __u8 peer_servicetype; + __u8 data_format; + __u8 peer_data_format; + __u8 flow_ctrl; + __u8 peer_flow_ctrl; + __u8 line_status; + __u8 peer_line_status; + __u8 break_signal; + __u8 peer_break_signal; + __u8 dte; + __u8 peer_dte; + __u8 dce; + __u8 peer_dce; + __u8 xon_char; + __u8 xoff_char; + __u8 peer_xon_char; + __u8 peer_xoff_char; + __u8 enq_char; + __u8 ack_char; + __u8 peer_enq_char; + __u8 peer_ack_char; + __u8 busy_timeout; + __u8 peer_busy_timeout; + __u8 ecp_epp_mode; + __u8 peer_ecp_epp_mode; + __u8 channel_or_addr; + __u8 peer_channel_or_addr; + + __u32 data_rate; + __u32 peer_data_rate; + char port_name[60]; + +}; + + + +void ircomm_connect_request(struct ircomm_cb *self, int maxsdusize); +void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata, + int maxsdusize); +void ircomm_disconnect_request(struct ircomm_cb *self, + struct sk_buff *userdata); +void ircomm_data_request(struct ircomm_cb *self, + struct sk_buff *userdata); +void ircomm_control_request(struct ircomm_cb *self); +void ircomm_append_ctrl(struct ircomm_cb *self, __u8 instruction); +struct ircomm_cb *ircomm_attach_cable( __u8 servicetype, struct notify_t notify, + void *handler); +int ircomm_detach_cable(struct ircomm_cb *self); + + +void ircomm_accept_data_indication(void *instance, void *sap, struct sk_buff *skb); +void ircomm_accept_connect_confirm(void *instance, void *sap, struct qos_info *qos, + int maxsdusize, struct sk_buff *skb); +void ircomm_accept_connect_indication(void *instance, void *sap, + struct qos_info *qos, + int maxsdusize, struct sk_buff *skb); +void ircomm_accept_disconnect_indication(void *instance, void *sap, LM_REASON reason, + struct sk_buff *skb); +void ircomm_accept_flow_indication(void *instance, void *sap, LOCAL_FLOW flow); +void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state); + + diff --git a/include/net/irda/irda.h b/include/net/irda/irda.h new file mode 100644 index 000000000000..d30dc9e7efa2 --- /dev/null +++ b/include/net/irda/irda.h @@ -0,0 +1,153 @@ +/********************************************************************* + * + * Filename: irda.h + * Version: + * Description: + * Status: Experimental. + * Author: Dag Brattli + * Created at: Tue Dec 9 21:13:12 1997 + * Modified at: Mon Nov 2 14:49:11 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef IRDA_H +#define IRDA_H + +#include + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define ALIGN __attribute__((aligned)) +#define PACK __attribute__((packed)) + +/* use 0 for production, 1 for verification, >2 for debug */ +#ifndef NET_DEBUG +#define NET_DEBUG 3 +static unsigned int net_debug = NET_DEBUG; + +#define DEBUG(n, args...) if (net_debug >= (n)) printk( KERN_DEBUG args) +#define ASSERT(expr, func) \ +if(!(expr)) { \ + printk( "Assertion failed! %s,%s,%s,line=%d\n",\ + #expr,__FILE__,__FUNCTION__,__LINE__); \ + ##func} +#else +#error +#define DEBUG(n, args...) +#define ASSERT(expr, func) +#endif /* NET_DEBUG */ + +#ifdef CHECK_SKB +static unsigned int check_skb = CHECK_SKB; + +#define SK_FREED_SKB 0x0DE2C0DE +#define SK_GOOD_SKB 0xDEC0DED1 +#define SK_HEAD_SKB 0x12231298 + +extern int skb_check(struct sk_buff *skb,int,int, char *); + +#ifdef IS_SKB +#undef IS_SKB +#endif + +#define IS_SKB(skb, func) \ +if( skb_check((skb), 0, __LINE__,__FILE__) == -1) { \ + ##func} + +#ifdef IS_SKB_HEAD +#undef IS_SKB_HEAD +#endif + +#define IS_SKB_HEAD(skb) skb_check((skb), 1, __LINE__,__FILE__) + +#define ALLOC_SKB_MAGIC(skb) \ +if( check_skb) \ + skb->magic_debug_cookie = SK_GOOD_SKB; + +#define FREE_SKB_MAGIC(skb) \ +if( check_skb) {\ + skb->magic_debug_cookie = SK_FREED_SKB; \ +} + +#else +#undef IS_SKB +#define IS_SKB(skb, func) +#undef IS_SKB_HEAD +#define IS_SKB_HEAD(skb) +#define ALLOC_SKB_MAGIC(skb) +#define FREE_SKB_MAGIC(skb) +#endif /* CHECK_SKB */ + +/* + * Magic numbers used by Linux/IR. Random numbers which must be unique to + * give the best protection + */ +#define IRTTY_MAGIC 0x2357 +#define LAP_MAGIC 0x1357 +#define LMP_MAGIC 0x4321 +#define LMP_LSAP_MAGIC 0x69333 +#define LMP_LAP_MAGIC 0x3432 +#define IRDA_DEVICE_MAGIC 0x63454 +#define IAS_MAGIC 0x007 +#define TTP_MAGIC 0x241169 +#define TTP_TSAP_MAGIC 0x4345 +#define IROBEX_MAGIC 0x341324 +#define HB_MAGIC 0x64534 +#define IRLAN_MAGIC 0x754 +#define IAS_OBJECT_MAGIC 0x34234 +#define IAS_ATTRIB_MAGIC 0x45232 + +#define IAS_DEVICE_ID 0x5342 +#define IAS_PNP_ID 0xd342 +#define IAS_OBEX_ID 0x34323 +#define IAS_IRLAN_ID 0x34234 +#define IAS_IRCOMM_ID 0x2343 +#define IAS_IRLPT_ID 0x9876 + +#endif /* IRDA_H */ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/include/net/irda/irda_device.h b/include/net/irda/irda_device.h new file mode 100644 index 000000000000..392002c1c3d0 --- /dev/null +++ b/include/net/irda/irda_device.h @@ -0,0 +1,152 @@ +/********************************************************************* + * + * Filename: irda_device.h + * Version: + * Description: + * Status: Experimental. + * Author: Haris Zukanovic + * Created at: Tue Apr 14 12:41:42 1998 + * Modified at: Thu Dec 10 21:18:25 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Haris Zukanovic, + * Copyright (c) 1998 Dag Brattli, + * Copyright (c) 1998 Thomas Davis, , + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Haris Zukanovic nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef IRDA_DEVICE_H +#define IRDA_DEVICE_H + +#include +#include + +#include +#include +#include + +#define SIR_MODE 0x01 +#define MIR_MODE 0x02 +#define FIR_MODE 0x04 +#define IO_PIO 0x08 +#define IO_DMA 0x10 + +#define IO_XMIT 0x01 +#define IO_RECV 0x02 + +/* Chip specific info */ +struct chipio_t { + int iobase, iobase2; /* IO base */ + int io_ext, io_ext2; /* Length of iobase */ + int irq, irq2; /* Interrupts used */ + int fifo_size; /* FIFO size */ + + int dma, dma2; /* DMA channel used */ + int irqflags; /* interrupt flags (ie, SA_SHIRQ|SA_INTERRUPT) */ + int direction; /* Used by some FIR drivers */ + + int baudrate; /* Currently used baudrate */ + int dongle_id; /* Dongle or transceiver currently used */ +}; + +/* Buffer specific info */ +struct iobuff_t { + int state; /* Receiving state (transmit state not used) */ + int in_frame; /* True if receiving frame */ + + __u8 *data; /* the buffer */ + __u8 *head; /* start of data in buffer */ + __u8 *tail; /* end of data in buffer */ + + int offset; /* Usually data + offset = head */ + int len; /* currently used bytes in buffer */ + int truesize; /* total size of the data area */ + __u16 fcs; + + int flags; /* Allocation flags (GFP_KERNEL | GFP_DMA ) */ +}; + +/* + * This structure contains data that _we_ would have liked to be in the device + * structure, but we don't want to mess it up more than it is already. Better + * to keep the data in separate structures! This structure abstracts common + * stuff from IrDA port implementations. + */ +struct irda_device { + QUEUE q; /* Must be first */ + + int magic; /* our magic bullet */ + char name[16]; + + struct irlap_cb *irlap; /* The link layer we are connected to */ + struct device netdev; /* Yes! we are some kind of netdevice */ + struct enet_statistics stats; + +/* int flags; */ + + void *priv; /* Pointer to low level implementation */ + + struct qos_info qos; /* QoS capabilities for this device */ + + struct chipio_t io; + struct iobuff_t tx_buff; + struct iobuff_t rx_buff; + + int media_busy; + + /* Media busy stuff */ + struct timer_list media_busy_timer; + struct timer_list todo_timer; + + int (*hard_xmit)( struct sk_buff *skb, struct device *dev); + void (*change_speed)( struct irda_device *driver, int baud); + + int (*is_receiving)(struct irda_device *); /* receiving? */ + /* int (*is_tbusy)(struct irda_device *); */ /* transmitting? */ + void (*wait_until_sent)(struct irda_device *); + + int new_speed; /* Will be removed in future */ +}; + +extern hashbin_t *irda_device; + +/* Function prototypes */ +int irda_device_init( void); +void irda_device_cleanup( void); + +int irda_device_open( struct irda_device *, char *name, void *priv); +void irda_device_close( struct irda_device *); + +/* Interface to be uses by IrLAP */ +inline void irda_device_set_media_busy( struct irda_device *, int status); +inline int irda_device_is_media_busy( struct irda_device *); +inline int irda_device_is_receiving( struct irda_device *); +inline void irda_device_change_speed( struct irda_device *, int); + +inline struct qos_info *irda_device_get_qos( struct irda_device *self); +int irda_device_txqueue_empty( struct irda_device *self); + +int irda_device_setup( struct device *dev); + +__inline__ int irda_get_mtt( struct sk_buff *skb); + +void setup_dma( int channel, char *buffer, int count, int mode); + +#endif + + + + + + + diff --git a/include/net/irda/irdacall.h b/include/net/irda/irdacall.h new file mode 100644 index 000000000000..f7f67ce9292c --- /dev/null +++ b/include/net/irda/irdacall.h @@ -0,0 +1,2 @@ +/* Separate to keep compilation of protocols.c simpler */ +extern void irda_proto_init(struct net_proto *pro); diff --git a/include/net/irda/iriap.h b/include/net/irda/iriap.h new file mode 100644 index 000000000000..495da351e704 --- /dev/null +++ b/include/net/irda/iriap.h @@ -0,0 +1,123 @@ +/********************************************************************* + * + * Filename: iriap.h + * Version: + * Description: Information Access Protocol (IAP) + * Status: Experimental. + * Author: Dag Brattli + * Created at: Thu Aug 21 00:02:07 1997 + * Modified at: Sat Dec 5 13:45:37 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1997 Dag Brattli , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef IRIAP_H +#define IRIAP_H + +#include +#include + +#include +#include +#include +#include +#include + +#define LST 0x80 +#define ACK 0x40 + +#define IAS_SERVER 0 +#define IAS_CLIENT 1 + +/* IrIAP Op-codes */ +#define GET_INFO_BASE 0x01 +#define GET_OBJECTS 0x02 +#define GET_VALUE 0x03 +#define GET_VALUE_BY_CLASS 0x04 +#define GET_OBJECT_INFO 0x05 +#define GET_ATTRIB_NAMES 0x06 + +#define IAS_SUCCESS 0 +#define IAS_CLASS_UNKNOWN 1 +#define IAS_ATTRIB_UNKNOWN 2 + +typedef void (*CONFIRM_CALLBACK)( __u16 obj_id, struct ias_value *value, + void *priv); + +struct iap_value { + char *full; + char *name; + char *attr; + __u16 obj_id; + __u8 ret_code; + __u8 type; + int len; + int value_int; + char *value_char; +}; + +struct iriap_cb { + QUEUE queue; /* Must be first */ + + int magic; /* Magic cookie */ + int mode; /* Client or server */ + __u32 daddr; + __u8 operation; + + struct sk_buff *skb; + struct lsap_cb *lsap; + __u8 slsap_sel; + + /* Client states */ + IRIAP_STATE client_state; + IRIAP_STATE call_state; + + /* Server states */ + IRIAP_STATE server_state; + IRIAP_STATE r_connect_state; + + CONFIRM_CALLBACK confirm; + void *priv; + + struct timer_list watchdog_timer; +}; + +int iriap_init(void); +void iriap_cleanup(void); +void iriap_getvaluebyclass_request( __u32 addr, char *name, char *attr, + CONFIRM_CALLBACK callback, void *priv); +void iriap_getvaluebyclass_confirm( struct iriap_cb *self, + struct sk_buff *skb); + +void iriap_send_ack( struct iriap_cb *self); +void iriap_data_indication( void *instance, void *sap, struct sk_buff *skb); +void iriap_connect_confirm( void *instance, void *sap, struct qos_info *qos, + int max_sdu_size, struct sk_buff *skb); +void iriap_connect_indication( void *instance, void *sap, + struct qos_info *qos, int max_sdu_size, + struct sk_buff *skb); +void iriap_call_indication( struct iriap_cb *self, struct sk_buff *skb); + +void iriap_register_server(void); + +void iriap_watchdog_timer_expired( unsigned long data); + +static inline void iriap_start_watchdog_timer( struct iriap_cb *self, + int timeout) +{ + irda_start_timer( &self->watchdog_timer, timeout, + (unsigned long) self, iriap_watchdog_timer_expired); +} + +#endif diff --git a/include/net/irda/iriap_event.h b/include/net/irda/iriap_event.h new file mode 100644 index 000000000000..e99f319a31b2 --- /dev/null +++ b/include/net/irda/iriap_event.h @@ -0,0 +1,84 @@ +/********************************************************************* + * + * Filename: iriap_event.h + * Version: + * Description: + * Status: Experimental. + * Author: Dag Brattli + * Created at: Mon Aug 4 20:40:53 1997 + * Modified at: Fri Sep 4 13:19:28 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef IRIAP_FSM_H +#define IRIAP_FSM_H + +/* Forward because of circular include dependecies */ +struct iriap_cb; + +/* IrIAP states */ +typedef enum { + /* Client */ + S_DISCONNECT, + S_CONNECTING, + S_CALL, + + /* S-Call */ + S_MAKE_CALL, + S_CALLING, + S_OUTSTANDING, + S_REPLYING, + S_WAIT_FOR_CALL, + S_WAIT_ACTIVE, + + /* Server */ + R_DISCONNECT, + R_CALL, + + /* R-Connect */ + R_WAITING, + R_WAIT_ACTIVE, + R_RECEIVING, + R_EXECUTE, + R_RETURNING, +} IRIAP_STATE; + +typedef enum { + IAP_CALL_REQUEST, + IAP_CALL_REQUEST_GVBC, + IAP_CALL_RESPONSE, + IAP_RECV_F_LST, + IAP_LM_DISCONNECT_INDICATION, + IAP_LM_CONNECT_INDICATION, + IAP_LM_CONNECT_CONFIRM, +} IRIAP_EVENT; + +void iriap_next_client_state ( struct iriap_cb *self, IRIAP_STATE state); +void iriap_next_call_state ( struct iriap_cb *self, IRIAP_STATE state); +void iriap_next_server_state ( struct iriap_cb *self, IRIAP_STATE state); +void iriap_next_r_connect_state( struct iriap_cb *self, IRIAP_STATE state); + + +void iriap_do_client_event( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb); +void iriap_do_call_event ( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb); + +void iriap_do_server_event ( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb); +void iriap_do_r_connect_event( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb); + +#endif diff --git a/include/net/irda/irias_object.h b/include/net/irda/irias_object.h new file mode 100644 index 000000000000..efacac8548a5 --- /dev/null +++ b/include/net/irda/irias_object.h @@ -0,0 +1,107 @@ +/********************************************************************* + * + * Filename: irias_object.h + * Version: + * Description: + * Status: Experimental. + * Author: Dag Brattli + * Created at: Thu Oct 1 22:49:50 1998 + * Modified at: Sun Oct 25 00:28:56 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef LM_IAS_OBJECT_H +#define LM_IAS_OBJECT_H + +#include "irqueue.h" + +/* LM-IAS Attribute types */ +#define IAS_MISSING 0 +#define IAS_INTEGER 1 +#define IAS_OCT_SEQ 2 +#define IAS_STRING 3 + +/* + * LM-IAS Object + */ +struct ias_object { + QUEUE queue; /* Must be first! */ + + int magic; + + char *name; + int id; + + hashbin_t *attribs; +}; + +/* + * Values used by LM-IAS attributes + */ +struct ias_value { + /* Value description */ + __u8 type; + int charset; /* Only used by string type */ + int len; + + /* Value */ + union { + int integer; + char *string; + __u8 *oct_seq; + } t; +}; + +/* + * Attributes used by LM-IAS objects + */ +struct ias_attrib { + QUEUE queue; /* Must be first! */ + + int magic; + + /* Attribute name */ + char *name; + /* char *attr; What do we need this for? */ + + /* Attribute value */ + struct ias_value *value; +}; + +char *strdup( char *str); + +struct ias_object *irias_new_object( char *name, int id); +void irias_insert_object( struct ias_object *obj); +void __irias_delete_object( struct ias_object *obj); +void irias_delete_object( char *name); + +void irias_add_integer_attrib( struct ias_object *obj, char *name, + int value); +void irias_add_string_attrib( struct ias_object *obj, char *name, + char *value); +void irias_add_octseq_attrib( struct ias_object *obj, char *name, + __u8 *octets, int len); +struct ias_object *irias_find_object( char *name); +struct ias_attrib *irias_find_attrib( struct ias_object *obj, char *name); + +struct ias_value *irias_new_string_value( char *string); +struct ias_value *irias_new_integer_value( int integer); +struct ias_value *irias_new_octseq_value( __u8 *octseq , int len); +void irias_delete_value( struct ias_value *value); + +extern struct ias_value missing; +extern hashbin_t *objects; + +#endif diff --git a/include/net/irda/irlan_cli.h b/include/net/irda/irlan_cli.h new file mode 100644 index 000000000000..fb677af20cd3 --- /dev/null +++ b/include/net/irda/irlan_cli.h @@ -0,0 +1,65 @@ +/********************************************************************* + * + * Filename: client.h + * Version: 0.3 + * Description: IrDA LAN access layer + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sun Aug 31 20:14:37 1997 + * Modified at: Mon Oct 19 12:37:20 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef IRLAN_CLIENT_H +#define IRLAN_CLIENT_H + +#include +#include +#include +#include + +int irlan_client_init(void); +void irlan_client_cleanup(void); + +void irlan_discovery_indication( DISCOVERY*); +void irlan_client_disconnect_indication( void *instance, void *sap, + LM_REASON reason, struct sk_buff *); + +void irlan_client_data_indication( void *instance, void *sap, + struct sk_buff *skb); + +void irlan_client_control_data_indication( void *instance, void *sap, + struct sk_buff *skb); + +void irlan_client_connect_confirm( void *instance, void *sap, + struct qos_info *qos, int max_sdu_size, + struct sk_buff *); +void irlan_client_connect_indication( void *instance, void *sap, + struct sk_buff *); +void irlan_client_connect_response( void *instance, void *sap, + int max_sdu_size, struct sk_buff *skb); + +void irlan_client_open_tsaps( struct irlan_cb *self); + +void irlan_client_extract_params( struct irlan_cb *self, + struct sk_buff *skb); +void check_response_param( struct irlan_cb *self, char *param, + char *value, int val_len); +void handle_request( struct irlan_cb *self); +void irlan_client_register_server(void); +void irlan_client_get_value_confirm( __u16 obj_id, struct ias_value *value, + void *priv); + +#endif diff --git a/include/net/irda/irlan_common.h b/include/net/irda/irlan_common.h new file mode 100644 index 000000000000..33ba52377333 --- /dev/null +++ b/include/net/irda/irlan_common.h @@ -0,0 +1,199 @@ +/********************************************************************* + * + * Filename: irlan.h + * Version: 0.1 + * Description: IrDA LAN access layer + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sun Aug 31 20:14:37 1997 + * Modified at: Thu Oct 29 13:23:11 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef IRLAN_H +#define IRLAN_H + +#include +#include +#include +#include + +#include "irqueue.h" +#include "irttp.h" + +#define IRLAN_MTU 1518 + +/* Command packet types */ +#define CMD_GET_PROVIDER_INFO 0 +#define CMD_GET_MEDIA_CHAR 1 +#define CMD_OPEN_DATA_CHANNEL 2 +#define CMD_CLOSE_DATA_CHAN 3 +#define CMD_RECONNECT_DATA_CHAN 4 +#define CMD_FILTER_OPERATION 5 + +/* Some responses */ +#define RSP_SUCCESS 0 +#define RSP_INSUFFICIENT_RESOURCES 1 +#define RSP_INVALID_COMMAND_FORMAT 2 +#define RSP_COMMAND_NOT_SUPPORTED 3 +#define RSP_PARAM_NOT_SUPPORTED 4 +#define RSP_VALUE_NOT_SUPPORTED 5 +#define RSP_NOT_OPEN 6 +#define RSP_AUTHENTICATION_REQUIRED 7 +#define RSP_INVALID_PASSWORD 8 +#define RSP_PROTOCOL_ERROR 9 +#define RSP_ASYNCHRONOUS_ERROR 255 + +/* Media types */ +#define MEDIA_802_3 1 +#define MEDIA_802_5 2 + +/* Filter parameters */ +#define DATA_CHAN 1 +#define FILTER_TYPE 2 +#define FILTER_MODE 3 + +/* Filter types */ +#define IR_DIRECTED 1 +#define IR_FUNCTIONAL 2 +#define IR_GROUP 3 +#define IR_MAC_FRAME 4 +#define IR_MULTICAST 5 +#define IR_BROADCAST 6 +#define IR_IPX_SOCKET 7 + +/* Filter modes */ +#define ALL 1 +#define FILTER 2 +#define NONE 3 + +/* Filter operations */ +#define GET 1 +#define CLEAR 2 +#define ADD 3 +#define REMOVE 4 +#define DYNAMIC 5 + +/* Access types */ +#define DIRECT 1 +#define PEER 2 +#define HOSTED 3 + +#define IRLAN_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER) + +/* + * IrLAN client subclass + */ +struct irlan_client_cb { + /* + * Client fields + */ + int open_retries; + + __u8 reconnect_key[255]; + __u8 key_len; + + int unicast_open; + int broadcast_open; +}; + +/* + * IrLAN servers subclass + */ +struct irlan_server_cb { + + /* + * Store some values here which are used by the irlan_server to parse + * FILTER_OPERATIONs + */ + int data_chan; + int filter_type; + int filter_mode; + int filter_operation; + int filter_entry; + + __u8 mac_address[6]; /* Generated MAC address for peer device */ +}; + +/* + * IrLAN super class + */ +struct irlan_cb { + QUEUE queue; /* Must be first */ + + int magic; + char ifname[9]; + struct device dev; /* Ethernet device structure*/ + struct enet_statistics stats; + + __u32 saddr; /* Source devcie address */ + __u32 daddr; /* Destination device address */ + int connected; /* TTP layer ready to exchange ether frames */ + + int state; /* Current state of IrLAN layer */ + + int media; + + struct tsap_cb *tsap_ctrl; + struct tsap_cb *tsap_data; + + int use_udata; /* Use Unit Data transfers */ + + __u8 dtsap_sel_data; /* Destination data TSAP selector */ + __u8 stsap_sel_data; /* Source data TSAP selector */ + __u8 dtsap_sel_ctrl; /* Destination ctrl TSAP selector */ + + int client; /* Client or server */ + union { + struct irlan_client_cb client; + struct irlan_server_cb server; + } t; + + /* void (*irlan_dev_init)(struct irlan_cb *); */ + + /* + * Used by extract_params, placed here for now to avoid placing + * them on the stack. FIXME: remove these! + */ + char name[255]; + char value[1016]; +}; + +struct irlan_cb *irlan_open(void); + +void irlan_get_provider_info( struct irlan_cb *self); +void irlan_get_unicast_addr( struct irlan_cb *self); +void irlan_get_media_char( struct irlan_cb *self); +void irlan_open_data_channel( struct irlan_cb *self); +void irlan_set_multicast_filter( struct irlan_cb *self, int status); +void irlan_set_broadcast_filter( struct irlan_cb *self, int status); +void irlan_open_unicast_addr( struct irlan_cb *self); + +int insert_byte_param( struct sk_buff *skb, char *param, __u8 value); +int insert_string_param( struct sk_buff *skb, char *param, char *value); +int insert_array_param( struct sk_buff *skb, char *name, __u8 *value, + __u16 value_len); + +int insert_param( struct sk_buff *skb, char *param, int type, char *value_char, + __u8 value_byte, __u16 value_short); + +int irlan_get_response_param( __u8 *buf, char *name, char *value, int *len); +void print_ret_code( __u8 code); + +extern hashbin_t *irlan; + +#endif + + diff --git a/include/net/irda/irlan_eth.h b/include/net/irda/irlan_eth.h new file mode 100644 index 000000000000..72f14ff75a80 --- /dev/null +++ b/include/net/irda/irlan_eth.h @@ -0,0 +1,40 @@ +/********************************************************************* + * + * Filename: irlan_eth.h + * Version: + * Description: + * Status: Experimental. + * Author: Dag Brattli + * Created at: Thu Oct 15 08:36:58 1998 + * Modified at: Thu Oct 15 12:28:12 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef IRLAN_ETH_H +#define IRLAN_ETH_H + +int irlan_eth_init( struct device *dev); +int irlan_eth_open( struct device *dev); +int irlan_eth_close( struct device *dev); + +void irlan_eth_rx( void *instance, void *sap, struct sk_buff *skb); +int irlan_eth_tx( struct sk_buff *skb, struct device *dev); + +void irlan_eth_flow_indication( void *instance, void *sap, LOCAL_FLOW flow); + +void irlan_eth_set_multicast_list( struct device *dev); +struct enet_statistics *irlan_eth_get_stats(struct device *dev); + +#endif diff --git a/include/net/irda/irlan_event.h b/include/net/irda/irlan_event.h new file mode 100644 index 000000000000..d3a062af0f2d --- /dev/null +++ b/include/net/irda/irlan_event.h @@ -0,0 +1,86 @@ +/********************************************************************* + * + * Filename: irlan_event.h + * Version: + * Description: LAN access + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sun Aug 31 20:14:37 1997 + * Modified at: Tue Oct 20 09:59:31 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1997 Dag Brattli , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef IRLAN_EVENT_H +#define IRLAN_EVENT_H + +#include +#include + +#include + +typedef enum { + IRLAN_IDLE, + IRLAN_QUERY, + IRLAN_CONN, + IRLAN_INFO, + IRLAN_MEDIA, + IRLAN_OPEN, + IRLAN_WAIT, + IRLAN_ARB, + IRLAN_DATA, + IRLAN_CLOSE, + IRLAN_SYNC +} IRLAN_STATE; + +/* IrLAN Client Events */ +typedef enum { + IRLAN_DISCOVERY_INDICATION, + IRLAN_IAS_PROVIDER_AVAIL, + IRLAN_IAS_PROVIDER_NOT_AVAIL, + IRLAN_LAP_DISCONNECT, + IRLAN_LMP_DISCONNECT, + IRLAN_CONNECT_COMPLETE, + IRLAN_DATA_INDICATION, + IRLAN_DATA_CONNECT_INDICATION, + IRLAN_RETRY_CONNECT, + + IRLAN_CONNECT_INDICATION, + IRLAN_GET_INFO_CMD, + IRLAN_GET_MEDIA_CMD, + IRLAN_OPEN_DATA_CMD, + IRLAN_FILTER_CONFIG_CMD, +} IRLAN_EVENT; + +struct irlan_info { + __u8 dlsap_sel; + __u32 daddr; + struct tsap_cb *tsap; +}; + +extern char *irlan_state[]; + +void irlan_do_client_event( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb); + +void irlan_do_server_event( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb, + struct irlan_info *info); + +void irlan_next_state( struct irlan_cb *self, + IRLAN_STATE state); + +#endif diff --git a/include/net/irda/irlan_srv.h b/include/net/irda/irlan_srv.h new file mode 100644 index 000000000000..c187302e2556 --- /dev/null +++ b/include/net/irda/irlan_srv.h @@ -0,0 +1,62 @@ +/********************************************************************* + * + * Filename: server.h + * Version: 0.1 + * Description: IrDA LAN access layer + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sun Aug 31 20:14:37 1997 + * Modified at: Fri Oct 16 11:25:37 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef IRLAN_SERVER_H +#define IRLAN_SERVER_H + +#include +#include +#include +#include + +#include + +int irlan_server_init(void); +void irlan_server_cleanup(void); +struct irlan_cb *irlan_server_open(void); +void irlan_server_close( struct irlan_cb *self); + +void irlan_server_disconnect_indication( void *instance, void *sap, + LM_REASON reason, + struct sk_buff *skb); + +void irlan_server_data_indication( void *instance, void *sap, + struct sk_buff *skb); +void irlan_server_control_data_indication( void *instance, void *sap, + struct sk_buff *skb); + +void irlan_server_connect_indication( void *instance, void *sap, + struct qos_info *qos, int max_sdu_size, + struct sk_buff *skb); +void irlan_server_connect_response( struct irlan_cb *, struct tsap_cb *); + +int irlan_parse_open_data_cmd( struct irlan_cb *self, struct sk_buff *skb); +int irlan_server_extract_params( struct irlan_cb *self, int cmd, + struct sk_buff *skb); + +void irlan_server_send_reply( struct irlan_cb *self, int command, + int ret_code); +void irlan_server_register(void); + +#endif diff --git a/include/net/irda/irlap.h b/include/net/irda/irlap.h new file mode 100644 index 000000000000..524d2b79907b --- /dev/null +++ b/include/net/irda/irlap.h @@ -0,0 +1,232 @@ +/********************************************************************* + * + * Filename: irlap.h + * Version: 0.3 + * Description: An IrDA LAP driver for Linux + * Status: Experimental. + * Author: Dag Brattli + * Created at: Mon Aug 4 20:40:53 1997 + * Modified at: Sat Dec 12 12:25:33 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef IRLAP_H +#define IRLAP_H + +#include +#include +#include +#include +#include +#include + +#include + +#define LAP_RELIABLE 1 +#define LAP_UNRELIABLE 0 + +#define LAP_ADDR_HEADER 1 /* IrLAP Address Header */ +#define LAP_CTRL_HEADER 1 /* IrLAP Control Header */ +#define LAP_COMP_HEADER 1 /* IrLAP Compression Header */ + +#ifdef CONFIG_IRDA_COMPRESSION +# define LAP_HEADER (LAP_ADDR_HEADER + LAP_CTRL_HEADER + LAP_COMP_HEADER) +# define IRDA_COMPRESSED 1 +# define IRDA_NORMAL 0 +#else +#define LAP_HEADER (LAP_ADDR_HEADER + LAP_CTRL_HEADER) +#endif + +#define BROADCAST 0xffffffff /* Broadcast device address */ +#define CBROADCAST 0xfe /* Connection broadcast address */ +#define XID_FORMAT 0x01 /* Discovery XID format */ + +#define LAP_WINDOW_SIZE 8 +#define MAX_CONNECTIONS 1 + +#define NR_EXPECTED 1 +#define NR_UNEXPECTED 0 +#define NR_INVALID -1 + +#define NS_EXPECTED 1 +#define NS_UNEXPECTED 0 +#define NS_INVALID -1 + +#ifdef CONFIG_IRDA_COMPRESSION +/* + * Just some shortcuts (may give you strange compiler errors if you change + * them :-) + */ +#define irda_compress (*self->compessor.cp->compress) +#define irda_comp_free (*self->compressor.cp->comp_free) +#define irda_decompress (*self->decompressor.cp->decompress) +#define irda_decomp_free (*self->decompressor.cp->decomp_free) +#define irda_incomp (*self->decompressor.cp->incomp) + +struct irda_compressor { + QUEUE queue; + + struct compressor *cp; + void *state; /* Not used by IrDA */ +}; +#endif + +/* Main structure of IrLAP */ +struct irlap_cb { + QUEUE q; /* Must be first */ + + int magic; + + struct irda_device *irdev; + struct device *netdev; + + /* Connection state */ + volatile IRLAP_STATE state; /* Current state */ + + /* Timers used by IrLAP */ + struct timer_list query_timer; + struct timer_list slot_timer; + struct timer_list discovery_timer; + struct timer_list final_timer; + struct timer_list poll_timer; + struct timer_list wd_timer; + struct timer_list backoff_timer; + + /* Timeouts which will be different with different turn time */ + int poll_timeout; + int final_timeout; + int wd_timeout; + + struct sk_buff_head tx_list; /* Frames to be transmitted */ + + __u8 caddr; /* Connection address */ + __u32 saddr; /* Source device address */ + __u32 daddr; /* Destination device address */ + + int retry_count; /* Times tried to establish connection */ + int add_wait; /* True if we are waiting for frame */ + +#ifdef CONFIG_IRDA_FAST_RR + /* + * To send a faster RR if tx queue empty + */ + int fast_RR_timeout; + int fast_RR; +#endif + + int N1; /* N1 * F-timer = Negitiated link disconnect warning threshold */ + int N2; /* N2 * F-timer = Negitiated link disconnect time */ + int N3; /* Connection retry count */ + + int local_busy; + int remote_busy; + int xmitflag; + + __u8 vs; /* Next frame to be sent */ + __u8 vr; /* Next frame to be received */ + int tmp; + __u8 va; /* Last frame acked */ + int window; /* Nr of I-frames allowed to send */ + int window_size; /* Current negotiated window size */ + int window_bytes; /* Number of bytes allowed to send */ + int bytes_left; /* Number of bytes allowed to transmit */ + + struct sk_buff_head wx_list; + + __u8 ack_required; + + /* XID parameters */ + __u8 S; /* Number of slots */ + __u8 slot; /* Random chosen slot */ + __u8 s; /* Current slot */ + int frame_sent; /* Have we sent reply? */ + + int discovery_count; + hashbin_t *discovery_log; + DISCOVERY *discovery_cmd; + + struct qos_info qos_tx; /* QoS requested by peer */ + struct qos_info qos_rx; /* QoS requested by self */ + + struct notify_t notify; /* Callbacks to IrLMP */ + + int mtt_required; /* Minumum turnaround time required */ + int xbofs_delay; /* Nr of XBOF's used to MTT */ + int bofs_count; /* Negotiated extra BOFs */ + + struct irda_statistics stats; + +#ifdef CONFIG_IRDA_RECYCLE_RR + struct sk_buff *recycle_rr_skb; +#endif + +#ifdef CONFIG_IRDA_COMPRESSION + struct irda_compressor compressor; + struct irda_compressor decompressor; +#endif +}; + +extern hashbin_t *irlap; + +/* + * Function prototypes + */ + +int irlap_init( void); +void irlap_cleanup( void); + +struct irlap_cb *irlap_open( struct irda_device *dev); +void irlap_close( struct irlap_cb *self); + +void irlap_connect_request( struct irlap_cb *self, __u32 daddr, + struct qos_info *qos, int sniff); +void irlap_connect_response( struct irlap_cb *self, struct sk_buff *skb); +void irlap_connect_indication( struct irlap_cb *self, struct sk_buff *skb); +void irlap_connect_confirm( struct irlap_cb *, struct sk_buff *skb); + +inline void irlap_data_indication( struct irlap_cb *, struct sk_buff *); +inline void irlap_unit_data_indication( struct irlap_cb *, struct sk_buff *); +inline void irlap_data_request( struct irlap_cb *, struct sk_buff *, + int reliable); + +void irlap_disconnect_request( struct irlap_cb *); +void irlap_disconnect_indication( struct irlap_cb *, LAP_REASON reason); + +void irlap_status_indication( int quality_of_link); + +void irlap_test_request( __u8 *info, int len); + +void irlap_discovery_request( struct irlap_cb *, DISCOVERY *discovery); +void irlap_discovery_confirm( struct irlap_cb *, hashbin_t *discovery_log); +void irlap_discovery_indication( struct irlap_cb *, DISCOVERY *discovery); + +void irlap_reset_indication( struct irlap_cb *self); +void irlap_reset_confirm(void); + +void irlap_update_nr_received( struct irlap_cb *, int nr); +int irlap_validate_nr_received( struct irlap_cb *, int nr); +int irlap_validate_ns_received( struct irlap_cb *, int ns); + +int irlap_generate_rand_time_slot( int S, int s); +void irlap_initiate_connection_state( struct irlap_cb *); +void irlap_flush_all_queues( struct irlap_cb *); +void irlap_change_speed( struct irlap_cb *, int); +void irlap_wait_min_turn_around( struct irlap_cb *, struct qos_info *); + +void irlap_init_qos_capabilities( struct irlap_cb *, struct qos_info *); +void irlap_apply_default_connection_parameters( struct irlap_cb *self); +void irlap_apply_connection_parameters( struct irlap_cb *, struct qos_info *); + +#endif diff --git a/include/net/irda/irlap_comp.h b/include/net/irda/irlap_comp.h new file mode 100644 index 000000000000..59f268e53a30 --- /dev/null +++ b/include/net/irda/irlap_comp.h @@ -0,0 +1,47 @@ +/********************************************************************* + * + * Filename: irlap_comp.h + * Version: + * Description: + * Status: Experimental. + * Author: Dag Brattli + * Created at: Fri Oct 9 09:21:12 1998 + * Modified at: Sat Dec 12 12:23:16 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef IRLAP_COMP_H +#define IRLAP_COMP_H + +#include + +#define CI_BZIP2 27 /* Random pick */ + +extern hashbin_t *irlap_compressors; + +int irda_register_compressor( struct compressor *cp); +void irda_unregister_compressor( struct compressor *cp); + +int irda_set_compression( struct irlap_cb *self, int proto); +void irlap_compressor_init( struct irlap_cb *self, int compress); +void irda_free_compression( struct irlap_cb *self); + +struct sk_buff *irlap_compress_frame( struct irlap_cb *self, + struct sk_buff *skb); +struct sk_buff *irlap_decompress_frame( struct irlap_cb *self, + struct sk_buff *skb); + +#endif + diff --git a/include/net/irda/irlap_event.h b/include/net/irda/irlap_event.h new file mode 100644 index 000000000000..e490eab14ebf --- /dev/null +++ b/include/net/irda/irlap_event.h @@ -0,0 +1,119 @@ +/********************************************************************* + * + * Filename: irlap_event.h + * Version: 0.1 + * Description: + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sat Aug 16 00:59:29 1997 + * Modified at: Mon Dec 14 13:58:27 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef IRLAP_EVENT_H +#define IRLAP_EVENT_H + +#include "irmod.h" + +struct irlap_cb; + +/* IrLAP States */ +typedef enum { + LAP_NDM, /* Normal disconnected mode */ + LAP_QUERY, + LAP_REPLY, + LAP_CONN, /* Connect indication */ + LAP_SETUP, /* Setting up connection */ + LAP_OFFLINE, /* A really boring state */ + LAP_XMIT_P, + LAP_PCLOSE, + LAP_NRM_P, /* Normal response mode as primary */ + LAP_RESET_WAIT, + LAP_RESET, + LAP_NRM_S, /* Normal response mode as secondary */ + LAP_XMIT_S, + LAP_SCLOSE, +} IRLAP_STATE; + +/* IrLAP Events */ +typedef enum { + /* Services events */ + DISCOVERY_REQUEST, + CONNECT_REQUEST, + CONNECT_RESPONSE, + DISCONNECT_REQUEST, + DATA_REQUEST, + RESET_REQUEST, + + /* Send events */ + SEND_I_CMD, + + /* Receive events */ + RECV_DISCOVERY_XID_CMD, + RECV_DISCOVERY_XID_RSP, + RECV_SNRM_CMD, + RECV_TEST_CMD, + RECV_UA_RSP, + RECV_DM_RSP, + RECV_I_CMD, + RECV_I_RSP, + RECV_UI_FRAME, + RECV_FRMR_RSP, + RECV_RR_CMD, + RECV_RR_RSP, + RECV_RNR_FRAME, + RECV_DISC_FRAME, + + /* Timer events */ + SLOT_TIMER_EXPIRED, + QUERY_TIMER_EXPIRED, + FINAL_TIMER_EXPIRED, + POLL_TIMER_EXPIRED, + DISCOVERY_TIMER_EXPIRED, + WD_TIMER_EXPIRED, + BACKOFF_TIMER_EXPIRED, +} IRLAP_EVENT; + +/* + * Various things used by the IrLAP state machine + */ +struct irlap_info { + __u8 caddr; /* Connection address */ + __u8 control; /* Frame type */ + __u8 cmd; + + __u32 saddr; + __u32 daddr; + + int pf; /* Poll/final bit set */ + + __u8 nr; /* Sequence number of next frame expected */ + __u8 ns; /* Sequence number of frame sent */ + + int S; /* Number of slots */ + int slot; /* Random chosen slot */ + int s; /* Current slot */ + + DISCOVERY *discovery; /* Discovery information */ +}; + +extern char *irlap_state[]; + +void irlap_do_event( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +void irlap_next_state( struct irlap_cb *self, IRLAP_STATE state); +void irlap_print_event( IRLAP_EVENT event); + +#endif diff --git a/include/net/irda/irlap_frame.h b/include/net/irda/irlap_frame.h new file mode 100644 index 000000000000..6b661e4b5d29 --- /dev/null +++ b/include/net/irda/irlap_frame.h @@ -0,0 +1,155 @@ +/********************************************************************* + * + * Filename: irlap_frame.h + * Version: 0.3 + * Description: Build and transmit IrLAP frames + * Status: Experimental. + * Author: Dag Brattli + * Created at: Tue Aug 19 10:27:26 1997 + * Modified at: Mon Dec 14 14:22:23 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef IRLAP_FRAME_H +#define IRLAP_FRAME_H + +#include + +#include +#include +#include + +/* Frame types and templates */ +#define INVALID 0xff + +/* Unnumbered (U) commands */ +#define SNRM_CMD 0x83 /* Set Normal Response Mode */ +#define DISC_CMD 0x43 /* Disconnect */ +#define XID_CMD 0x2f /* Exchange Station Identification */ +#define TEST_CMD 0xe3 /* Test */ + +/* Unnumbered responses */ +#define RNRM_RSP 0x83 /* Request Normal Response Mode */ +#define UA_RSP 0x63 /* Unnumbered Acknowledgement */ +#define FRMR_RSP 0x87 /* Frame Reject */ +#define DM_RSP 0x0f /* Disconnect Mode */ +#define RD_RSP 0x43 /* Request Disconnection */ +#define XID_RSP 0xaf /* Exchange Station Identification */ +#define TEST_RSP 0xe3 /* Test frame */ + +/* Supervisory (S) */ +#define RR 0x01 /* Receive Ready */ +#define REJ 0x09 /* Reject */ +#define RNR 0x05 /* Receive Not Ready */ +#define SREJ 0x0d /* Selective Reject */ + +/* Information (I) */ +#define I_FRAME 0x00 /* Information Format */ +#define UI_FRAME 0x03 /* Unnumbered Information */ + +#define CMD_FRAME 0x01 +#define RSP_FRAME 0x00 + +#define PF_BIT 0x10 /* Poll/final bit */ + +#define IR_S 0x01 /* Supervisory frames */ +#define IR_RR 0x01 /* Receiver ready */ +#define IR_RNR 0x05 /* Receiver not ready */ +#define IR_REJ 0x09 /* Reject */ +#define IR_U 0x03 /* Unnumbered frames */ +#define IR_SNRM 0x2f /* Set Asynchronous Balanced Mode */ + +#define IR_DISC 0x43 /* Disconnect */ +#define IR_DM 0x0f /* Disconnected mode */ +#define IR_UA 0x63 /* Unnumbered acknowledge */ +#define IR_FRMR 0x87 /* Frame reject */ +#define IR_UI 0x03 /* Unnumbered information */ + +struct xid_frame { + __u8 caddr __attribute__((packed)); /* Connection address */ + __u8 control __attribute__((packed)); + __u8 ident __attribute__((packed)); /* Should always be XID_FORMAT */ + __u32 saddr __attribute__((packed)); /* Source device address */ + __u32 daddr __attribute__((packed)); /* Destination device address */ + __u8 flags __attribute__((packed)); /* Discovery flags */ + __u8 slotnr __attribute__((packed)); + __u8 version __attribute__((packed)); + __u8 discovery_info[0] __attribute__((packed)); +}; + +struct test_frame { + __u8 caddr; /* Connection address */ + __u8 control; + __u8 saddr; /* Source device address */ + __u8 daddr; /* Destination device address */ + __u8 *info; /* Information */ +}; + +struct ua_frame { + __u8 caddr __attribute__((packed)); + __u8 control __attribute__((packed)); + + __u32 saddr __attribute__((packed)); /* Source device address */ + __u32 daddr __attribute__((packed)); /* Dest device address */ + __u8 params[0]; +}; + +struct i_frame { + __u8 caddr __attribute__((packed)); + __u8 control __attribute__((packed)); + __u8 data[0] __attribute__((packed)); +}; + +struct snrm_frame { + __u8 caddr __attribute__((packed)); + __u8 control __attribute__((packed)); + __u32 saddr __attribute__((packed)); + __u32 daddr __attribute__((packed)); + __u8 ncaddr __attribute__((packed)); + __u8 params[0]; +}; + +/* Per-packet information we need to hide inside sk_buff */ +struct irlap_skb_cb { + int mtt; /* minimum turn around time */ + int xbofs; /* number of xbofs required */ + int vs; /* next frame to send */ + int vr; /* next frame to receive */ +}; + +__inline__ void irlap_insert_mtt( struct irlap_cb *self, struct sk_buff *skb); + +void irlap_send_discovery_xid_frame( struct irlap_cb *, int S, __u8 s, + __u8 command, DISCOVERY *discovery); +void irlap_send_snrm_frame( struct irlap_cb *, struct qos_info *); +void irlap_send_ua_response_frame( struct irlap_cb *, struct qos_info *); +void irlap_send_ui_frame( struct irlap_cb *self, struct sk_buff *skb, + int command); +void irlap_send_dm_frame( struct irlap_cb *); +void irlap_send_disc_frame( struct irlap_cb *); +void irlap_send_rr_frame( struct irlap_cb *, int command); + +void irlap_send_data_primary( struct irlap_cb *, struct sk_buff *); +void irlap_send_data_primary_poll( struct irlap_cb *, struct sk_buff *); +void irlap_send_data_secondary( struct irlap_cb *, struct sk_buff *); +void irlap_send_data_secondary_final( struct irlap_cb *, struct sk_buff *); +void irlap_resend_rejected_frames( struct irlap_cb *, int command); + +void irlap_send_i_frame( struct irlap_cb *, struct sk_buff *, int command); +void irlap_send_ui_frame( struct irlap_cb *, struct sk_buff *, int command); + +/* void irlap_input( struct irlap_cb *self, struct sk_buff *skb); */ + +#endif diff --git a/include/net/irda/irlmp.h b/include/net/irda/irlmp.h new file mode 100644 index 000000000000..a10a08fe1b14 --- /dev/null +++ b/include/net/irda/irlmp.h @@ -0,0 +1,239 @@ +/********************************************************************* + * + * Filename: irlmp.h + * Version: 0.3 + * Description: IrDA Link Management Protocol (LMP) layer + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sun Aug 17 20:54:32 1997 + * Modified at: Mon Dec 7 21:11:32 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef IRLMP_H +#define IRLMP_H + +#include +#include + +#include "irmod.h" +#include "qos.h" +#include "irlap.h" +#include "irlmp_event.h" +#include "irqueue.h" + +/* LSAP-SEL's */ +#define LSAP_MASK 0x7f +#define LSAP_IAS 0x00 +#define LSAP_ANY 0xff + +/* Predefined LSAPs used by the various servers */ +#define TSAP_IRLAN 0x05 +#define LSAP_IRLPT 0x06 +#define TSAP_IROBEX 0x07 +#define TSAP_IRCOMM 0x08 + +#define LMP_HEADER 2 /* Dest LSAP + Source LSAP */ +#define LMP_CONTROL_HEADER 4 +#define LMP_MAX_HEADER (LAP_HEADER+LMP_HEADER) + +#define LM_MAX_CONNECTIONS 10 + +/* Hint bit positions for first hint byte */ +#define HINT_PNP 0x01 +#define HINT_PDA 0x02 +#define HINT_COMPUTER 0x04 +#define HINT_PRINTER 0x08 +#define HINT_MODEM 0x10 +#define HINT_FAX 0x20 +#define HINT_LAN 0x40 +#define HINT_EXTENSION 0x80 + +/* Hint bit positions for second hint byte (first extension byte) */ +#define HINT_TELEPHONY 0x01 +#define HINT_FILE_SERVER 0x02 +#define HINT_COMM 0x04 +#define HINT_MESSAGE 0x08 +#define HINT_HTTP 0x10 +#define HINT_OBEX 0x20 + +typedef enum { + S_PNP, + S_PDA, + S_COMPUTER, + S_PRINTER, + S_MODEM, + S_FAX, + S_LAN, + S_TELEPHONY, + S_COMM, + S_OBEX, +} SERVICE; + +#define S_END 0xff + +#define CLIENT 1 +#define SERVER 2 + +typedef void (*DISCOVERY_CALLBACK) ( DISCOVERY*); + +struct irlmp_registration { + QUEUE queue; /* Must be first */ + + int service; /* LAN, OBEX, COMM etc. */ + int type; /* Client or server or both */ + + DISCOVERY_CALLBACK discovery_callback; +}; + +struct lap_cb; /* Forward decl. */ + +/* + * Information about each logical LSAP connection + */ +struct lsap_cb { + QUEUE queue; /* Must be first */ + + int magic; + + int connected; + int persistent; + + struct irda_statistics stats; + + __u8 slsap_sel; /* Source (this) LSAP address */ + __u8 dlsap_sel; /* Destination LSAP address (if connected) */ + + struct sk_buff *tmp_skb; /* Store skb here while connecting */ + + struct timer_list watchdog_timer; + + IRLMP_STATE lsap_state; /* Connection state */ + struct notify_t notify; /* Indication/Confirm entry points */ + struct qos_info qos; /* QoS for this connection */ + + struct lap_cb *lap; /* Pointer to LAP connection structure */ +}; + +/* + * Information about each registred IrLAP layer + */ +struct lap_cb { + QUEUE queue; /* Must be first */ + + int magic; + int reason; /* LAP disconnect reason */ + + IRLMP_STATE lap_state; + + struct irlap_cb *irlap; /* Instance of IrLAP layer */ + + hashbin_t *lsaps; /* LSAP associated with this link */ + + __u8 caddr; /* Connection address */ + + __u32 saddr; /* Source device address */ + __u32 daddr; /* Destination device address */ + + hashbin_t *cachelog; /* Discovered devices for this link */ + + struct qos_info *qos; /* LAP QoS for this session */ +}; + +/* + * Used for caching the last slsap->dlsap->handle mapping + */ +typedef struct { + int valid; + + __u8 slsap_sel; + __u8 dlsap_sel; + struct lsap_cb *lsap; +} CACHE_ENTRY; + +/* + * Main structure for IrLMP + */ +struct irlmp_cb { + int magic; + + __u8 conflict_flag; + + /* int discovery; */ + + DISCOVERY discovery_rsp; /* Discovery response to use by IrLAP */ + DISCOVERY discovery_cmd; /* Discovery command to use by IrLAP */ + + int free_lsap_sel; + +#ifdef CONFIG_IRDA_CACHE_LAST_LSAP + CACHE_ENTRY cache; /* Caching last slsap->dlsap->handle mapping */ +#endif + struct timer_list discovery_timer; + + hashbin_t *links; /* IrLAP connection table */ + hashbin_t *unconnected_lsaps; + hashbin_t *registry; + + __u8 hint[2]; /* Hint bits */ +}; + +/* Prototype declarations */ +int irlmp_init(void); +void irlmp_cleanup(void); + +struct lsap_cb *irlmp_open_lsap( __u8 slsap, struct notify_t *notify); +void irlmp_close_lsap( struct lsap_cb *self); + +void irlmp_register_layer( int service, int type, int do_discovery, + DISCOVERY_CALLBACK); +void irlmp_unregister_layer( int service, int type); + +void irlmp_register_irlap( struct irlap_cb *self, __u32 saddr, + struct notify_t *); +void irlmp_unregister_irlap( __u32 saddr); + +void irlmp_connect_request( struct lsap_cb *, __u8 dlsap_sel, __u32 daddr, + struct qos_info *, struct sk_buff *); +void irlmp_connect_indication( struct lsap_cb *self, struct sk_buff *skb); +void irlmp_connect_response( struct lsap_cb *, struct sk_buff *); +void irlmp_connect_confirm( struct lsap_cb *, struct sk_buff *); + + +void irlmp_disconnect_indication( struct lsap_cb *self, LM_REASON reason, + struct sk_buff *userdata); +void irlmp_disconnect_request( struct lsap_cb *, struct sk_buff *userdata); + +void irlmp_discovery_confirm( struct lap_cb *, hashbin_t *discovery_log); +void irlmp_discovery_indication( struct lap_cb *, DISCOVERY *discovery); +void irlmp_discovery_request( int nslots); +DISCOVERY *irlmp_get_discovery_response(void); + +void irlmp_data_request( struct lsap_cb *, struct sk_buff *); +void irlmp_udata_request( struct lsap_cb *, struct sk_buff *); +void irlmp_data_indication( struct lsap_cb *, struct sk_buff *); +void irlmp_udata_indication( struct lsap_cb *, struct sk_buff *); + +void irlmp_status_request(void); +void irlmp_status_indication( LINK_STATUS link, LOCK_STATUS lock); + +int irlmp_slsap_inuse( __u8 slsap); +__u8 irlmp_find_free_slsap(void); + +LM_REASON irlmp_convert_lap_reason( LAP_REASON); + +extern struct irlmp_cb *irlmp; + +#endif diff --git a/include/net/irda/irlmp_event.h b/include/net/irda/irlmp_event.h new file mode 100644 index 000000000000..1ffb6faa5537 --- /dev/null +++ b/include/net/irda/irlmp_event.h @@ -0,0 +1,113 @@ +/********************************************************************* + * + * Filename: irlmp_event.h + * Version: 0.1 + * Description: IrDA-LMP event handling + * Status: Experimental. + * Author: Dag Brattli + * Created at: Mon Aug 4 20:40:53 1997 + * Modified at: Wed Oct 28 14:58:23 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1997 Dag Brattli , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef IRLMP_EVENT_H +#define IRLMP_EVENT_H + +struct irlmp_cb; +struct lsap_cb; +struct lap_cb; + +/* LAP states */ +typedef enum { + /* IrLAP connection control states */ + LAP_STANDBY, /* No LAP connection */ + LAP_U_CONNECT, /* Starting LAP connection */ + LAP_ACTIVE, /* LAP connection is active */ +} IRLMP_STATE; + +/* LSAP connection control states */ +typedef enum { + LSAP_DISCONNECTED, /* No LSAP connection */ + LSAP_CONNECT, /* Connect indication from peer */ + LSAP_CONNECT_PEND, /* Connect request from service user */ + LSAP_DATA_TRANSFER_READY, /* LSAP connection established */ + LSAP_SETUP, /* Trying to set up LSAP connection */ + LSAP_SETUP_PEND, /* Request to start LAP connection */ +} LSAP_STATE; + +typedef enum { + /* LSAP events */ + LM_CONNECT_REQUEST, + LM_CONNECT_CONFIRM, + LM_CONNECT_RESPONSE, + LM_CONNECT_INDICATION, + + LM_DISCONNECT_INDICATION, + LM_DISCONNECT_REQUEST, + + LM_DATA_REQUEST, + LM_UDATA_REQUEST, + LM_DATA_INDICATION, + LM_UDATA_INDICATION, + + LM_WATCHDOG_TIMEOUT, + + /* IrLAP events */ + LM_LAP_CONNECT_REQUEST, + LM_LAP_CONNECT_INDICATION, + LM_LAP_CONNECT_CONFIRM, + LM_LAP_DISCONNECT_INDICATION, + LM_LAP_DISCONNECT_REQUEST, + LM_LAP_DISCOVERY_REQUEST, + LM_LAP_DISCOVERY_CONFIRM, + +} IRLMP_EVENT; + +/* + * Information which is used by the current thread, when executing in the + * state machine. + */ +struct irlmp_event { + IRLMP_EVENT *event; + struct sk_buff *skb; + + __u8 hint; + __u32 daddr; + __u32 saddr; + + __u8 slsap; + __u8 dlsap; + + int reason; + + DISCOVERY *discovery; +}; + +extern char *irlmp_state[]; +extern char *irlsap_state[]; + +void irlmp_watchdog_timer_expired( unsigned long data); +void irlmp_discovery_timer_expired( unsigned long data); + +void irlmp_next_station_state( IRLMP_STATE state); +void irlmp_next_lsap_state( struct lsap_cb *self, LSAP_STATE state); +void irlmp_next_lap_state( struct lap_cb *self, IRLMP_STATE state); + +void irlmp_do_lap_event( struct lap_cb *self, IRLMP_EVENT event, + struct sk_buff *skb); +void irlmp_do_lsap_event( struct lsap_cb *self, IRLMP_EVENT event, + struct sk_buff *skb); + +#endif diff --git a/include/net/irda/irlmp_frame.h b/include/net/irda/irlmp_frame.h new file mode 100644 index 000000000000..64960f31dcc4 --- /dev/null +++ b/include/net/irda/irlmp_frame.h @@ -0,0 +1,57 @@ +/********************************************************************* + * + * Filename: irlmp_frame.h + * Version: 0.1 + * Description: + * Status: Experimental. + * Author: Dag Brattli + * Created at: Tue Aug 19 02:09:59 1997 + * Modified at: Sun Oct 25 00:30:31 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1997 Dag Brattli , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef IRMLP_FRAME_H +#define IRMLP_FRAME_H + +#include + +/* Frame opcodes */ +#define CONNECT_CMD 0x01 +#define CONNECT_CNF 0x81 +#define DISCONNECT 0x02 +#define ACCESSMODE_CMD 0x03 +#define ACCESSMODE_CNF 0x83 + +#define CONTROL_BIT 0x80 + +inline void irlmp_send_data_pdu( struct lap_cb *self, __u8 dlsap, __u8 slsap, + int expedited, struct sk_buff *skb); +void irlmp_send_lcf_pdu( struct lap_cb *self, __u8 dlsap, __u8 slsap, + __u8 opcode, struct sk_buff *skb); +void irlmp_link_data_indication( struct lap_cb *, int reliable, + struct sk_buff *); +void irlmp_link_connect_indication( struct lap_cb *, struct qos_info *qos, + struct sk_buff *skb); +void irlmp_link_connect_request( __u32 daddr); +void irlmp_link_connect_confirm( struct lap_cb *self, struct qos_info *qos, + struct sk_buff *skb); +void irlmp_link_disconnect_indication( struct lap_cb *self, + struct irlap_cb *irlap, + LAP_REASON reason, + struct sk_buff *); +void irlmp_link_discovery_confirm( struct lap_cb *self, hashbin_t *log); +/* void irlmp_link_disconnect_request( void); */ + +#endif diff --git a/include/net/irda/irmod.h b/include/net/irda/irmod.h new file mode 100644 index 000000000000..c79d1b5be648 --- /dev/null +++ b/include/net/irda/irmod.h @@ -0,0 +1,263 @@ +/********************************************************************* + * + * Filename: irmod.h + * Version: 0.3 + * Description: IrDA module and utilities functions + * Status: Experimental. + * Author: Dag Brattli + * Created at: Mon Dec 15 13:58:52 1997 + * Modified at: Mon Dec 7 01:40:35 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charg. + * + ********************************************************************/ + +#ifndef IRMOD_H +#define IRMOD_H + +#include +#include + +#include +#include + +#define IRMGR_IOC_MAGIC 'm' +#define IRMGR_IOCTNPC _IO(IRMGR_IOC_MAGIC, 1) +#define IRMGR_IOC_MAXNR 1 + +/* + * Events that we pass to the user space manager + */ +typedef enum { + EVENT_DEVICE_DISCOVERED = 0, + EVENT_REQUEST_MODULE, + EVENT_IRLAN_START, + EVENT_IRLAN_STOP, + EVENT_IRLPT_START, + EVENT_IRLPT_STOP, + EVENT_IROBEX_START, + EVENT_IROBEX_STOP, + EVENT_IRDA_STOP, + EVENT_NEED_PROCESS_CONTEXT, +} IRMGR_EVENT; + +/* + * Event information passed to the IrManager daemon process + */ +struct irmanager_event { + IRMGR_EVENT event; + char devname[10]; + char info[32]; + int service; + __u32 saddr; + __u32 daddr; +}; + +typedef void (*TODO_CALLBACK)( void *self, __u32 param); + +/* + * Same as irmanager_event but this one can be queued and inclueds some + * addtional information + */ +struct irda_event { + QUEUE q; /* Must be first */ + + struct irmanager_event event; +}; + +/* + * Funtions with needs to be called with a process context + */ +struct irda_todo { + QUEUE q; /* Must be first */ + + void *self; + TODO_CALLBACK callback; + __u32 param; +}; + +/* + * Main structure for the IrDA device (not much here :-) + */ +struct irda { + struct miscdevice dev; + struct wait_queue *wait_queue; + + QUEUE *event_queue; /* Events queued for the irmanager */ + QUEUE *todo_queue; /* Todo list */ +}; + +typedef struct { + char irda_call[7]; /* 6 call + SSID (shifted ascii!) */ +} irda_address; + +struct sockaddr_irda { + short sirda_family; + irda_address sirda_call; + int sirda_ndigis; +}; + +/* + * This type is used by the protocols that transmit 16 bits words in + * little endian format. A little endian machine stores MSB of word in + * byte[1] and LSB in byte[0]. A big endian machine stores MSB in byte[0] + * and LSB in byte[1]. + */ +typedef union { + __u16 word; + __u8 byte[2]; +} __u16_host_order; + +/* + * Information monitored by some layers + */ +struct irda_statistics +{ + int rx_packets; /* total packets received */ + int tx_packets; /* total packets transmitted */ + int rx_errors; /* bad packets received */ + int tx_errors; /* packet transmit problems */ + int rx_dropped; /* no space in linux buffers */ + int tx_dropped; /* no space available in linux */ + int rx_compressed; + int tx_compressed; + int rx_bytes; /* total bytes received */ + int tx_bytes; /* total bytes transmitted */ + + int multicast; /* multicast packets received */ + int collisions; + + /* detailed rx_errors: */ + int rx_length_errors; + int rx_over_errors; /* receiver ring buff overflow */ + int rx_crc_errors; /* recved pkt with crc error */ + int rx_frame_errors; /* recv'd frame alignment error */ + int rx_fifo_errors; /* recv'r fifo overrun */ + int rx_missed_errors; /* receiver missed packet */ + + /* detailed tx_errors */ + int tx_aborted_errors; + int tx_carrier_errors; + int tx_fifo_errors; + int tx_heartbeat_errors; + int tx_window_errors; +}; + +typedef enum { + NO_CHANGE, + LOCKED, + UNLOCKED, +} LOCK_STATUS; + +/* Misc status information */ +typedef enum { + STATUS_OK, + STATUS_ABORTED, + STATUS_NO_ACTIVITY, + STATUS_NOISY, + STATUS_REMOTE, +} LINK_STATUS; + +typedef enum { /* FIXME check the two first reason codes */ + LAP_DISC_INDICATION=1, /* Received a disconnect request from peer */ + LAP_NO_RESPONSE, /* To many retransmits without response */ + LAP_RESET_INDICATION, /* To many retransmits, or invalid nr/ns */ + LAP_FOUND_NONE, /* No devices were discovered */ + LAP_MEDIA_BUSY, + LAP_PRIMARY_CONFLICT, +} LAP_REASON; + +/* + * IrLMP disconnect reasons. The order is very important, since they + * correspond to disconnect reasons sent in IrLMP disconnect frames, so + * please do not touch :-) + */ +typedef enum { + LM_USER_REQUEST = 1, /* User request */ + LM_LAP_DISCONNECT, /* Unexpected IrLAP disconnect */ + LM_CONNECT_FAILURE, /* Failed to establish IrLAP connection */ + LM_LAP_RESET, /* IrLAP reset */ + LM_INIT_DISCONNECT, /* Link Management initiated disconnect */ +} LM_REASON; /* FIXME: Just for now */ + +/* + * IrLMP character code values + */ +#define CS_ASCII 0x00 +#define CS_ISO_8859_1 0x01 +#define CS_ISO_8859_2 0x02 +#define CS_ISO_8859_3 0x03 +#define CS_ISO_8859_4 0x04 +#define CS_ISO_8859_5 0x05 +#define CS_ISO_8859_6 0x06 +#define CS_ISO_8859_7 0x07 +#define CS_ISO_8859_8 0x08 +#define CS_ISO_8859_9 0x09 +#define CS_UNICODE 0xff + +/* + * The DISCOVERY structure is used for both discovery requests and responses + */ +#define DISCOVERY struct discovery_t +struct discovery_t { + QUEUE queue; /* Must be first! */ + + __u32 saddr; /* Which link the device was discovered */ + __u32 daddr; /* Remote device address */ + LAP_REASON condition; /* More info about the discovery */ + + __u8 hint[2]; /* Discovery hint bits */ + __u8 charset; + char info[32]; /* Usually the name of the device */ + __u8 info_len; /* Length of device info field */ + + int gen_addr_bit; /* Need to generate a new device address? */ +}; + +typedef enum { FLOW_STOP, FLOW_START } LOCAL_FLOW; + +/* + * Notify structure used between transport and link management layers + */ +struct notify_t { + void (*data_indication)( void *instance, void *sap, + struct sk_buff *skb); + void (*udata_indication)( void *instance, void *sap, + struct sk_buff *skb); + void (*connect_confirm)( void *instance, void *sap, + struct qos_info *qos, int max_sdu_size, + struct sk_buff *skb); + void (*connect_indication)( void *instance, void *sap, + struct qos_info *qos, int max_sdu_size, + struct sk_buff *skb); + void (*disconnect_indication)( void *instance, void *sap, + LM_REASON reason, struct sk_buff *); + void (*flow_indication)( void *instance, void *sap, LOCAL_FLOW flow); + void *instance; /* Layer instance pointer */ + char name[16]; /* Name of layer */ +}; + +#define NOTIFY_MAX_NAME 16 + +int irmod_init_module(void); +void irmod_cleanup_module(void); + +inline int irda_lock( int *lock); +inline int irda_unlock( int *lock); + +void irda_notify_init( struct notify_t *notify); + +void irda_execute_as_process( void *self, TODO_CALLBACK callback, __u32 param); +void irmanager_notify( struct irmanager_event *event); + +#endif diff --git a/include/net/irda/irobex.h b/include/net/irda/irobex.h new file mode 100644 index 000000000000..da16195051b2 --- /dev/null +++ b/include/net/irda/irobex.h @@ -0,0 +1,134 @@ +/********************************************************************* + * + * Filename: irobex.h + * Version: + * Description: + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sat Jul 4 22:43:57 1998 + * Modified at: Mon Oct 19 12:32:33 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef IROBEX_H +#define IROBEX_H + +#include +#include +#include +/* #include */ +#include + +#include +#include +#include + +#define LOW_THRESHOLD 4 +#define HIGH_THRESHOLD 8 +#define IROBEX_MAX_QUEUE 12 + +/* Small structure to be used by the IOCTL call */ +struct irobex_ioc_t { + __u32 daddr; +}; + +#define IROBEX_IOC_MAGIC 'k' + +#define IROBEX_IOCSCONNECT _IOW(IROBEX_IOC_MAGIC, 1, 4) +#define IROBEX_IOCSDISCONNECT _IOW(IROBEX_IOC_MAGIC, 2, 4) +#define IROBEX_IOC_MAXNR 2 + + +#define IROBEX_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER) + +struct irobex_cb { + QUEUE queue; /* Must be first! */ + + int magic; /* magic used to detect corruption of the struct */ + + __u32 saddr; /* my local address */ + __u32 daddr; /* peer address */ + unsigned long time_discovered; + + char devname[9]; /* name of the registered device */ + struct tsap_cb *tsap; + int connected; + int eof; + + __u8 dtsap_sel; /* remote TSAP address */ + __u8 stsap_sel; /* local TSAP address */ + + int irlap_data_size; + + struct miscdevice dev; + + int count; /* open count */ + + struct sk_buff_head rx_queue; /* Receive queue */ + + struct wait_queue *read_wait; + struct wait_queue *write_wait; + + /* These wait queues are used for setting up a connections */ + struct wait_queue *connect_wait; + struct wait_queue *discover_wait; + struct wait_queue *ias_wait; + + struct fasync_struct *async; + + struct timer_list watchdog_timer; + + LOCAL_FLOW tx_flow; + LOCAL_FLOW rx_flow; +}; + +int irobex_init(void); +void irobex_cleanup(void); +struct irobex_cb *irobex_open(void); +void irobex_close( struct irobex_cb *self); + +void irobex_discovery_indication( DISCOVERY *); + +void irobex_data_request( int handle, struct sk_buff *skb); +void irobex_data_indication( void *instance, void *sap, struct sk_buff *skb); +void irobex_control_data_indication( void *instance, void *sap, + struct sk_buff *skb); + +void irobex_connect_request( struct irobex_cb *self); +void irobex_connect(struct irobex_cb *self, struct sk_buff *skb); +void irobex_connect_confirm( void *instance, void *sap, struct qos_info *qos, + int max_sdu_size, struct sk_buff *skb); +void irobex_disconnect_indication( void *instance, void *sap, LM_REASON reason, + struct sk_buff *skb); +void irobex_flow_indication( void *instance, void *sap, LOCAL_FLOW flow); + +void irobex_extract_params( struct sk_buff *skb); +void irobex_get_value_confirm(__u16 obj_id, struct ias_value *value, + void *priv); +void irobex_register_server( struct irobex_cb *self); + +void irobex_watchdog_timer_expired( unsigned long data); + +inline void irobex_start_watchdog_timer( struct irobex_cb *self, + int timeout) +{ + irda_start_timer( &self->watchdog_timer, timeout, (unsigned long) self, + irobex_watchdog_timer_expired); +} + + +extern struct irobex_cb *irobex; + +#endif diff --git a/include/net/irda/irport.h b/include/net/irda/irport.h new file mode 100644 index 000000000000..0ad4cc786a11 --- /dev/null +++ b/include/net/irda/irport.h @@ -0,0 +1,61 @@ +/********************************************************************* + * + * Filename: irport.h + * Version: 0.1 + * Description: Serial driver for IrDA + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sun Aug 3 13:49:59 1997 + * Modified at: Wed Nov 4 15:10:41 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1997, 1998 Dag Brattli + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef IRPORT_H +#define IRPORT_H + +#include +#include +#include + +#include + +#define SPEED_DEFAULT 9600 +#define SPEED_MAX 115200 + +/* + * These are the supported serial types. + */ +#define PORT_UNKNOWN 0 +#define PORT_8250 1 +#define PORT_16450 2 +#define PORT_16550 3 +#define PORT_16550A 4 +#define PORT_CIRRUS 5 +#define PORT_16650 6 +#define PORT_MAX 6 + +#define FRAME_MAX_SIZE 2048 + +void irport_close( int iobase); +int irport_open( int iobase); +int irport_detect(struct irda_device *idev); + +void irport_change_speed( int iobase, int speed); +void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs); + +int irport_hard_xmit( struct sk_buff *skb, struct device *dev); + +#endif diff --git a/include/net/irda/irqueue.h b/include/net/irda/irqueue.h new file mode 100644 index 000000000000..0551e3b523c6 --- /dev/null +++ b/include/net/irda/irqueue.h @@ -0,0 +1,106 @@ +/********************************************************************* + * + * Filename: irqueue.h + * Version: 0.3 + * Description: General queue implementation + * Status: Experimental. + * Author: Dag Brattli + * Created at: Tue Jun 9 13:26:50 1998 + * Modified at: Sun Oct 25 00:26:31 1998 + * Modified by: Dag Brattli + * + * Copyright (C) 1998, Aage Kvalnes + * Copyright (c) 1998, Dag Brattli + * All Rights Reserved. + * + * This code is taken from the Vortex Operating System written by Aage + * Kvalnes and has been ported to Linux and Linux/IR by Dag Brattli + * + * 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. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include + +#include + +#ifndef QUEUE_H +#define QUEUE_H + +#define NAME_SIZE 32 + +/* + * Hash types + */ +#define HB_NOLOCK 0 +#define HB_GLOBAL 1 +#define HB_LOCAL 2 +#define HB_SORTED 4 + +/* + * Hash defines + */ +#define HASHBIN_SIZE 8 +#define HASHBIN_MASK 0x7 + +typedef void (*FREE_FUNC)( void *arg); + +/* + * Hashbin + */ +#define GET_HASHBIN(x) ( x & HASHBIN_MASK ) + +#define QUEUE struct queue_t +struct queue_t { + QUEUE* q_next; + QUEUE* q_prev; + + char q_name[ NAME_SIZE]; + __u32 q_hash; +}; + +typedef struct hashbin_t { + int magic; + int hb_type; + int hb_size; + spinlock_t hb_mutex[ HASHBIN_SIZE ] ALIGN; + QUEUE* hb_queue[ HASHBIN_SIZE ] ALIGN; + + QUEUE* hb_current; +} hashbin_t; + +hashbin_t *hashbin_new( int type); +int hashbin_delete( hashbin_t* hashbin, FREE_FUNC func); +int hashbin_clear( hashbin_t* hashbin, FREE_FUNC free_func); +void hashbin_insert( hashbin_t* hashbin, QUEUE* entry, __u32 hashv, + char* name); +void* hashbin_find( hashbin_t* hashbin, __u32 hashv, char* name); +void* hashbin_remove( hashbin_t* hashbin, __u32 hashv, char* name); +void* hashbin_remove_first( hashbin_t *hashbin); +QUEUE *hashbin_get_first( hashbin_t *hashbin); +QUEUE *hashbin_get_next( hashbin_t *hashbin); + +void enqueue_last(QUEUE **queue, QUEUE* element); +void enqueue_first(QUEUE **queue, QUEUE* element); +QUEUE *dequeue_first(QUEUE **queue); + +/* + * Function hashbin_get_size (hashbin) + * + * Returns the number of elements in the hashbin + * + */ +extern __inline__ int hashbin_get_size( hashbin_t* hashbin) +{ + return hashbin->hb_size; +} + +#endif diff --git a/include/net/irda/irttp.h b/include/net/irda/irttp.h new file mode 100644 index 000000000000..02a486dd54c3 --- /dev/null +++ b/include/net/irda/irttp.h @@ -0,0 +1,136 @@ +/********************************************************************* + * + * Filename: irttp.h + * Version: 0.3 + * Description: Tiny Transport Protocol (TTP) definitions + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sun Aug 31 20:14:31 1997 + * Modified at: Sat Dec 5 13:48:12 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef IRTTP_H +#define IRTTP_H + +#include +#include + +#include +#include +#include +#include + +#define TTP_MAX_CONNECTIONS LM_MAX_CONNECTIONS +#define TTP_HEADER 1 +#define TTP_HEADER_WITH_SAR 6 +#define TTP_PARAMETERS 0x80 +#define TTP_MORE 0x80 + +#define DEFAULT_INITIAL_CREDIT 22 + +#define LOW_THRESHOLD 4 +#define HIGH_THRESHOLD 8 +#define TTP_MAX_QUEUE 22 + +/* Some priorities for disconnect requests */ +#define P_NORMAL 0 +#define P_HIGH 1 + +#define SAR_DISABLE 0 + +/* + * This structure contains all data assosiated with one instance of a TTP + * connection. + */ +struct tsap_cb { + QUEUE queue; /* For linking it into the hashbin */ + int magic; /* Just in case */ + + int max_seg_size; /* Max data that fit into an IrLAP frame */ + + __u8 stsap_sel; /* Source TSAP */ + __u8 dtsap_sel; /* Destination TSAP */ + + struct lsap_cb *lsap; /* Corresponding LSAP to this TSAP */ + + __u8 connected; /* TSAP connected */ + + __u8 initial_credit; /* Initial credit to give peer */ + + int avail_credit; /* Available credit to return to peer */ + int remote_credit; /* Credit held by peer TTP entity */ + int send_credit; /* Credit held by local TTP entity */ + + struct sk_buff_head tx_queue; /* Frames to be transmitted */ + struct sk_buff_head rx_queue; /* Received frames */ + struct sk_buff_head rx_fragments; + int tx_queue_lock; + int rx_queue_lock; + + struct notify_t notify; /* Callbacks to client layer */ + + struct irda_statistics stats; + struct timer_list todo_timer; + + int rx_sdu_busy; /* RxSdu.busy */ + int rx_sdu_size; /* The current size of a partially received frame */ + int rx_max_sdu_size; /* Max receive user data size */ + + int tx_sdu_busy; /* TxSdu.busy */ + int tx_max_sdu_size; /* Max transmit user data size */ + + int no_defrag; /* Don't reassemble received fragments */ + + int disconnect_pend; /* Disconnect, but still data to send */ + struct sk_buff *disconnect_skb; +}; + +struct irttp_cb { + int magic; + + hashbin_t *tsaps; +}; + +int irttp_init(void); +void irttp_cleanup(void); + +struct tsap_cb *irttp_open_tsap( __u8 stsap, int credit, + struct notify_t *notify); +void irttp_close_tsap( struct tsap_cb *self); + +int irttp_data_request( struct tsap_cb *self, struct sk_buff *skb); +int irttp_udata_request( struct tsap_cb *self, struct sk_buff *skb); + +void irttp_connect_request( struct tsap_cb *self, __u8 dtsap_sel, __u32 daddr, + struct qos_info *qos, int max_sdu_size, + struct sk_buff *userdata); +void irttp_connect_confirm( void *instance, void *sap, struct qos_info *qos, + int max_sdu_size, struct sk_buff *skb); +void irttp_connect_response( struct tsap_cb *self, int max_sdu_size, + struct sk_buff *userdata); + +void irttp_disconnect_request( struct tsap_cb *self, struct sk_buff *skb, + int priority); +void irttp_flow_request( struct tsap_cb *self, LOCAL_FLOW flow); + +static __inline__ void irttp_no_reassemble( struct tsap_cb *self) +{ + self->no_defrag = TRUE; +} + +extern struct irttp_cb *irttp; + +#endif /* IRTTP_H */ diff --git a/include/net/irda/irtty.h b/include/net/irda/irtty.h new file mode 100644 index 000000000000..313a32d9b3eb --- /dev/null +++ b/include/net/irda/irtty.h @@ -0,0 +1,68 @@ +/********************************************************************* + * + * Filename: irtty.h + * Version: 0.1 + * Description: + * Status: Experimental. + * Author: Dag Brattli + * Created at: Tue Dec 9 21:13:12 1997 + * Modified at: Mon Dec 14 11:22:37 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1997 Dag Brattli, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef IRTTY_H +#define IRTTY_H + +#include +#include +#include + +#include +#include +#include + +#include + +#define IRTTY_IOC_MAGIC 'e' +#define IRTTY_IOCTDONGLE _IO(IRTTY_IOC_MAGIC, 1) +#define IRTTY_IOC_MAXNR 1 + +#ifndef N_IRDA +#define N_IRDA 11 /* This one should go in */ +#endif + +struct dongle_q { + QUEUE q; + + struct dongle *dongle; +}; + +struct irtty_cb { + QUEUE q; /* Must be first */ + +/* char name[16]; */ + + int magic; + + struct tty_struct *tty; /* Ptr to TTY structure */ + struct irda_device idev; + + struct dongle_q *dongle_q; /* Has this tty got a dongle attached? */ +}; + +int irtty_register_dongle( struct dongle *dongle); +void irtty_unregister_dongle( struct dongle *dongle); + +#endif diff --git a/include/net/irda/irvtd.h b/include/net/irda/irvtd.h new file mode 100644 index 000000000000..43d61c9c08be --- /dev/null +++ b/include/net/irda/irvtd.h @@ -0,0 +1,104 @@ +/********************************************************************* + * + * Filename: irvtd.h + * Version: 0.1 + * Sources: irlpt.h + * + * Copyright (c) 1998, Takahide Higuchi , + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * I, Takahide Higuchi, provide no warranty for any of this software. + * This material is provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef IRCOMM_H +#define IRCOMM_H + +#include +#include +#include + +#include +#include +#include + + +#define IRVTD_MAGIC 0xff545943 /* random */ +#define COMM_MAX_TTY 1 +#define IRVTD_RX_QUEUE_HIGH 10 +#define IRVTD_RX_QUEUE_LOW 2 + + +/* + * Serial input interrupt line counters -- external structure + * Four lines can interrupt: CTS, DSR, RI, DCD + * + * this structure must be compatible with serial_icounter_struct defined in + * . + */ +struct icounter_struct { + int cts, dsr, rng, dcd; + int reserved[16]; +}; + +struct irvtd_cb { + + int magic; /* magic used to detect corruption of the struct */ + + /* if daddr is NULL, remote device have not been discovered yet */ + + int rx_disable; + struct sk_buff *txbuff; /* buffer queue */ + struct sk_buff_head rxbuff; /* buffer queue */ + struct ircomm_cb *comm; /* ircomm instance */ + + /* + * These members are used for compatibility with usual serial device. + * See linux/serial.h + */ + + int baud_base; + int flags; + struct tty_struct *tty; + + int line; + int count; /* open count */ + int blocked_open; + struct wait_queue *open_wait; + struct wait_queue *close_wait; + struct wait_queue *delta_msr_wait; + struct wait_queue *tx_wait; + + struct tq_struct rx_tqueue; + + long pgrp; + long session; + struct termios normal_termios; + struct termios callout_termios; + unsigned short closing_wait; /* time to wait before closing */ + unsigned short close_delay; + + int mcr; + int msr; + int cts_stoptx; + int ttp_stoptx; + int ttp_stoprx; + struct icounter_struct icount; + int read_status_mask; + int ignore_status_mask; +}; + + +/* Debug function */ + +/* #define CHECK_SKB(skb) check_skb((skb), __LINE__,__FILE__) */ + + + +#endif diff --git a/include/net/irda/irvtd_driver.h b/include/net/irda/irvtd_driver.h new file mode 100644 index 000000000000..4983b3d2c56e --- /dev/null +++ b/include/net/irda/irvtd_driver.h @@ -0,0 +1,122 @@ +/********************************************************************* + * + * Filename: irvtd_driver.h + * Version: 0.1 + * + * Copyright (c) 1998, Takahide Higuchi , + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * I, Takahide Higuchi, provide no warranty for any of this software. + * This material is provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include + +#include +#include +#include + + +#define VSP_TYPE_NORMAL 1 +#define VSP_TYPE_CALLOUT 2 +#define IRCOMM_MAJOR 60; /* Zero means automatic allocation + 60,61,62,and 63 is reserved for experiment */ +#define IRVTD_MINOR 64 +#define IRVTD_CALLOUT_MINOR 32 + +#define IRVTD_TYPE_NORMAL 11 +#define IRVTD_TYPE_CALLOUT 12 + + +#define IRCOMM_HEADER 1 +#define IRCOMM_RESERVE LAP_HEADER+LMP_HEADER+TTP_HEADER+IRCOMM_HEADER + + + + + +/* + * Definitions for ircomm_cb_struct flags field + * this section is "stolen" from linux-kernel (drivers/char/serial.c) + */ +#define IRVTD_ASYNC_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes + on the callout port */ +/* #define IRVTD_ASYNC_FOURPORT 0x0002 */ +/* Set OU1, OUT2 per AST Fourport settings */ + +#define IRVTD_ASYNC_SAK 0x0004 /* Secure Attention Key (Orange book) */ + +#define IRVTD_ASYNC_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */ + +#define IRVTD_ASYNC_SPD_MASK 0x0030 +#define IRVTD_ASYNC_SPD_HI 0x0010 /* Use 56000 instead of 38400 bps */ + +#define IRVTD_ASYNC_SPD_VHI 0x0020 /* Use 115200 instead of 38400 bps */ +#define IRVTD_ASYNC_SPD_CUST 0x0030 /* Use user-specified divisor */ + +#define IRVTD_ASYNC_SKIP_TEST 0x0040 /* Skip UART test during autoconfiguration */ +#define IRVTD_ASYNC_AUTO_IRQ 0x0080 /* Do automatic IRQ during autoconfiguration */ +#define IRVTD_ASYNC_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */ +#define IRVTD_ASYNC_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */ +#define IRVTD_ASYNC_CALLOUT_NOHUP 0x0400 /* Don't do hangups for cua device */ + +#define IRVTD_ASYNC_FLAGS 0x0FFF /* Possible legal async flags */ +#define IRVTD_ASYNC_USR_MASK 0x0430 /* Legal flags that non-privileged + * users can set or reset */ + +/* Internal flags used only by kernel/chr_drv/serial.c */ +#define IRVTD_ASYNC_INITIALIZED 0x80000000 /* Serial port was initialized */ +#define IRVTD_ASYNC_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */ +#define IRVTD_ASYNC_NORMAL_ACTIVE 0x20000000 /* Normal device is active */ +#define IRVTD_ASYNC_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */ +#define IRVTD_ASYNC_CLOSING 0x08000000 /* Serial port is closing */ +#define IRVTD_ASYNC_CTS_FLOW 0x04000000 /* Do CTS flow control */ +#define IRVTD_ASYNC_CHECK_CD 0x02000000 /* i.e., CLOCAL */ +#define IRVTD_ASYNC_SHARE_IRQ 0x01000000 /* for multifunction cards */ + + +#define IRVTD_ASYNC_CLOSING_WAIT_INF 0 +#define IRVTD_ASYNC_CLOSING_WAIT_NONE 65535 + +/**************************************/ + +#define DELTA_DTR 0x01 +#define DELTA_RTS 0x02 +#define MCR_DTR 0x04 +#define MCR_RTS 0x08 + +#define DELTA_CTS 0x01 +#define DELTA_DSR 0x02 +#define DELTA_RI 0x04 +#define DELTA_DCD 0x08 +#define MSR_CTS 0x10 +#define MSR_DSR 0x20 +#define MSR_RI 0x40 +#define MSR_DCD 0x80 + +#define LSR_OE 0x02 /* Overrun error indicator */ +#define LSR_PE 0x04 /* Parity error indicator */ +#define LSR_FE 0x08 /* Frame error indicator */ +#define LSR_BI 0x01 /* Break interrupt indicator */ + + + +/**************************************/ + + + + +int irvtd_register_ttydriver(void); +void irvtd_unregister_ttydriver(void); + +void irvtd_flush_chars(struct tty_struct *tty); + + + + diff --git a/include/net/irda/pc87108.h b/include/net/irda/pc87108.h new file mode 100644 index 000000000000..ed47bdc1b94a --- /dev/null +++ b/include/net/irda/pc87108.h @@ -0,0 +1,194 @@ +/********************************************************************* + * + * Filename: pc87108.h + * Version: + * Description: + * Status: Experimental. + * Author: Dag Brattli + * Created at: Fri Nov 13 14:37:40 1998 + * Modified at: Thu Dec 10 19:58:20 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli + * Copyright (c) 1998 Lichen Wang, + * Copyright (c) 1998 Actisys Corp., www.actisys.com + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef PC87108_H +#define PC87108_H + +#include + +/* Flags for configuration register CRF0 */ +#define APEDCRC 0x02 +#define ENBNKSEL 0x01 + +/* Set 0 */ +#define TXD 0x00 /* Transmit data port */ +#define RXD 0x00 /* Receive data port */ + +/* Register 1 */ +#define IER 0x01 /* Interrupt Enable Register*/ +#define IER_RXHDL_IE 0x01 /* Receiver high data level interrupt */ +#define IER_TXLDL_IE 0x02 /* Transeiver low data level interrupt */ +#define IER_LS_IE 0x04//* Link Status Interrupt */ +#define IER_ETXURI 0x04 /* Tx underrun */ +#define IER_DMA_IE 0x10 /* DMA finished interrupt */ +#define IER_TXEMP_IE 0x20 +#define IER_SFIF_IE 0x40 /* Frame status FIFO intr */ +#define IER_TMR_IE 0x80 /* Timer event */ + +#define FCR 0x02 /* (write only) */ +#define FCR_FIFO_EN 0x01 /* Enable FIFO's */ +#define FCR_RXSR 0x02 /* Rx FIFO soft reset */ +#define FCR_TXSR 0x04 /* Tx FIFO soft reset */ +#define FCR_RXTH 0x80 /* Rx FIFO threshold (set to 16) */ +#define FCR_TXTH 0x20 /* Tx FIFO threshold (set to 17) */ + +#define EIR 0x02 /* (read only) */ +#define EIR_RXHDL_EV 0x01 +#define EIR_TXLDL_EV 0x02 +#define EIR_LS_EV 0x04 +#define EIR_DMA_EV 0x10 +#define EIR_TXEMP_EV 0x20 +#define EIR_SFIF_EV 0x40 +#define EIR_TMR_EV 0x80 + +#define LCR 0x03 /* Link control register */ +#define LCR_WLS_8 0x03 /* 8 bits */ + +#define BSR 0x03 /* Bank select register */ +#define BSR_BKSE 0x80 +#define BANK0 LCR_WLS_8 /* Must make sure that we set 8N1 */ +#define BANK1 0x80 +#define BANK2 0xe0 +#define BANK3 0xe4 +#define BANK4 0xe8 +#define BANK5 0xec +#define BANK6 0xf0 +#define BANK7 0xf4 + +#define MCR 0x04 /* Mode Control Register */ +#define MCR_MODE_MASK ~(0xd0) +#define MCR_UART 0x00 +#define MCR_RESERVED 0x20 +#define MCR_SHARP_IR 0x40 +#define MCR_SIR 0x60 +#define MCR_MIR 0x80 +#define MCR_FIR 0xa0 +#define MCR_CEIR 0xb0 +#define MCR_DMA_EN 0x04 +#define MCR_EN_IRQ 0x08 +#define MCR_TX_DFR 0x08 + +#define LSR 0x05 /* Link status register */ +#define LSR_RXDA 0x01 /* Receiver data available */ +#define LSR_TXRDY 0x20 /* Transmitter ready */ +#define LSR_TXEMP 0x40 /* Transmitter empty */ + +#define ASCR 0x07 /* Auxillary Status and Control Register */ +#define ASCR_RXF_TOUT 0x01 /* Rx FIFO timeout */ +#define ASCR_FEND_INF 0x02 /* Frame end bytes in rx FIFO */ +#define ASCR_S_EOT 0x04 /* Set end of transmission */ +#define ASCT_RXBSY 0x20 /* Rx busy */ +#define ASCR_TXUR 0x40 /* Transeiver underrun */ +#define ASCR_CTE 0x80 /* Clear timer event */ + +/* Bank 2 */ +#define BGDL 0x00 /* Baud Generator Divisor Port (Low Byte) */ +#define BGDH 0x01 /* Baud Generator Divisor Port (High Byte) */ + +#define ECR1 0x02 /* Extended Control Register 1 */ +#define ECR1_EXT_SL 0x01 /* Extended Mode Select */ +#define ECR1_DMANF 0x02 /* DMA Fairness */ +#define ECR1_DMATH 0x04 +#define ECR1_DMASWP 0x08 /* DMA Swap */ + +#define EXCR2 0x04 +#define EXCR2_TFSIZ 0x01 /* Rx FIFO size = 32 */ +#define EXCR2_RFSIZ 0x04 /* Tx FIFO size = 32 */ + +#define TXFLV 0x06 /* Tx FIFO level */ +#define RXFLV 0x07 /* Rx FIFO level */ + +/* Bank 3 */ +#define MID 0x00 + +/* Bank 4 */ +#define TMRL 0x00 /* Timer low byte */ +#define TMRH 0x01 /* Timer high byte */ +#define IRCR1 0x02 /* Infrared control register 1 */ +#define IRCR1_TMR_EN 0x01 /* Timer enable */ + +#define TFRLL 0x04 +#define TFRLH 0x05 +#define RFRLL 0x06 +#define RFRLH 0x07 + +/* Bank 5 */ +#define IRCR2 0x04 /* Infrared control register 2 */ +#define IRCR2_MDRS 0x04 /* MIR data rate select */ +#define IRCR2_FEND_MD 0x20 /* */ + +#define FRM_ST 0x05 /* Frame status FIFO */ +#define FRM_ST_VLD 0x80 /* Frame status FIFO data valid */ +#define FRM_ST_ERR_MSK 0x5f +#define FRM_ST_LOST_FR 0x40 /* Frame lost */ +#define FRM_ST_MAX_LEN 0x10 /* Max frame len exceeded */ +#define FRM_ST_PHY_ERR 0x08 /* Physical layer error */ +#define FRM_ST_BAD_CRC 0x04 +#define FRM_ST_OVR2 0x02 /* Receive overrun */ +#define FRM_ST_OVR1 0x01 /* Frame status FIFO overrun */ + +#define RFLFL 0x06 +#define RFLFH 0x07 + +/* Bank 6 */ +#define IR_CFG2 0x00 +#define IR_CFG2_DIS_CRC 0x02 + +/* Bank 7 */ +#define IRM_CR 0x07 /* Infrared module control register */ +#define IRM_CR_IRX_MSL 0x40 +#define IRM_CR_AF_MNT 0x80 /* Automatic format */ + +/* For storing entries in the status FIFO */ +struct st_fifo_entry { + int status; + int len; +}; + +struct st_fifo { + struct st_fifo_entry entries[10]; + int head; + int tail; + int len; +}; + +/* Private data for each instance */ +struct pc87108 { + struct st_fifo st_fifo; + + int tx_buff_offsets[10]; /* Offsets between frames in tx_buff */ + int tx_len; /* Number of frames in tx_buff */ + + struct irda_device idev; +}; + +static inline void switch_bank( int iobase, int bank) +{ + outb( bank, iobase+BSR); +} + +#endif diff --git a/include/net/irda/qos.h b/include/net/irda/qos.h new file mode 100644 index 000000000000..39ca2b7b9f92 --- /dev/null +++ b/include/net/irda/qos.h @@ -0,0 +1,104 @@ +/********************************************************************* + * + * Filename: qos.h + * Version: 0.1 + * Description: Quality of Service definitions + * Status: Experimental. + * Author: Dag Brattli + * Created at: Fri Sep 19 23:21:09 1997 + * Modified at: Wed Dec 9 10:32:47 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef QOS_H +#define QOS_H + +#include +#include + +#define PI_BAUD_RATE 0x01 +#define PI_MAX_TURN_TIME 0x82 +#define PI_DATA_SIZE 0x83 +#define PI_WINDOW_SIZE 0x84 +#define PI_ADD_BOFS 0x85 +#define PI_MIN_TURN_TIME 0x86 +#define PI_LINK_DISC 0x08 +#define PI_COMPRESSION 0x07 /* Just a random pick */ + + +#define IR_115200_MAX 0x3f + +/* Baud rates (first byte) */ +#define IR_2400 0x01 +#define IR_9600 0x02 +#define IR_19200 0x04 +#define IR_38400 0x08 +#define IR_57600 0x10 +#define IR_115200 0x20 +#define IR_576000 0x40 +#define IR_1152000 0x80 + +/* Baud rates (second byte) */ +#define IR_4000000 0x01 + +/* Quality of Service information */ +typedef struct { + int value; + __u16 bits; /* LSB is first byte, MSB is second byte */ +} qos_value_t; + +struct qos_info { + int magic; + + qos_value_t baud_rate; /* IR_11520O | ... */ + qos_value_t max_turn_time; + qos_value_t data_size; + qos_value_t window_size; + qos_value_t additional_bofs; + qos_value_t min_turn_time; + qos_value_t link_disc_time; + + qos_value_t power; +#ifdef CONFIG_IRDA_COMPRESSION + /* An experimental non IrDA field */ + qos_value_t compression; +#endif +}; + +extern int baud_rates[]; +extern int data_size[]; +extern int min_turn_time[]; +extern int add_bofs[]; +extern int compression[]; + +void irda_init_max_qos_capabilies( struct qos_info *qos); +void irda_qos_compute_intersection( struct qos_info *, struct qos_info *); +int irda_insert_qos_negotiation_params( struct qos_info *qos, __u8 *fp); +void irda_qos_negotiate( struct qos_info *qos_rx, struct qos_info *qos_tx, + struct sk_buff *skb); + +int msb_index ( __u16 byte); +int byte_value( __u8 byte, int *array); +int value_index( int value, int *array); +int index_value( int index, int *array); + +void irda_qos_bits_to_value( struct qos_info *qos); + +#endif + + + + + diff --git a/include/net/irda/smc_ircc.h b/include/net/irda/smc_ircc.h new file mode 100644 index 000000000000..8750618a757a --- /dev/null +++ b/include/net/irda/smc_ircc.h @@ -0,0 +1,123 @@ +#if 0 +static char *rcsid = "$Id: smc_ircc.h,v 1.5 1998/07/27 01:25:29 ratbert Exp $"; +#endif + +#ifndef SMC_IRCC_H +#define SMC_IRCC_H + +#define FIR_XMIT 1 +#define FIR_RECEIVE 2 +#define SIR_XMIT 3 +#define SIR_RECEIVE 4 + +#define MASTER 0x07 +#define MASTER_POWERDOWN 1<<7 +#define MASTER_RESET 1<<6 +#define MASTER_INT_EN 1<<5 +#define MASTER_ERROR_RESET 1<<4 + +/* Register block 0 */ + +#define IIR 0x01 +#define IER 0x02 +#define LSR 0x03 +#define LCR_A 0x04 +#define LCR_B 0x05 +#define BSR 0x06 + +#define IIR_ACTIVE_FRAME 1<<7 +#define IIR_EOM 1<<6 +#define IIR_RAW_MODE 1<<5 +#define IIR_FIFO 1<<4 + +#define IER_ACTIVE_FRAME 1<<7 +#define IER_EOM 1<<6 +#define IER_RAW_MODE 1<<5 +#define IER_FIFO 1<<4 + +#define LSR_UNDER_RUN 1<<7 +#define LSR_OVER_RUN 1<<6 +#define LSR_FRAME_ERROR 1<<5 +#define LSR_SIZE_ERROR 1<<4 +#define LSR_CRC_ERROR 1<<3 +#define LSR_FRAME_ABORT 1<<2 + +#define LCR_A_FIFO_RESET 1<<7 +#define LCR_A_FAST 1<<6 +#define LCR_A_GP_DATA 1<<5 +#define LCR_A_RAW_TX 1<<4 +#define LCR_A_RAW_RX 1<<3 +#define LCR_A_ABORT 1<<2 +#define LCR_A_DATA_DONE 1<<1 + +#define LCR_B_SCE_MODE_DISABLED 0x00<<6 +#define LCR_B_SCE_MODE_TRANSMIT 0x01<<6 +#define LCR_B_SCE_MODE_RECEIVE 0x02<<6 +#define LCR_B_SCE_MODE_UNDEFINED 0x03<<6 +#define LCR_B_SIP_ENABLE 1<<5 +#define LCR_B_BRICK_WALL 1<<4 + +#define BSR_NOT_EMPTY 1<<7 +#define BSR_FIFO_FULL 1<<6 +#define BSR_TIMEOUT 1<<5 + +/* Register block 1 */ + +#define SCE_CFG_A 0x00 +#define SCE_CFG_B 0x01 +#define FIFO_THRESHOLD 0x02 + +#define CFG_A_AUX_IR 0x01<<7 +#define CFG_A_HALF_DUPLEX 0x01<<2 +#define CFG_A_TX_POLARITY 0x01<<1 +#define CFG_A_RX_POLARITY 0x01 + +#define CFG_A_COM 0x00<<3 +#define CFG_A_IRDA_SIR_A 0x01<<3 +#define CFG_A_ASK_SIR 0x02<<3 +#define CFG_A_IRDA_SIR_B 0x03<<3 +#define CFG_A_IRDA_HDLC 0x04<<3 +#define CFG_A_IRDA_4PPM 0x05<<3 +#define CFG_A_CONSUMER 0x06<<3 +#define CFG_A_RAW_IR 0x07<<3 +#define CFG_A_OTHER 0x08<<3 + +#define IR_HDLC 0x04 +#define IR_4PPM 0x01 +#define IR_CONSUMER 0x02 + +#define CFG_B_LOOPBACK 0x01<<5 +#define CFG_B_LPBCK_TX_CRC 0x01<<4 +#define CFG_B_NOWAIT 0x01<<3 +#define CFB_B_STRING_MOVE 0x01<<2 +#define CFG_B_DMA_BURST 0x01<<1 +#define CFG_B_DMA_ENABLE 0x01 + +#define CFG_B_MUX_COM 0x00<<6 +#define CFG_B_MUX_IR 0x01<<6 +#define CFG_B_MUX_AUX 0x02<<6 +#define CFG_B_INACTIVE 0x03<<6 + +/* Register block 2 - Consumer IR - not used */ + +/* Register block 3 - Identification Registers! */ + +#define SMSC_ID_HIGH 0x00 /* 0x10 */ +#define SMSC_ID_LOW 0x01 /* 0xB8 */ +#define CHIP_ID 0x02 /* 0xF1 */ +#define VERSION_NUMBER 0x03 /* 0x01 */ +#define HOST_INTERFACE 0x04 /* low 4 = DMA, high 4 = IRQ */ + +/* Register block 4 - IrDA */ +#define IR_CONTROL 0x00 +#define BOF_COUNT_LO 0x01 +#define BRICK_WALL_CNT_LO 0x02 +#define BRICK_TX_CNT_HI 0x03 +#define TX_DATA_SIZE_LO 0x04 +#define RX_DATA_SIZE_HI 0x05 +#define RX_DATA_SIZE_LO 0x06 + +#define SELECT_1152 0x01<<7 +#define CRC_SELECT 0x01<<6 + +#endif diff --git a/include/net/irda/timer.h b/include/net/irda/timer.h new file mode 100644 index 000000000000..35a5be2604af --- /dev/null +++ b/include/net/irda/timer.h @@ -0,0 +1,79 @@ +/********************************************************************* + * + * Filename: timer.h + * Version: + * Description: + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sat Aug 16 00:59:29 1997 + * Modified at: Mon Nov 2 14:31:55 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1997, 1998 Dag Brattli , + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef TIMER_H +#define TIMER_H + +#include "irda.h" +#include "irmod.h" +#include "irlap.h" +#include "irlmp.h" +#include "irda_device.h" + +/* + * Timeout definitions, some defined in IrLAP p. 92 + */ +#define POLL_TIMEOUT 45 /* Must never exceed 500 ms */ +#define FINAL_TIMEOUT 50 /* Must never exceed 500 ms */ + +/* + * Normally twice of p-timer. Note 3, IrLAP p. 60 suggests at least twice + * duration of the P-timer. + */ +#define WD_TIMEOUT POLL_TIMEOUT*2 +#define MEDIABUSY_TIMEOUT 50 /* 500 msec */ + +/* + * Slot timer must never exceed 85 ms, and must always be at least 25 ms, + * suggested to 75-85 msec by IrDA lite + */ +#define SLOT_TIMEOUT 8 +#define QUERY_TIMEOUT 100 + +#define WATCHDOG_TIMEOUT 2000 /* 20 sec */ +#define RETRY_TIMEOUT 51 + +typedef void (*TIMER_CALLBACK)( unsigned long); + +void irda_start_timer( struct timer_list *ptimer, int timeout, int data, + TIMER_CALLBACK callback); + +inline void irlap_start_slot_timer( struct irlap_cb *self, int timeout); +inline void irlap_start_query_timer( struct irlap_cb *self, int timeout); +inline void irlap_start_final_timer( struct irlap_cb *self, int timeout); +inline void irlap_start_wd_timer( struct irlap_cb *self, int timeout); +inline void irlap_start_backoff_timer( struct irlap_cb *self, int timeout); + +inline void irda_device_start_mbusy_timer( struct irda_device *self); + +struct lsap_cb; +inline void irlmp_start_watchdog_timer( struct lsap_cb *, int timeout); +inline void irlmp_start_discovery_timer( struct irlmp_cb *, int timeout); + +struct irobex_cb; +inline void irobex_start_watchdog_timer( struct irobex_cb *, int timeout); + +#endif + diff --git a/include/net/irda/w83977af.h b/include/net/irda/w83977af.h new file mode 100644 index 000000000000..dda084ab7f8c --- /dev/null +++ b/include/net/irda/w83977af.h @@ -0,0 +1,54 @@ +#ifndef W83977AF_H +#define W83977AF_H + +#define W977_EFER 0x370 +#define W977_EFIR 0x370 +#define W977_EFDR 0x371 +#define W977_DEVICE_IR 0x06 + + +/* + * Enter extended function mode + */ +static inline void w977_efm_enter(void) +{ + outb(0x87, W977_EFER); + outb(0x87, W977_EFER); +} + +/* + * Select a device to configure + */ + +static inline void w977_select_device(__u8 devnum) +{ + outb(0x07, W977_EFIR); + outb(devnum, W977_EFDR); +} + +/* + * Write a byte to a register + */ +static inline void w977_write_reg(__u8 reg, __u8 value) +{ + outb(reg, W977_EFIR); + outb(value, W977_EFDR); +} + +/* + * read a byte from a register + */ +static inline __u8 w977_read_reg(__u8 reg) +{ + outb(reg, W977_EFIR); + return inb(W977_EFDR); +} + +/* + * Exit extended function mode + */ +static inline void w977_efm_exit(void) +{ + outb(0xAA, W977_EFER); +} +#endif diff --git a/include/net/irda/w83977af_ir.h b/include/net/irda/w83977af_ir.h new file mode 100644 index 000000000000..3e3200b2de3f --- /dev/null +++ b/include/net/irda/w83977af_ir.h @@ -0,0 +1,158 @@ +/********************************************************************* + * + * Filename: w83977af_ir.h + * Version: + * Description: + * Status: Experimental. + * Author: Paul VanderSpek + * Created at: Thu Nov 19 13:55:34 1998 + * Modified at: Thu Dec 10 14:06:18 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef W83977AF_IR_H +#define W83977AF_IR_H + +#include + +/* Flags for configuration register CRF0 */ +#define ENBNKSEL 0x01 +#define APEDCRC 0x02 +#define TXW4C 0x04 +#define RXW4C 0x08 + +/* Bank 0 */ +#define RBR 0x00 /* Receiver buffer register */ +#define TBR 0x00 /* Transmitter buffer register */ + +#define ICR 0x01 /* Interrupt configuration register */ +#define ICR_ERBRI 0x01 /* Receiver buffer register interrupt */ +#define ICR_ETBREI 0x02 /* Transeiver empty interrupt */ +#define ICR_EUSRI 0x04//* IR status interrupt */ +#define ICR_EHSRI 0x04 +#define ICR_ETXURI 0x04 /* Tx underrun */ +#define ICR_EDMAI 0x10 /* DMA interrupt */ +#define ICR_ETXTHI 0x20 /* Transmitter threshold interrupt */ +#define ICR_EFSFI 0x40 /* Frame status FIFO interrupt */ +#define ICR_ETMRI 0x80 /* Timer interrupt */ + +#define UFR 0x02 /* FIFO control register */ +#define UFR_EN_FIFO 0x01 /* Enable FIFO's */ +#define UFR_RXF_RST 0x02 /* Reset Rx FIFO */ +#define UFR_TXF_RST 0x04 /* Reset Tx FIFO */ +#define UFR_RXTL 0x80 /* Rx FIFO threshold (set to 16) */ +#define UFR_TXTL 0x20 /* Tx FIFO threshold (set to 17) */ + +#define ISR 0x02 /* Interrupt status register */ +#define ISR_RXTH_I 0x01 /* Receive threshold interrupt */ +#define ISR_TXEMP_I 0x02 /* Transmitter empty interrupt */ +#define ISR_FEND_I 0x04 +#define ISR_DMA_I 0x10 +#define ISR_TXTH_I 0x20 /* Transmitter threshold interrupt */ +#define ISR_FSF_I 0x40 +#define ISR_TMR_I 0x80 /* Timer interrupt */ + +#define UCR 0x03 /* Uart control register */ +#define UCR_DLS8 0x03 /* 8N1 */ + +#define SSR 0x03 /* Sets select register */ +#define SET0 UCR_DLS8 /* Make sure we keep 8N1 */ +#define SET1 (0x80|UCR_DLS8) /* Make sure we keep 8N1 */ +#define SET2 0xE0 +#define SET3 0xE4 +#define SET4 0xE8 +#define SET5 0xEC +#define SET6 0xF0 +#define SET7 0xF4 + +#define HCR 0x04 +#define HCR_MODE_MASK ~(0xD0) +#define HCR_SIR 0x60 +#define HCR_MIR_576 0x20 +#define HCR_MIR_1152 0x80 +#define HCR_FIR 0xA0 +#define HCR_EN_DMA 0x04 +#define HCR_EN_IRQ 0x08 +#define HCR_TX_WT 0x08 + +#define USR 0x05 /* IR status register */ +#define USR_RDR 0x01 /* Receive data ready */ +#define USR_TSRE 0x40 /* Transmitter empty? */ + +#define AUDR 0x07 +#define AUDR_SFEND 0x08 /* Set a frame end */ +#define AUDR_RXBSY 0x20 /* Rx busy */ +#define AUDR_UNDR 0x40 /* Transeiver underrun */ + +/* Set 2 */ +#define ABLL 0x00 /* Advanced baud rate divisor latch (low byte) */ +#define ABHL 0x01 /* Advanced baud rate divisor latch (high byte) */ + +#define ADCR1 0x02 +#define ADCR1_ADV_SL 0x01 +#define ADCR1_D_CHSW 0x08 /* the specs are wrong. its bit 3, not 4 */ +#define ADCR1_DMA_F 0x02 + +#define ADCR2 0x04 +#define ADCR2_TXFS32 0x01 +#define ADCR2_RXFS32 0x04 + +#define RXFDTH 0x07 + +/* Set 3 */ +#define AUID 0x00 + +/* Set 4 */ +#define TMRL 0x00 /* Timer value register (low byte) */ +#define TMRH 0x01 /* Timer value register (high byte) */ + +#define IR_MSL 0x02 /* Infrared mode select */ +#define IR_MSL_EN_TMR 0x01 /* Enable timer */ + +#define TFRLL 0x04 /* Transmitter frame length (low byte) */ +#define TFRLH 0x05 /* Transmitter frame length (high byte) */ +#define RFRLL 0x06 /* Receiver frame length (low byte) */ +#define RFRLH 0x07 /* Receiver frame length (high byte) */ + +/* Set 5 */ + +#define FS_FO 0x05 /* Frame status FIFO */ +#define FS_FO_FSFDR 0x80 /* Frame status FIFO data ready */ +#define FS_FO_LST_FR 0x40 /* Frame lost */ +#define FS_FO_MX_LEX 0x10 /* Max frame len exceeded */ +#define FS_FO_PHY_ERR 0x08 /* Physical layer error */ +#define FS_FO_CRC_ERR 0x04 +#define FS_FO_RX_OV 0x02 /* Receive overrun */ +#define FS_FO_FSF_OV 0x01 /* Frame status FIFO overrun */ +#define FS_FO_ERR_MSK 0x5f /* Error mask */ + +#define RFLFL 0x06 +#define RFLFH 0x07 + +/* Set 6 */ +#define IR_CFG2 0x00 +#define IR_CFG2_DIS_CRC 0x02 + +/* Set 7 */ +#define IRM_CR 0x07 /* Infrared module control register */ +#define IRM_CR_IRX_MSL 0x40 +#define IRM_CR_AF_MNT 0x80 /* Automatic format */ + +static inline void switch_bank( int iobase, int set) +{ + outb( set, iobase+SSR); +} + +#endif diff --git a/include/net/irda/wrapper.h b/include/net/irda/wrapper.h new file mode 100644 index 000000000000..838713f31fbc --- /dev/null +++ b/include/net/irda/wrapper.h @@ -0,0 +1,57 @@ +/********************************************************************* + * + * Filename: wrapper.h + * Version: + * Description: IrDA Wrapper layer + * Status: Experimental. + * Author: Dag Brattli + * Created at: Mon Aug 4 20:40:53 1997 + * Modified at: Thu Nov 19 13:17:56 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#ifndef WRAPPER_H +#define WRAPPER_H + +#include +#include + +#include "irda_device.h" + +#define BOF 0xc0 /* Beginning of frame */ +#define XBOF 0xff +#define EOF 0xc1 /* End of frame */ +#define CE 0x7d /* Control escape */ + +#define STA BOF /* Start flag */ +#define STO EOF /* End flag */ + +#define IR_TRANS 0x20 /* Asynchronous transparency modifier */ + +#define SOP BOF /* Start of */ +#define EOP EOF /* End of */ + +enum { + OUTSIDE_FRAME = 1, + BEGIN_FRAME, + LINK_ESCAPE, + INSIDE_FRAME +}; + +/* Proto definitions */ +int async_wrap_skb( struct sk_buff *skb, __u8 *tx_buff, int buffsize); +void async_unwrap_char( struct irda_device *, __u8 byte); + +#endif diff --git a/net/Makefile b/net/Makefile index 0bbf171fa661..9131266d122c 100644 --- a/net/Makefile +++ b/net/Makefile @@ -10,7 +10,7 @@ MOD_SUB_DIRS := ipv4 ALL_SUB_DIRS := 802 ax25 bridge core ethernet ipv4 ipv6 ipx unix appletalk \ netrom rose lapb x25 wanrouter netlink sched packet sunrpc \ - econet #decnet + econet irda #decnet SUB_DIRS := core ethernet sched MOD_LIST_NAME := NET_MISC_MODULES @@ -125,6 +125,14 @@ else endif endif +ifeq ($(CONFIG_IRDA),y) +SUB_DIRS += irda +else + ifeq ($(CONFIG_IRDA),m) + MOD_SUB_DIRS += irda + endif +endif + ifeq ($(CONFIG_SUNRPC),y) SUB_DIRS += sunrpc else @@ -168,7 +176,9 @@ L_OBJS := $(SOCK) protocols.o $(join $(SUB_DIRS),$(SUB_DIRS:%=/%.o)) M_OBJS := ifeq ($(CONFIG_SYSCTL),y) +ifeq ($(CONFIG_NET),y) L_OBJS += sysctl_net.o endif +endif include $(TOPDIR)/Rules.make diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index c79fc6874e9e..c47f83263492 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -912,7 +912,7 @@ int atif_ioctl(int cmd, void *arg) break; case SIOCSARP: - if(!suser()) + if(!capable(CAP_NET_ADMIN)) return (-EPERM); if(sa->sat_family != AF_APPLETALK) return (-EINVAL); @@ -961,7 +961,7 @@ int atif_ioctl(int cmd, void *arg) break; case SIOCDARP: - if(!suser()) + if(!capable(CAP_NET_ADMIN)) return (-EPERM); if(sa->sat_family != AF_APPLETALK) return (-EINVAL); diff --git a/net/bridge/br.c b/net/bridge/br.c index 014453f8cec8..b648ec4a8624 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c @@ -50,6 +50,7 @@ * */ +#include #include #include #include @@ -71,6 +72,7 @@ #include #include #include +#include #ifndef min #define min(a, b) (((a) <= (b)) ? (a) : (b)) @@ -802,6 +804,40 @@ static void hold_timer_expiry(int port_no) /* (4.7.8) */ } /* (4.6.1.2.3) */ } +/* Vova Oksman: Write the buffer (contents of the Bridge table) */ +/* to a PROCfs file */ +int br_tree_get_info(char *buffer, char **start, off_t offset, int length, int dummy) +{ + int size; + int len=0; + off_t pos=0; + char* pbuffer; + + if(0==offset) + { + /* first time write the header */ + size = sprintf(buffer,"%s","MAC address Device Flags Age (sec.)\n"); + len=size; + } + + pbuffer=&buffer[len]; + sprintf_avl(&pbuffer,NULL,&pos,&len,offset,length); + + *start = buffer+len-(pos-offset); /* Start of wanted data */ + len = pos-offset; /* Start slop */ + if (len>length) + len = length; /* Ending slop */ + + return len; +} +#ifdef CONFIG_PROC_FS +struct proc_dir_entry proc_net_bridge= { + PROC_NET_BRIDGE, 6, "bridge", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_net_inode_operations, + br_tree_get_info +}; +#endif __initfunc(void br_init(void)) { /* (4.8.1) */ int port_no; @@ -857,6 +893,10 @@ __initfunc(void br_init(void)) br_stats.policy = BR_ACCEPT; /* Enable bridge to accpet all protocols */ br_stats.exempt_protocols = 0; /*start_hello_timer();*/ + /* Vova Oksman: register the function for the PROCfs "bridge" file */ +#ifdef CONFIG_PROC_FS + proc_net_register(&proc_net_bridge); +#endif } static inline unsigned short make_port_id(int port_no) diff --git a/net/bridge/br_tree.c b/net/bridge/br_tree.c index 709bafb2b511..31387f13c464 100644 --- a/net/bridge/br_tree.c +++ b/net/bridge/br_tree.c @@ -426,3 +426,46 @@ static int addr_cmp(unsigned char a1[], unsigned char a2[]) return(0); } +/* Vova Oksman: function for copy tree to the buffer */ +void sprintf_avl (char **pbuffer, struct fdb * tree, off_t *pos, + int* len, off_t offset, int length) +{ + int size; + + if( 0 == *pos){ + if(avl_br_empty == tree) + /* begin from the root */ + tree = fhp; + *pos = *len; + } + + if (*pos >= offset+length) + return; + + if (tree != avl_br_empty) { + /* don't write the local device */ + if(tree->port != 0){ + size = sprintf(*pbuffer, + "%02x:%02x:%02x:%02x:%02x:%02x eth%d %d %d\n", + tree->ula[0],tree->ula[1],tree->ula[2], + tree->ula[3],tree->ula[4],tree->ula[5], + tree->port-1, tree->flags,CURRENT_TIME-tree->timer); + + (*pos)+=size; + (*len)+=size; + (*pbuffer)+=size; + } + if (*pos <= offset) + *len=0; + + if (tree->fdb_avl_left != avl_br_empty) { + sprintf_avl (pbuffer,tree->fdb_avl_left,pos,len,offset,length); + } + if (tree->fdb_avl_right != avl_br_empty) { + sprintf_avl (pbuffer,tree->fdb_avl_right,pos,len,offset,length); + } + + } + + return; +} diff --git a/net/decnet/README b/net/decnet/README index 54190782fdcc..c62e293238b9 100644 --- a/net/decnet/README +++ b/net/decnet/README @@ -4,10 +4,9 @@ For information on the Linux DECnet Project and the latest progress, look at the project home page: -http://eeshack3.swan.ac.uk/~gw7rrm/DECnet/index.html +http://www-sigproc.eng.cam.ac.uk/~sjw44/ To contribute either mail or post on one of the Linux mailing lists (either linux-net or netdev). Steve Whitehouse -http://eeshack3.swan.ac.uk/~gw7rrm diff --git a/net/irda/Config.in b/net/irda/Config.in new file mode 100644 index 000000000000..fd406fdee4f1 --- /dev/null +++ b/net/irda/Config.in @@ -0,0 +1,35 @@ +# +# IrDA protocol configuration +# + +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + if [ "$CONFIG_NET" != "n" ] ; then + + mainmenu_option next_comment + comment 'IrDA subsystem support' + dep_tristate 'IrDA subsystem support' CONFIG_IRDA $CONFIG_EXPERIMENTAL $CONFIG_NET + + if [ "$CONFIG_IRDA" != "n" ] ; then + comment 'IrDA protocols' + source net/irda/irlan/Config.in + source net/irda/irobex/Config.in + source net/irda/ircomm/Config.in + + bool 'IrDA protocol options' CONFIG_IRDA_OPTIONS + if [ "$CONFIG_IRDA_OPTIONS" != "n" ] ; then + comment ' IrDA options' + bool ' Cache last LSAP' CONFIG_IRDA_CACHE_LAST_LSAP + bool ' Fast RRs' CONFIG_IRDA_FAST_RR + bool ' Recycle RRs' CONFIG_IRDA_RECYCLE_RR + fi + fi + + if [ "$CONFIG_IRDA" != "n" ] ; then + source net/irda/compressors/Config.in + source drivers/net/irda/Config.in + fi + endmenu + + fi +fi + diff --git a/net/irda/Makefile b/net/irda/Makefile new file mode 100644 index 000000000000..8d350ba02849 --- /dev/null +++ b/net/irda/Makefile @@ -0,0 +1,80 @@ +# +# Makefile for the Linux IrDA protocol layer. +# +# 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 definition is now in the main makefile... + +ALL_SUB_DIRS := irlan ircomm compressors +SUB_DIRS := +MOD_SUB_DIRS := + +O_TARGET := irda.o +O_OBJS := irmod.o iriap.o iriap_event.o irlmp.o irlmp_event.o irlmp_frame.o \ + irlap.o irlap_event.o irlap_frame.o timer.o qos.o irqueue.o \ + irttp.o irda_device.o irias_object.o crc.o wrapper.o af_irda.o +MOD_LIST_NAME := IRDA_MODULES +M_OBJS := $(O_TARGET) + +ifeq ($(CONFIG_IRDA_COMPRESSION),y) +O_OBJS += irlap_comp.o +endif + +ifeq ($(CONFIG_PROC_FS),y) +O_OBJS += irproc.o +endif + +ifeq ($(CONFIG_SYSCTL),y) +O_OBJS += irsysctl.o +endif + +ifeq ($(CONFIG_IRLAN),y) +SUB_DIRS += irlan +O_OBJS += irlan/irlan.o +else + ifeq ($(CONFIG_IRLAN),m) + MOD_SUB_DIRS += irlan + endif +endif + +ifeq ($(CONFIG_IROBEX),y) +SUB_DIRS += irobex +O_OBJS += irobex/irobex.o +else + ifeq ($(CONFIG_IROBEX),m) + MOD_SUB_DIRS += irobex + endif +endif + +ifeq ($(CONFIG_IRDA_COMPRESSION),y) +SUB_DIRS += compressors +MOD_IN_SUB_DIRS += compressors +endif + +ifeq ($(CONFIG_IRDA_DEFLATE),y) +O_OBJS += compressors/irda_deflate.o +else + ifeq ($(CONFIG_IRDA_DEFLATE),m) + MOD_TO_LIST += irda_deflate.o + endif +endif + +ifeq ($(CONFIG_IRCOMM),y) +SUB_DIRS += ircomm +O_OBJS += ircomm/ircomm_n_vtd.o +else + ifeq ($(CONFIG_IRCOMM),m) + MOD_SUB_DIRS += ircomm + endif +endif + +include $(TOPDIR)/Rules.make + +tar: + tar -cvf /dev/f1 . + + + + diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c new file mode 100644 index 000000000000..003dc75b840a --- /dev/null +++ b/net/irda/af_irda.c @@ -0,0 +1,738 @@ +/********************************************************************* + * + * Filename: af_irda.c + * Version: 0.1 + * Description: IrDA sockets implementation + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sun May 31 10:12:43 1998 + * Modified at: Mon Dec 14 10:39:45 1998 + * Modified by: Dag Brattli + * Sources: af_netroom.c, af_ax25.x + * + * Copyright (c) 1997 Dag Brattli, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include +#include + +extern int irda_init(void); +extern void irda_cleanup(void); +extern int irlap_input(struct sk_buff *, struct device *, struct packet_type *); + +#define IRDA_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER) + +#ifdef IRDA_SOCKETS + +/* + * Function irda_getname (sock, uaddr, uaddr_len, peer) + * + * + * + */ +static int irda_getname( struct socket *sock, struct sockaddr *uaddr, + int *uaddr_len, int peer) +{ + DEBUG( 0, __FUNCTION__ "(), Not implemented!\n"); + + return 0; +} + +/* + * Function irda_sendmsg (sock, msg, len, noblock, flags) + * + * + * + */ +static int irda_sendmsg( struct socket *sock, struct msghdr *msg, int len, + int noblock, int flags) +{ +#if 0 + struct sock *sk = (struct sock *) sock->data; + /* struct sockaddr_irda *usax = (struct sockaddr_irda *)msg->msg_name; */ + int err; + struct sk_buff *skb; + unsigned char *asmptr; + int size; + struct tsap_cb *tsap; + + DEBUG( 0, __FUNCTION__ "()\n"); + + if (sk->err) + return sock_error(sk); + + if (flags) + return -EINVAL; + + if (sk->zapped) + return -EADDRNOTAVAIL; + + if (sk->debug) + printk( "IrDA: sendto: Addresses built.\n"); + + /* Build a packet */ + if (sk->debug) + printk( "IrDA: sendto: building packet.\n"); + + size = len + IRDA_MAX_HEADER; + + if ((skb = sock_alloc_send_skb(sk, size, 0, 0, &err)) == NULL) + return err; + + skb->sk = sk; + skb->free = 1; + skb->arp = 1; + + skb_reserve(skb, size - len); + + memcpy_fromiovec( asmptr, msg->msg_iov, len); + + if (sk->debug) + printk( "IrDA: Transmitting buffer\n"); + + if (sk->state != TCP_ESTABLISHED) { + kfree_skb( skb, FREE_WRITE); + return -ENOTCONN; + } + + tsap = (struct tsap_cb *) sk->protinfo.irda; + ASSERT( tsap != NULL, return -ENODEV;); + ASSERT( tsap->magic == TTP_TSAP_MAGIC, return -EBADR;); + + irttp_data_request( tsap, skb); +#endif + return len; +} + +/* + * Function irda_recvmsg (sock, msg, size, noblock, flags, addr_len) + * + * + * + */ +static int irda_recvmsg( struct socket *sock, struct msghdr *msg, int size, + int noblock, int flags, int *addr_len) +{ + int copied=0; +#if 0 + struct sock *sk = (struct sock *)sock->data; + struct sockaddr_irda *sax = (struct sockaddr_irda *)msg->msg_name; + struct sk_buff *skb; + int er; + + DEBUG( 0, __FUNCTION__ "()\n"); + + if (sk->err) + return sock_error(sk); + + if (addr_len != NULL) + *addr_len = sizeof(*sax); + + /* + * This works for seqpacket too. The receiver has ordered the queue for + * us! We do one quick check first though + */ + if (sk->state != TCP_ESTABLISHED) + return -ENOTCONN; + + /* Now we can treat all alike */ + if ((skb = skb_recv_datagram( sk, flags, noblock, &er)) == NULL) + return er; + +/* if (!sk->nr->hdrincl) { */ +/* skb_pull(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN); */ +/* skb->h.raw = skb->data; */ +/* } */ + + copied = (size < skb->len) ? size : skb->len; + skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); + + skb_free_datagram(sk, skb); +#endif + return copied; +} + +/* + * Function irda_listen (sock, backlog) + * + * + * + */ +static int irda_listen( struct socket *sock, int backlog) +{ +#if 0 + struct sock *sk = (struct sock *)sock->data; + + if (sk->state != TCP_LISTEN) { + sk->max_ack_backlog = backlog; + sk->state = TCP_LISTEN; + return 0; + } +#endif + return -EOPNOTSUPP; +} + +/* + * Function irda_bind (sock, uaddr, addr_len) + * + * Bind to a specified TSAP + * + */ +static int irda_bind( struct socket *sock, struct sockaddr *uaddr, + int addr_len) +{ +#if 0 + struct sock *sk; + struct full_sockaddr_irda *addr = (struct full_sockaddr_irda *)uaddr; + struct device *dev; + irda_address *user, *source; + struct tsap_cb *tsap; + struct notify_t notify; + + DEBUG( 0, __FUNCTION__ "()\n"); + + sk = (struct sock *) sock->data; + + if ( sk->zapped == 0) + return -EIO; + + irda_notify_init( ¬ify); + tsap = irttp_open_tsap( LSAP_ANY, DEFAULT_INITIAL_CREDIT, ¬ify); + + sk->zapped = 0; + + if (sk->debug) + printk("IrDA: socket is bound\n"); +#endif + return 0; +} + +/* + * Function irda_connect (sock, uaddr, addr_len, flags) + * + * Connect to a IrDA device + * + */ +static int irda_connect( struct socket *sock, struct sockaddr *uaddr, + int addr_len, int flags) +{ +#if 0 + struct sock *sk = (struct sock *)sock->data; + struct sockaddr_irda *addr = (struct sockaddr_irda *)uaddr; + irda_address *user, *source = NULL; + struct device *dev; + + DEBUG( 0, __FUNCTION__ "()\n"); + + if (sk->state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { + sock->state = SS_CONNECTED; + return 0; /* Connect completed during a ERESTARTSYS event */ + } + + if (sk->state == TCP_CLOSE && sock->state == SS_CONNECTING) { + sock->state = SS_UNCONNECTED; + return -ECONNREFUSED; + } + + if (sk->state == TCP_ESTABLISHED) + return -EISCONN; /* No reconnect on a seqpacket socket */ + + sk->state = TCP_CLOSE; + sock->state = SS_UNCONNECTED; + + if (addr_len != sizeof(struct sockaddr_irda)) + return -EINVAL; + + + /* Now the loop */ + if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) + return -EINPROGRESS; + + cli(); /* To avoid races on the sleep */ + + /* A Connect Ack with Choke or timeout or failed routing will go to + * closed. */ + while ( sk->state == TCP_SYN_SENT) { + interruptible_sleep_on( sk->sleep); + if (current->signal & ~current->blocked) { + sti(); + return -ERESTARTSYS; + } + } + + if (sk->state != TCP_ESTABLISHED) { + sti(); + sock->state = SS_UNCONNECTED; + return sock_error( sk); /* Always set at this point */ + } + + sock->state = SS_CONNECTED; + + sti(); +#endif + return 0; +} + +static int irda_socketpair( struct socket *sock1, struct socket *sock2) +{ + DEBUG( 0, __FUNCTION__ "(), Not implemented\n"); + + return -EOPNOTSUPP; +} + +static int irda_accept(struct socket *sock, struct socket *newsock, int flags) +{ + struct sock *sk; + struct sock *newsk; + struct sk_buff *skb; + + DEBUG( 0, __FUNCTION__ "()\n"); +#if 0 + if (newsock->data) + sk_free(newsock->data); + + newsock->data = NULL; + + sk = (struct sock *)sock->data; + + if (sk->type != SOCK_SEQPACKET) + return -EOPNOTSUPP; + + if (sk->state != TCP_LISTEN) + return -EINVAL; + + /* + * The write queue this time is holding sockets ready to use + * hooked into the SABM we saved + */ + do { + cli(); + if ((skb = skb_dequeue(&sk->receive_queue)) == NULL) { + if (flags & O_NONBLOCK) { + sti(); + return 0; + } + interruptible_sleep_on(sk->sleep); + if (current->signal & ~current->blocked) { + sti(); + return -ERESTARTSYS; + } + } + } while (skb == NULL); + + newsk = skb->sk; + newsk->pair = NULL; + sti(); + + /* Now attach up the new socket */ + skb->sk = NULL; + kfree_skb(skb, FREE_READ); + sk->ack_backlog--; + newsock->data = newsk; +#endif + return 0; +} + +static void def_callback1(struct sock *sk) +{ + DEBUG( 0, __FUNCTION__ "()\n"); + + if (!sk->dead) + wake_up_interruptible(sk->sleep); +} + +static void def_callback2(struct sock *sk, int len) +{ + DEBUG( 0, __FUNCTION__ "()\n"); + + if (!sk->dead) + wake_up_interruptible(sk->sleep); +} + + +/* + * Function irda_create (sock, protocol) + * + * Create IrDA socket + * + */ +static int irda_create( struct socket *sock, int protocol) +{ + struct sock *sk; + + DEBUG( 0, __FUNCTION__ "()\n"); +#if 0 + if (sock->type != SOCK_SEQPACKET || protocol != 0) + return -ESOCKTNOSUPPORT; + + /* Allocate socket */ + if ((sk = sk_alloc( GFP_ATOMIC)) == NULL) + return -ENOMEM; + + skb_queue_head_init(&sk->receive_queue); + skb_queue_head_init(&sk->write_queue); + skb_queue_head_init(&sk->back_log); + + init_timer( &sk->timer); + + sk->socket = sock; + sk->type = sock->type; + sk->protocol = protocol; + sk->allocation = GFP_KERNEL; + sk->rcvbuf = SK_RMEM_MAX; + sk->sndbuf = SK_WMEM_MAX; + sk->state = TCP_CLOSE; + sk->priority = SOPRI_NORMAL; + sk->mtu = 2048; /* FIXME, insert the right size*/ + sk->zapped = 1; +/* sk->window = nr_default.window; */ + + sk->state_change = def_callback1; + sk->data_ready = def_callback2; + sk->write_space = def_callback1; + sk->error_report = def_callback1; + + if (sock != NULL) { + sock->data = (void *)sk; + sk->sleep = sock->wait; + } +#endif + return 0; +} + +/* + * Function irda_destroy_socket (tsap) + * + * Destroy socket + * + */ +void irda_destroy_socket(struct tsap_cb *tsap) +{ + DEBUG( 0, __FUNCTION__ "()\n"); + + return; +} + +/* + * Function irda_release (sock, peer) + * + * + * + */ +static int irda_release( struct socket *sock, struct socket *peer) +{ +#if 0 + struct sock *sk = (struct sock *)sock->data; + + DEBUG( 0, __FUNCTION__ "()\n"); + + + if (sk == NULL) return 0; + + if (sk->type == SOCK_SEQPACKET) { + + + } else { + sk->state = TCP_CLOSE; + sk->shutdown |= SEND_SHUTDOWN; + sk->state_change(sk); + sk->dead = 1; + irda_destroy_socket( sk->protinfo.irda); + } + + sock->data = NULL; + sk->socket = NULL; /* Not used, but we should do this. **/ +#endif + return 0; +} + + +/* + * Function irda_dup (newsock, oldsock) + * + * + * + */ +static int irda_dup( struct socket *newsock, struct socket *oldsock) +{ +#if 0 + struct sock *sk = (struct sock *)oldsock->data; + + DEBUG( 0, __FUNCTION__ "()\n"); + + if (sk == NULL || newsock == NULL) + return -EINVAL; + + return irda_create( newsock, sk->protocol); +#endif + return 0; +} + +static int irda_shutdown( struct socket *sk, int how) +{ + DEBUG( 0, __FUNCTION__ "()\n"); + + /* FIXME - generate DM and RNR states */ + return -EOPNOTSUPP; +} + + +unsigned int irda_poll( struct file *file, struct socket *sock, + struct poll_table_struct *wait) +{ + +} + +/* + * Function irda_ioctl (sock, cmd, arg) + * + * + * + */ +static int irda_ioctl( struct socket *sock, unsigned int cmd, + unsigned long arg) +{ +#if 0 + struct sock *sk = (struct sock *) sock->data; + int err; + + DEBUG( 0, __FUNCTION__ "(), Not implemented!\n"); +#endif + return 0; +} + +static int irda_setsockopt( struct socket *sock, int level, int optname, + char *optval, int optlen) +{ +#if 0 + struct sock *sk = (struct sock *)sock->data; + int err, opt; + + DEBUG( 0, __FUNCTION__ "()\n"); + + if (level == SOL_SOCKET) + return sock_setsockopt(sk, level, optname, optval, optlen); + + /* if (level != SOL_AX25) */ +/* return -EOPNOTSUPP; */ + + if (optval == NULL) + return -EINVAL; + + if ((err = verify_area(VERIFY_READ, optval, sizeof(int))) != 0) + return err; + + opt = get_fs_long((int *)optval); + + switch (optname) { + default: + return -ENOPROTOOPT; + } +#endif + return -ENOPROTOOPT; +} + +static int irda_getsockopt(struct socket *sock, int level, int optname, + char *optval, int *optlen) +{ +#if 0 + struct sock *sk = (struct sock *)sock->data; + int val = 0; + int err; + + DEBUG( 0, __FUNCTION__ "()\n"); + + if (level == SOL_SOCKET) + return sock_getsockopt(sk, level, optname, optval, optlen); + + /* if (level != SOL_AX25) */ +/* return -EOPNOTSUPP; */ + + switch (optname) { + default: + return -ENOPROTOOPT; + } + + if ((err = verify_area(VERIFY_WRITE, optlen, sizeof(int))) != 0) + return err; + + put_user(sizeof(int), optlen); + + if ((err = verify_area(VERIFY_WRITE, optval, sizeof(int))) != 0) + return err; + + put_user(val, (int *)optval); +#endif + return 0; +} + +static int irda_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg) +{ + DEBUG( 0, __FUNCTION__ "()\n"); + + return -EINVAL; +} +/* + * Function irda_rcv (skb, dev, dev_addr, ptype) + * + * + * + */ +static int irda_rcv( struct sk_buff *skb, struct device *dev, + irda_address *dev_addr, struct packet_type *ptype) +{ + DEBUG( 0, __FUNCTION__ "()\n"); + + return 0; +} + +/* + * Function irda_driver_rcv (skb, dev, ptype) + * + * + * + */ +static int irda_driver_rcv( struct sk_buff *skb, struct device *dev, + struct packet_type *ptype) +{ + skb->sk = NULL; /* Initially we don't know who it's for */ + + DEBUG( 0, __FUNCTION__ "()\n"); + +#if 0 + if ((*skb->data & 0x0F) != 0) { + kfree_skb(skb, FREE_READ); /* Not a KISS data frame */ + return 0; + } + + /* skb_pull(skb, AX25_KISS_HEADER_LEN); */ /* Remove the KISS byte */ + + return irda_rcv( skb, dev, (irda_address *)dev->dev_addr, ptype); +#endif + return NULL; +} + +static struct proto_ops irda_proto_ops = { + AF_IRDA, + + irda_create, + irda_dup, + irda_release, + irda_bind, + irda_connect, + irda_socketpair, + irda_accept, + irda_getname, + irda_poll, + irda_ioctl, + irda_listen, + irda_shutdown, + irda_setsockopt, + irda_getsockopt, + irda_fcntl, + irda_sendmsg, + irda_recvmsg +}; + +#endif /* IRDA_SOCKETS */ + +static int irda_device_event( struct notifier_block *this, unsigned long event, + void *ptr) +{ + /* struct device *dev = (struct device *) ptr; */ + + DEBUG( 0, __FUNCTION__ "()\n"); + + /* Reject non AX.25 devices */ + /* if (dev->type != ARPHRD_AX25) */ +/* return NOTIFY_DONE; */ + + switch (event) { + case NETDEV_UP: + /* ax25_dev_device_up(dev); */ + break; + case NETDEV_DOWN: + /* ax25_kill_by_device(dev); */ +/* ax25_rt_device_down(dev); */ +/* ax25_dev_device_down(dev); */ + break; + default: + break; + } + + return NOTIFY_DONE; +} + +static struct packet_type irda_packet_type = +{ + 0, /* MUTTER ntohs(ETH_P_IRDA),*/ + NULL, + irlap_input, /* irda_driver_rcv, */ + NULL, + NULL, +}; + +static struct notifier_block irda_dev_notifier = { + irda_device_event, + NULL, + 0 +}; + +/* + * Function irda_proto_init (pro) + * + * Initialize IrDA protocol layer + * + */ +void irda_proto_init(struct net_proto *pro) +{ + DEBUG( 0, __FUNCTION__ "\n"); + + /* sock_register( irda_proto_ops.family, &irda_proto_ops); */ + irda_packet_type.type = htons(ETH_P_IRDA); + dev_add_pack(&irda_packet_type); + + /* register_netdevice_notifier( &irda_dev_notifier); */ + + /* printk( KERN_INFO "IrDA Sockets for Linux (Dag Brattli)\n"); */ + irda_init(); +} + +/* + * Function irda_proto_cleanup (void) + * + * Remove IrDA protocol layer + * + */ +void irda_proto_cleanup(void) +{ + DEBUG( 0, __FUNCTION__ "\n"); + + irda_packet_type.type = htons(ETH_P_IRDA); + dev_remove_pack(&irda_packet_type); + + /* unregister_netdevice_notifier( &irda_dev_notifier); */ + + /* (void) sock_unregister( irda_proto_ops.family); */ + irda_cleanup(); + + return; +} + diff --git a/net/irda/compressors/Config.in b/net/irda/compressors/Config.in new file mode 100644 index 000000000000..61500751b23e --- /dev/null +++ b/net/irda/compressors/Config.in @@ -0,0 +1,9 @@ + +bool 'IrLAP compression' CONFIG_IRDA_COMPRESSION + +if [ "$CONFIG_IRDA_COMPRESSION" != "n" ] ; then + comment ' IrDA compressors' + dep_tristate ' Deflate compression (experimental)' CONFIG_IRDA_DEFLATE $CONFIG_IRDA +# tristate ' BZIP2 compression' CONFIG_IRDA_BZIP2 +# tristate ' BSD compression' CONFIG_IRDA_BSD +fi diff --git a/net/irda/compressors/Makefile b/net/irda/compressors/Makefile new file mode 100644 index 000000000000..b7992289a835 --- /dev/null +++ b/net/irda/compressors/Makefile @@ -0,0 +1,26 @@ +# +# Makefile for the Linux IRDA compression protocols +# +# 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 definition is now in the main makefile... + +O_TARGET := +O_OBJS := +MOD_LIST_NAME := IRDA_MODULES +M_OBJS := + +ifeq ($(CONFIG_IRDA_DEFLATE),y) +O_OBJS += irda_deflate.o +else + ifeq ($(CONFIG_IRDA_DEFLATE),m) + M_OBJS += irda_deflate.o + endif +endif + +include $(TOPDIR)/Rules.make + +tar: + tar -cvf /dev/f1 . diff --git a/net/irda/compressors/irda_deflate.c b/net/irda/compressors/irda_deflate.c new file mode 100644 index 000000000000..f258a356608a --- /dev/null +++ b/net/irda/compressors/irda_deflate.c @@ -0,0 +1,636 @@ +/********************************************************************* + * + * Filename: irda_deflate.c + * Version: + * Description: + * Status: Experimental. + * Author: Dag Brattli + * Created at: Fri Oct 9 02:52:08 1998 + * Modified at: Mon Dec 14 19:48:54 1998 + * Modified by: Dag Brattli + * + * ==FILEVERSION 980319== + * + * irda_deflate.c - interface the zlib procedures for Deflate compression + * and decompression (as used by gzip) to the IrDA code. + * This version is for use with Linux kernel 2.1.X. + * + * Copyright (c) 1994 The Australian National University. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. The Australian National University + * makes no representations about the suitability of this software for + * any purpose. + * + * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY + * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO + * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, + * OR MODIFICATIONS. + * + * From: deflate.c,v 1.1 1996/01/18 03:17:48 paulus Exp + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* to get the struct task_struct */ +#include /* used in new tty drivers */ +#include /* used in new tty drivers */ + +#include + +#include +#include +#include +#include + +#include +#include + +/* + * This is not that nice, but what can we do when the code has been placed + * elsewhere + */ + +#include "../../../drivers/net/zlib.c" + +/* + * State for a Deflate (de)compressor. + */ +struct irda_deflate_state { + int seqno; + int w_size; + int unit; + int mru; + int debug; + z_stream strm; + struct compstat stats; +}; + +#define DEFLATE_OVHD 2 /* Deflate overhead/packet */ + +static void *zalloc __P((void *, unsigned int items, unsigned int size)); +static void *zalloc_init __P((void *, unsigned int items, + unsigned int size)); +static void zfree __P((void *, void *ptr)); +static void *z_comp_alloc __P((unsigned char *options, int opt_len)); +static void *z_decomp_alloc __P((unsigned char *options, int opt_len)); +static void z_comp_free __P((void *state)); +static void z_decomp_free __P((void *state)); +static int z_comp_init __P((void *state, unsigned char *options, + int opt_len, + int unit, int hdrlen, int debug)); +static int z_decomp_init __P((void *state, unsigned char *options, + int opt_len, + int unit, int hdrlen, int mru, int debug)); +static int z_compress __P((void *state, unsigned char *rptr, + unsigned char *obuf, + int isize, int osize)); +static void z_incomp __P((void *state, unsigned char *ibuf, int icnt)); +static int z_decompress __P((void *state, unsigned char *ibuf, + int isize, unsigned char *obuf, int osize)); +static void z_comp_reset __P((void *state)); +static void z_decomp_reset __P((void *state)); +static void z_comp_stats __P((void *state, struct compstat *stats)); + +struct chunk_header { + int valloced; /* allocated with valloc, not kmalloc */ + int guard; /* check for overwritten header */ +}; + +#define GUARD_MAGIC 0x77a8011a +#define MIN_VMALLOC 2048 /* use kmalloc for blocks < this */ + +/* + * Space allocation and freeing routines for use by zlib routines. + */ +void zfree(void *arg, void *ptr) +{ + struct chunk_header *hdr = ((struct chunk_header *)ptr) - 1; + + if (hdr->guard != GUARD_MAGIC) { + printk(KERN_WARNING "zfree: header corrupted (%x %x) at %p\n", + hdr->valloced, hdr->guard, hdr); + return; + } + if (hdr->valloced) + vfree(hdr); + else + kfree(hdr); +} + +void * +zalloc(arg, items, size) + void *arg; + unsigned int items, size; +{ + struct chunk_header *hdr; + unsigned nbytes; + + nbytes = items * size + sizeof(*hdr); + hdr = kmalloc(nbytes, GFP_ATOMIC); + if (hdr == 0) + return 0; + hdr->valloced = 0; + hdr->guard = GUARD_MAGIC; + return (void *) (hdr + 1); +} + +void * zalloc_init(void *arg, unsigned int items, unsigned int size) +{ + struct chunk_header *hdr; + unsigned nbytes; + + nbytes = items * size + sizeof(*hdr); + if (nbytes >= MIN_VMALLOC) + hdr = vmalloc(nbytes); + else + hdr = kmalloc(nbytes, GFP_KERNEL); + if (hdr == 0) + return 0; + hdr->valloced = nbytes >= MIN_VMALLOC; + hdr->guard = GUARD_MAGIC; + return (void *) (hdr + 1); +} + +static void +z_comp_free(arg) + void *arg; +{ + struct irda_deflate_state *state = (struct irda_deflate_state *) arg; + + if (state) { + deflateEnd(&state->strm); + kfree(state); + MOD_DEC_USE_COUNT; + } +} + +/* + * Allocate space for a compressor. + */ +static void * +z_comp_alloc(options, opt_len) + unsigned char *options; + int opt_len; +{ + struct irda_deflate_state *state; + int w_size; + + if (opt_len != CILEN_DEFLATE + || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) + || options[1] != CILEN_DEFLATE + || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL + || options[3] != DEFLATE_CHK_SEQUENCE) + return NULL; + w_size = DEFLATE_SIZE(options[2]); + w_size = MAX_WBITS; + if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE) + return NULL; + + state = (struct irda_deflate_state *) kmalloc(sizeof(*state), GFP_KERNEL); + if (state == NULL) + return NULL; + + MOD_INC_USE_COUNT; + memset (state, 0, sizeof (struct irda_deflate_state)); + state->strm.next_in = NULL; + state->strm.zalloc = zalloc_init; + state->strm.zfree = zfree; + state->w_size = w_size; + + if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION, + DEFLATE_METHOD_VAL, -w_size, 8, Z_DEFAULT_STRATEGY) + != Z_OK) + goto out_free; + state->strm.zalloc = zalloc; + return (void *) state; + +out_free: + z_comp_free(state); + MOD_DEC_USE_COUNT; + return NULL; +} + +static int +z_comp_init(arg, options, opt_len, unit, hdrlen, debug) + void *arg; + unsigned char *options; + int opt_len, unit, hdrlen, debug; +{ + struct irda_deflate_state *state = (struct irda_deflate_state *) arg; + + if (opt_len < CILEN_DEFLATE + || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) + || options[1] != CILEN_DEFLATE + || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL + || DEFLATE_SIZE(options[2]) != state->w_size + || options[3] != DEFLATE_CHK_SEQUENCE) + return 0; + + state->seqno = 0; + state->unit = unit; + state->debug = debug; + + deflateReset(&state->strm); + + return 1; +} + +static void z_comp_reset(void *arg) +{ + struct irda_deflate_state *state = (struct irda_deflate_state *) arg; + + state->seqno = 0; + deflateReset(&state->strm); +} + +int +z_compress(arg, rptr, obuf, isize, osize) + void *arg; + unsigned char *rptr; /* uncompressed packet (in) */ + unsigned char *obuf; /* compressed packet (out) */ + int isize, osize; +{ + struct irda_deflate_state *state = (struct irda_deflate_state *) arg; + int r, olen, oavail; + + olen = 0; + + /* Don't generate compressed packets which are larger than + the uncompressed packet. */ + if (osize > isize) + osize = isize; + + state->strm.next_out = obuf; + state->strm.avail_out = oavail = osize; + + state->strm.next_in = rptr; + state->strm.avail_in = isize; + + for (;;) { + r = deflate(&state->strm, Z_PACKET_FLUSH); + if (r != Z_OK) { + if (state->debug) + printk(KERN_ERR + "z_compress: deflate returned %d\n", r); + break; + } + if (state->strm.avail_out == 0) { + olen += oavail; + state->strm.next_out = NULL; + state->strm.avail_out = oavail = 1000000; + } else { + break; /* all done */ + } + } + olen += oavail - state->strm.avail_out; + + /* + * See if we managed to reduce the size of the packet. + */ + if (olen < isize) { + state->stats.comp_bytes += olen; + state->stats.comp_packets++; + } else { + state->stats.inc_bytes += isize; + state->stats.inc_packets++; + olen = 0; + } + state->stats.unc_bytes += isize; + state->stats.unc_packets++; + + return olen; +} + +static void +z_comp_stats(arg, stats) + void *arg; + struct compstat *stats; +{ + struct irda_deflate_state *state = (struct irda_deflate_state *) arg; + + *stats = state->stats; +} + +static void z_decomp_free(void *arg) +{ + struct irda_deflate_state *state = (struct irda_deflate_state *) arg; + + if (state) { + inflateEnd(&state->strm); + kfree(state); + MOD_DEC_USE_COUNT; + } +} + +/* + * Allocate space for a decompressor. + */ +static void * +z_decomp_alloc(options, opt_len) + unsigned char *options; + int opt_len; +{ + struct irda_deflate_state *state; + int w_size; + + if (opt_len != CILEN_DEFLATE + || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) + || options[1] != CILEN_DEFLATE + || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL + || options[3] != DEFLATE_CHK_SEQUENCE) + return NULL; + w_size = DEFLATE_SIZE(options[2]); + w_size = MAX_WBITS; + if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE) + return NULL; + + state = (struct irda_deflate_state *) kmalloc(sizeof(*state), GFP_KERNEL); + if (state == NULL) + return NULL; + + MOD_INC_USE_COUNT; + memset (state, 0, sizeof (struct irda_deflate_state)); + state->w_size = w_size; + state->strm.next_out = NULL; + state->strm.zalloc = zalloc_init; + state->strm.zfree = zfree; + + if (inflateInit2(&state->strm, -w_size) != Z_OK) + goto out_free; + state->strm.zalloc = zalloc; + return (void *) state; + +out_free: + z_decomp_free(state); + MOD_DEC_USE_COUNT; + return NULL; +} + +static int +z_decomp_init(arg, options, opt_len, unit, hdrlen, mru, debug) + void *arg; + unsigned char *options; + int opt_len, unit, hdrlen, mru, debug; +{ + struct irda_deflate_state *state = (struct irda_deflate_state *) arg; + + if (opt_len < CILEN_DEFLATE + || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) + || options[1] != CILEN_DEFLATE + || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL + || DEFLATE_SIZE(options[2]) != state->w_size + || options[3] != DEFLATE_CHK_SEQUENCE) + return 0; + + state->seqno = 0; + state->unit = unit; + state->debug = debug; + state->mru = mru; + + inflateReset(&state->strm); + + return 1; +} + +static void z_decomp_reset(void *arg) +{ + struct irda_deflate_state *state = (struct irda_deflate_state *) arg; + + state->seqno = 0; + inflateReset(&state->strm); +} + +/* + * Decompress a Deflate-compressed packet. + * + * Because of patent problems, we return DECOMP_ERROR for errors + * found by inspecting the input data and for system problems, but + * DECOMP_FATALERROR for any errors which could possibly be said to + * be being detected "after" decompression. For DECOMP_ERROR, + * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be + * infringing a patent of Motorola's if we do, so we take CCP down + * instead. + * + * Given that the frame has the correct sequence number and a good FCS, + * errors such as invalid codes in the input most likely indicate a + * bug, so we return DECOMP_FATALERROR for them in order to turn off + * compression, even though they are detected by inspecting the input. + */ +int +z_decompress(arg, ibuf, isize, obuf, osize) + void *arg; + unsigned char *ibuf; + int isize; + unsigned char *obuf; + int osize; +{ + struct irda_deflate_state *state = (struct irda_deflate_state *) arg; + int olen, r; + int overflow; + unsigned char overflow_buf[1]; + + if (isize <= DEFLATE_OVHD) { + if (state->debug) + printk(KERN_DEBUG "z_decompress%d: short pkt (%d)\n", + state->unit, isize); + return DECOMP_ERROR; + } + + /* + * Set up to call inflate. + */ + state->strm.next_in = ibuf; + state->strm.avail_in = isize; + state->strm.next_out = obuf; + state->strm.avail_out = osize; + overflow = 0; + + /* + * Call inflate, supplying more input or output as needed. + */ + for (;;) { + r = inflate(&state->strm, Z_PACKET_FLUSH); + if (r != Z_OK) { + if (state->debug) + printk(KERN_DEBUG "z_decompress%d: inflate returned %d (%s)\n", + state->unit, r, (state->strm.msg? state->strm.msg: "")); + return DECOMP_FATALERROR; + } + if (state->strm.avail_out != 0) + break; /* all done */ + + if (!overflow) { + /* + * We've filled up the output buffer; the only way to + * find out whether inflate has any more characters + * left is to give it another byte of output space. + */ + state->strm.next_out = overflow_buf; + state->strm.avail_out = 1; + overflow = 1; + } else { + if (state->debug) + printk(KERN_DEBUG "z_decompress%d: ran out of mru\n", + state->unit); + return DECOMP_FATALERROR; + } + } + + olen = osize + overflow - state->strm.avail_out; + state->stats.unc_bytes += olen; + state->stats.unc_packets++; + state->stats.comp_bytes += isize; + state->stats.comp_packets++; + + return olen; +} + +/* + * Incompressible data has arrived - add it to the history. + */ +static void +z_incomp(arg, ibuf, icnt) + void *arg; + unsigned char *ibuf; + int icnt; +{ + struct irda_deflate_state *state = (struct irda_deflate_state *) arg; + int r; + + /* + * Check that the protocol is one we handle. + */ + + /* + * We start at the either the 1st or 2nd byte of the protocol field, + * depending on whether the protocol value is compressible. + */ + state->strm.next_in = ibuf; + state->strm.avail_in = icnt; + + r = inflateIncomp(&state->strm); + if (r != Z_OK) { + /* gak! */ + if (state->debug) { + printk(KERN_DEBUG "z_incomp%d: inflateIncomp returned %d (%s)\n", + state->unit, r, (state->strm.msg? state->strm.msg: "")); + } + return; + } + + /* + * Update stats. + */ + state->stats.inc_bytes += icnt; + state->stats.inc_packets++; + state->stats.unc_bytes += icnt; + state->stats.unc_packets++; +} + +/************************************************************* + * Module interface table + *************************************************************/ + +/* These are in ppp.c */ +extern int irda_register_compressor (struct compressor *cp); +extern void irda_unregister_compressor (struct compressor *cp); + +/* + * Procedures exported to if_ppp.c. + */ +static struct compressor irda_deflate = { + CI_DEFLATE, /* compress_proto */ + z_comp_alloc, /* comp_alloc */ + z_comp_free, /* comp_free */ + z_comp_init, /* comp_init */ + z_comp_reset, /* comp_reset */ + z_compress, /* compress */ + z_comp_stats, /* comp_stat */ + z_decomp_alloc, /* decomp_alloc */ + z_decomp_free, /* decomp_free */ + z_decomp_init, /* decomp_init */ + z_decomp_reset, /* decomp_reset */ + z_decompress, /* decompress */ + z_incomp, /* incomp */ + z_comp_stats, /* decomp_stat */ +}; + +static struct compressor irda_deflate_draft = { + CI_DEFLATE_DRAFT, /* compress_proto */ + z_comp_alloc, /* comp_alloc */ + z_comp_free, /* comp_free */ + z_comp_init, /* comp_init */ + z_comp_reset, /* comp_reset */ + z_compress, /* compress */ + z_comp_stats, /* comp_stat */ + z_decomp_alloc, /* decomp_alloc */ + z_decomp_free, /* decomp_free */ + z_decomp_init, /* decomp_init */ + z_decomp_reset, /* decomp_reset */ + z_decompress, /* decompress */ + z_incomp, /* incomp */ + z_comp_stats, /* decomp_stat */ +}; + +__initfunc(int irda_deflate_init(void)) +{ + int answer = irda_register_compressor ( &irda_deflate); + if (answer == 0) + printk (KERN_INFO + "IrDA Deflate Compression module registered\n"); + irda_register_compressor( &irda_deflate_draft); + return answer; +} + +void irda_deflate_cleanup(void) +{ + + irda_unregister_compressor (&irda_deflate); + irda_unregister_compressor (&irda_deflate_draft); +} + +#ifdef MODULE +/************************************************************* + * Module support routines + *************************************************************/ + +int init_module(void) +{ + return irda_deflate_init(); +} + +void +cleanup_module(void) +{ + if (MOD_IN_USE) + printk (KERN_INFO + "Deflate Compression module busy, remove delayed\n"); + else { + irda_deflate_cleanup(); + } +} +#endif diff --git a/net/irda/crc.c b/net/irda/crc.c new file mode 100644 index 000000000000..9a6f3021fa05 --- /dev/null +++ b/net/irda/crc.c @@ -0,0 +1,65 @@ +/********************************************************************* + * + * Filename: crc.c + * Version: 0.1 + * Description: CRC calculation routines + * Status: Experimental. + * Author: Dag Brattli + * Created at: Mon Aug 4 20:40:53 1997 + * Modified at: Sat Dec 12 09:56:35 1998 + * Modified by: Dag Brattli + * Sources: ppp.c by Michael Callahan + * Al Longyear + * + ********************************************************************/ + +#include + +/* + * This mysterious table is just the CRC of each possible byte. It can be + * computed using the standard bit-at-a-time methods. The polynomial can + * be seen in entry 128, 0x8408. This corresponds to x^0 + x^5 + x^12. + * Add the implicit x^16, and you have the standard CRC-CCITT. + */ +__u16 const irda_crc16_table[256] = +{ + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + +unsigned short crc_calc( __u16 fcs, __u8 const *buf, size_t len) +{ + while ( len--) + fcs = IR_FCS(fcs, *buf++); + return fcs; +} diff --git a/net/irda/ircomm/Config.in b/net/irda/ircomm/Config.in new file mode 100644 index 000000000000..f384eb8d76df --- /dev/null +++ b/net/irda/ircomm/Config.in @@ -0,0 +1,3 @@ + +dep_tristate 'IrCOMM protocol' CONFIG_IRCOMM $CONFIG_IRDA + diff --git a/net/irda/ircomm/Makefile b/net/irda/ircomm/Makefile new file mode 100644 index 000000000000..1ff2e45be43f --- /dev/null +++ b/net/irda/ircomm/Makefile @@ -0,0 +1,31 @@ +# +# Makefile for the Linux IrDA IrCOMM protocol layer. +# +# 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 definition is now in the main makefile... + +O_TARGET := ircomm_n_vtd.o +O_OBJS := ircomm_common.o attach.o irvtd.o irvtd_driver.o +M_OBJS := ircomm.o ircomm_tty.o +MI_OBJS := ircomm_common.o attach.o irvtd.o irvtd_driver.o + +OX_OBJS += + +# Special rule to build the composite modules + +ifeq ($(CONFIG_IRCOMM),m) +ircomm.o: $(MI_OBJS) + $(LD) $(LD_RFLAG) -r -o $@ ircomm_common.o attach.o + +ircomm_tty.o: $(MI_OBJS) + $(LD) $(LD_RFLAG) -r -o $@ irvtd.o irvtd_driver.o +endif + +include $(TOPDIR)/Rules.make + +tar: + tar -cvf /dev/f1 . + diff --git a/net/irda/ircomm/attach.c b/net/irda/ircomm/attach.c new file mode 100644 index 000000000000..1e5e373ee88d --- /dev/null +++ b/net/irda/ircomm/attach.c @@ -0,0 +1,364 @@ +/********************************************************************* + * + * Filename: attach.c + * Version: + * Description: An implementation of IrCOMM service interface. + * Status: Experimental. + * Author: Takahide Higuchi + * + * Copyright (c) 1998, Takahide Higuchi, , + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * I, Takahide Higuchi, provide no warranty for any of this software. + * This material is provided "AS-IS" and at no charge. + * + ********************************************************************/ + + +/* + * ---------------------------------------------------------------------- + * IrIAS related things for IrCOMM + * If you are to use ircomm layer, use ircomm_attach_cable to + * setup it and register your program. + * ---------------------------------------------------------------------- + */ + + +#include +#include + +#include +#include +#include +#include + +#include + +extern struct ircomm_cb **ircomm; +struct ircomm_cb *discovering_instance; + +static void got_lsapsel(struct ircomm_cb * info); +static void query_lsapsel(struct ircomm_cb * self); +void ircomm_getvalue_confirm( __u16 obj_id, struct ias_value *value, void *priv ); + +#if 0 +static char *rcsid = "$Id: attach.c,v 1.11 1998/10/22 12:02:20 dagb Exp $"; +#endif + + +/* + * handler for iriap_getvaluebyclass_request() + * + */ + +void ircomm_getvalue_confirm( __u16 obj_id, struct ias_value *value, void *priv ){ + + struct ircomm_cb *self = (struct ircomm_cb *) priv; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRCOMM_MAGIC, return;); + + DEBUG(0, __FUNCTION__"type(%d)\n", value->type); + + switch(value->type){ + + case IAS_OCT_SEQ: + /* + * FIXME:we should use data which came here + * it is used for nothing at this time + */ + +#if 1 + DEBUG(0, "octet sequence is:\n"); + { + int i; + for ( i=0;ilen;i++) + printk("%02x", + (int)(*value->t.oct_seq + i) ); + printk("\n"); + } +#endif + query_lsapsel(self); + break; + + case IAS_INTEGER: + /* LsapSel seems to be sent to me */ + + if ( value->t.integer == -1){ + DEBUG( 0, "ircomm_getvalue_confirm: invalid value!\n"); + return; + } + if(self->state == COMM_IDLE){ + self->dlsap = value->t.integer; + got_lsapsel(self); + } + break; + + case IAS_STRING: + DEBUG( 0, __FUNCTION__":STRING is not implemented\n"); + DEBUG( 0, __FUNCTION__":received string:%s\n", + value->t.string); + query_lsapsel(self); /* experiment */ + break; + + case IAS_MISSING: + DEBUG( 0, __FUNCTION__":MISSING is not implemented\n"); + break; + + default: + DEBUG( 0, __FUNCTION__":unknown type!\n"); + break; + } +} + + +static void got_lsapsel(struct ircomm_cb * self){ + + struct notify_t notify; + + DEBUG(0, "ircomm:got_lsapsel: got peersap!(%d)\n", self->dlsap ); + + /* remove tsap for server */ + irttp_close_tsap(self->tsap); + + /* create TSAP for initiater ... */ + irda_notify_init(¬ify); + notify.data_indication = ircomm_accept_data_indication; + notify.connect_confirm = ircomm_accept_connect_confirm; + notify.connect_indication = ircomm_accept_connect_indication; + notify.flow_indication = ircomm_accept_flow_indication; + notify.disconnect_indication = ircomm_accept_disconnect_indication; + strncpy( notify.name, "IrCOMM cli", NOTIFY_MAX_NAME); + notify.instance = self; + + self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, + ¬ify ); + ASSERT(self->tsap != NULL, return;); + + + /* + * invoke state machine + * and notify that I'm ready to accept connect_request + */ + + ircomm_next_state(self, COMM_IDLE); + if(self->d_handler) + self->d_handler(self); +} + + + + + +static void query_lsapsel(struct ircomm_cb * self){ + + DEBUG(0, "ircomm:query_lsapsel..\n"); + + /* + * since we've got Parameters field of IAS, we are to get peersap. + */ + + if(!(self->servicetype & THREE_WIRE_RAW)){ + iriap_getvaluebyclass_request + (self->daddr, "IrDA:IrCOMM", "IrDA:TinyTP:LsapSel", + ircomm_getvalue_confirm, self ); + } else { + DEBUG(0,"ircomm:query_lsap:" + "THREE_WIRE_RAW is not implemented!\n"); + } +} + + + +/* + * ircomm_discovery_indication() + * Remote device is discovered, try query the remote IAS to see which + * device it is, and which services it has. + */ + +void ircomm_discovery_indication( DISCOVERY *discovery) +{ + + struct ircomm_cb *self; + + DEBUG( 0, "ircomm_discovery_indication\n"); + + self = discovering_instance; + ASSERT(self != NULL, return;); + ASSERT(self->magic == IRCOMM_MAGIC, return;); + + self->daddr = discovery->daddr; + + DEBUG( 0, "ircomm_discovery_indication:daddr=%08x\n", self->daddr); + + /* query "Parameters" attribute of LM-IAS */ + + DEBUG(0, "ircomm:querying parameters..\n"); +#if 0 + iriap_getvaluebyclass_request(self->daddr, "IrDA:IrCOMM", + + "Parameters", + ircomm_getvalue_confirm, + self); +#else + query_lsapsel(self); +#endif + return; +} + + +struct ircomm_cb * ircomm_attach_cable( __u8 servicetype, + struct notify_t notify, + void *handler ){ + + int i; + struct ircomm_cb *self = NULL; + struct notify_t server_notify; + struct ias_object* obj; + + /* FIXME: it should not be hard coded */ + __u8 oct_seq[6] = { 0,1,4,1,1,1 }; + + ASSERT(ircomm != NULL,return NULL;); + DEBUG(0,"ircomm_attach_cable:\n"); + + + /* find free handle */ + + for(i = 0; i < IRCOMM_MAX_CONNECTION; i++){ + ASSERT(ircomm[i] != NULL,return(NULL);); + if(!ircomm[i]->in_use){ + self = ircomm[i]; + break; + } + } + + if (!self){ + DEBUG(0,"ircomm_attach_cable:no free handle!\n"); + return (NULL); + } + + self->in_use = 1; + self->servicetype = servicetype; + + DEBUG(0,"attach_cable:servicetype:%d\n",servicetype); + self->d_handler = handler; + self->notify = notify; + + /* register server.. */ + + /* + * TODO: since server TSAP is currentry hard coded, + * we can use *only one* IrCOMM connection. + * We have to create one more TSAP and register IAS entry dynamically + * each time when we are to allocate new server here. + */ + irda_notify_init(&server_notify); + server_notify.data_indication = ircomm_accept_data_indication; + server_notify.connect_confirm = ircomm_accept_connect_confirm; + server_notify.connect_indication = ircomm_accept_connect_indication; + server_notify.flow_indication = ircomm_accept_flow_indication; + server_notify.disconnect_indication = ircomm_accept_disconnect_indication; + server_notify.instance = self; + strncpy( server_notify.name, "IrCOMM srv", NOTIFY_MAX_NAME); + + self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, + &server_notify); + if(!self->tsap){ + DEBUG(0,"ircomm:Sorry, failed to allocate server_tsap\n"); + return NULL; + } + + /* + * Register with LM-IAS + */ + obj = irias_new_object( "IrDA:IrCOMM", IAS_IRCOMM_ID); + irias_add_integer_attrib( obj, "IrDA:TinyTP:LsapSel", + self->tsap->stsap_sel ); + + /* FIXME: it should not be hard coded */ + + irias_add_octseq_attrib( obj, "Parameters", + &oct_seq[0], 6); + irias_insert_object( obj); + +/* obj = irias_new_object( "IrDA:IrCOMM", IAS_IRCOMM_ID); */ +/* irias_add_octseq_attrib( obj, "Parameters", len, &octseq); */ +/* irias_insert_object( obj); */ + + + + /* and start discovering .. */ + discovering_instance = self; + + switch(servicetype){ + case NINE_WIRE: + DEBUG(0,"ircomm_attach_cable:discovering..\n"); + irlmp_register_layer(S_COMM , CLIENT|SERVER, TRUE, + ircomm_discovery_indication); + break; + +/* case CENTRONICS: */ +/* case THREE_WIRE: */ +/* case THREE_WIRE_RAW: */ + + default: + DEBUG(0,"ircomm_attach_cable:requested servicetype is not " + "implemented!\n"); + return NULL; + } + + ircomm_next_state(self, COMM_IDLE); + return (self); +} + + + + +int ircomm_detach_cable(struct ircomm_cb *self){ + + ASSERT( self != NULL, return -EIO;); + ASSERT( self->magic == IRCOMM_MAGIC, return -EIO;); + + + DEBUG(0,"ircomm_detach_cable:\n"); + + /* shutdown ircomm layer */ + if(self->state != COMM_IDLE ){ + DEBUG(0,"ircomm:detach_cable:not IDLE\n"); + if(self->state != COMM_WAITI) + ircomm_disconnect_request(self, NULL); + } + + + switch(self->servicetype){ +/* case CENTRONICS: */ + case NINE_WIRE: +/* case THREE_WIRE: */ + irlmp_unregister_layer( S_COMM, CLIENT|SERVER ); + break; + +/* case THREE_WIRE_RAW: */ +/* irlmp_unregister( S_COMM ) */ +/* irlmp_unregister( S_PRINTER) */ +/* break; */ + + default: + DEBUG(0,"ircomm_detach_cable:requested servicetype is not " + "implemented!\n"); + return -ENODEV; + } + + /* remove tsaps */ + if(self->tsap) + irttp_close_tsap(self->tsap); + + self->tsap = NULL; + self->in_use = 0; + return 0; +} diff --git a/net/irda/ircomm/ircomm_common.c b/net/irda/ircomm/ircomm_common.c new file mode 100644 index 000000000000..cfda567ceb67 --- /dev/null +++ b/net/irda/ircomm/ircomm_common.c @@ -0,0 +1,1290 @@ +/********************************************************************* + * + * Filename: ircomm_common.c + * Version: + * Description: An implementation of IrCOMM service interface, + * state machine, and incidental function(s). + * Status: Experimental. + * Author: Takahide Higuchi + * Source: irlpt_event.c + * + * Copyright (c) 1998, Takahide Higuchi, , + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * I, Takahide Higuchi, provide no warranty for any of this software. + * This material is provided "AS-IS" and at no charge. + * + ********************************************************************/ + +/* + * Reference: + * "'IrCOMM':Serial and Parallel Port Emulation Over IR(Wire Replacement)" + * version 1.0, which is available at http://www.irda.org/. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#if 0 +static char *rcsid = "$Id: ircomm_common.c,v 1.13 1998/10/13 12:59:05 takahide Exp $"; +#endif +static char *version = "IrCOMM_common, $Revision: 1.13 $ $Date: 1998/10/13 12:59:05 $ (Takahide Higuchi)"; + + + + +static void ircomm_state_discovery( struct ircomm_cb *self, + IRCOMM_EVENT event, struct sk_buff *skb ); +static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event, + struct sk_buff *skb ); +static void ircomm_state_waiti( struct ircomm_cb *self, IRCOMM_EVENT event, + struct sk_buff *skb ); +static void ircomm_state_waitr( struct ircomm_cb *self, IRCOMM_EVENT event, + struct sk_buff *skb ); +static void ircomm_state_conn( struct ircomm_cb *self, IRCOMM_EVENT event, + struct sk_buff *skb ); +static void ircomm_do_event( struct ircomm_cb *self, IRCOMM_EVENT event, + struct sk_buff *skb); +void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state); + +int ircomm_check_handle(int handle); + +static void ircomm_parse_control(struct ircomm_cb *self, struct sk_buff *skb, + int type); +static char *ircommstate[] = { + "DISCOVERY", + "IDLE", + "WAITI", + "WAITR", + "CONN", +}; + +static char *ircommservicetype[] = { + "N/A", + "THREE_WIRE_RAW", + "THREE_WIRE", + "NINE_WIRE", + "CENTRONICS", +}; +static char *ircommporttype[] = { + "Unknown", + "SERIAL", + "PARALLEL", +}; + + +struct ircomm_cb **ircomm = NULL; + +static char *ircommevent[] = { + "IRCOMM_CONNECT_REQUEST", + "TTP_CONNECT_INDICATION", + "LMP_CONNECT_INDICATION", + + "TTP_CONNECT_CONFIRM", + "TTP_DISCONNECT_INDICATION", + "LMP_CONNECT_CONFIRM", + "LMP_DISCONNECT_INDICATION", + + "IRCOMM_CONNECT_RESPONSE", + "IRCOMM_DISCONNECT_REQUEST", + + "TTP_DATA_INDICATION", + "IRCOMM_DATA_REQUEST", + "LMP_DATA_INDICATION", + "IRCOMM_CONTROL_REQUEST", +}; + +int ircomm_proc_read(char *buf, char **start, off_t offset, + int len, int unused); + +#ifdef CONFIG_PROC_FS +extern struct proc_dir_entry proc_irda; +struct proc_dir_entry proc_ircomm = { + 0, 6, "ircomm", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, NULL, + &ircomm_proc_read, +}; +#endif + +static void (*state[])( struct ircomm_cb *self, IRCOMM_EVENT event, + struct sk_buff *skb) = +{ + ircomm_state_discovery, + ircomm_state_idle, + ircomm_state_waiti, + ircomm_state_waitr, + ircomm_state_conn, +}; + + +__initfunc(int ircomm_init(void)) +{ + int i; + + printk( KERN_INFO "%s\n", version); + DEBUG( 4, "ircomm_common:init_module\n"); + + /* allocate master array */ + + ircomm = (struct ircomm_cb **) kmalloc( sizeof(struct ircomm_cb *) * + IRCOMM_MAX_CONNECTION, + GFP_KERNEL); + if ( ircomm == NULL) { + printk( KERN_WARNING "IrCOMM: Can't allocate ircomm array!\n"); + return -ENOMEM; + } + + memset( ircomm, 0, sizeof(struct ircomm_cb *) * IRCOMM_MAX_CONNECTION); + + /* initialize structures */ + + for(i = 0;i < IRCOMM_MAX_CONNECTION; i++){ + ircomm[i] = kmalloc( sizeof(struct ircomm_cb), GFP_KERNEL ); + + if(!ircomm[i]){ + printk(KERN_ERR "ircomm:kmalloc failed!\n"); + return -ENOMEM; + } + + + memset( ircomm[i], 0, sizeof(struct ircomm_cb)); + + ircomm[i]->magic = IRCOMM_MAGIC; + /* default settings */ + ircomm[i]->data_format = CS8; + ircomm[i]->flow_ctrl = USE_RTS|USE_DTR; /*TODO: is this OK? */ + ircomm[i]->xon_char = 0x11; + ircomm[i]->xoff_char = 0x13; + ircomm[i]->enq_char = 0x05; + ircomm[i]->ack_char = 0x06; + + ircomm[i]->max_txbuff_size = COMM_DEFAULT_DATA_SIZE; /* 64 */ + ircomm[i]->maxsdusize = SAR_DISABLE; + ircomm[i]->ctrl_skb = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE); + if (ircomm[i]->ctrl_skb == NULL){ + DEBUG(0,"ircomm:init_module:alloc_skb failed!\n"); + return -ENOMEM; + } + + skb_reserve(ircomm[i]->ctrl_skb,COMM_HEADER_SIZE); + + } + + /* + * we register /proc/irda/ircomm + */ + +#ifdef CONFIG_PROC_FS + proc_register( &proc_irda, &proc_ircomm); +#endif /* CONFIG_PROC_FS */ + + return 0; +} + +void ircomm_cleanup(void) +{ + int i; + + DEBUG( 4, "ircomm_common:cleanup_module\n"); + /* + * free some resources + */ + if (ircomm) { + for (i=0; ictrl_skb){ + dev_kfree_skb(ircomm[i]->ctrl_skb); + + ircomm[i]->ctrl_skb = NULL; + } + + DEBUG( 4, "freeing structures(%d)\n",i); + kfree(ircomm[i]); + ircomm[i] = NULL; + } + } + DEBUG( 4, "freeing master array\n"); + kfree(ircomm); + ircomm = NULL; + } + +#ifdef CONFIG_PROC_FS + proc_unregister( &proc_irda, proc_ircomm.low_ino); +#endif +} + +/* + * ---------------------------------------------------------------------- + * callbacks which accept incoming indication/confirm from IrTTP (or IrLMP) + * ---------------------------------------------------------------------- + */ + +void ircomm_accept_data_indication(void *instance, void *sap, struct sk_buff *skb){ + + struct ircomm_cb *self = (struct ircomm_cb *)instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRCOMM_MAGIC, return;); + ASSERT( skb != NULL, return;); + + DEBUG(4,"ircomm_accept_data_indication:\n"); + ircomm_do_event( self, TTP_DATA_INDICATION, skb); +} + +void ircomm_accept_connect_confirm(void *instance, void *sap, + struct qos_info *qos, + int maxsdusize, struct sk_buff *skb){ + + struct ircomm_cb *self = (struct ircomm_cb *)instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRCOMM_MAGIC, return;); + ASSERT( skb != NULL, return;); + ASSERT( qos != NULL, return;); + + DEBUG(0,"ircomm_accept_connect_confirm:\n"); + + if(maxsdusize == SAR_DISABLE) + self->max_txbuff_size = qos->data_size.value; + else { + ASSERT(maxsdusize >= COMM_DEFAULT_DATA_SIZE, return;); + self->max_txbuff_size = maxsdusize; /* use fragmentation */ + } + + self->qos = qos; + self->null_modem_mode = 0; /* disable null modem emulation */ + + ircomm_do_event( self, TTP_CONNECT_CONFIRM, skb); +} + +void ircomm_accept_connect_indication(void *instance, void *sap, + struct qos_info *qos, + int maxsdusize, + struct sk_buff *skb ){ + + struct ircomm_cb *self = (struct ircomm_cb *)instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRCOMM_MAGIC, return;); + ASSERT( skb != NULL, return;); + ASSERT( qos != NULL, return;); + + DEBUG(0,"ircomm_accept_connect_indication:\n"); + + if(maxsdusize == SAR_DISABLE) + self->max_txbuff_size = qos->data_size.value; + else + self->max_txbuff_size = maxsdusize; + + self->qos = qos; + ircomm_do_event( self, TTP_CONNECT_INDICATION, skb); +} + +void ircomm_accept_disconnect_indication(void *instance, void *sap, LM_REASON reason, + struct sk_buff *skb){ + struct ircomm_cb *self = (struct ircomm_cb *)instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRCOMM_MAGIC, return;); + ASSERT( skb != NULL, return;); + + DEBUG(0,"ircomm_accept_disconnect_indication:\n"); + ircomm_do_event( self, TTP_DISCONNECT_INDICATION, skb); +} + +void ircomm_accept_flow_indication( void *instance, void *sap, LOCAL_FLOW cmd){ + + struct ircomm_cb *self = (struct ircomm_cb *)instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRCOMM_MAGIC, return;); + + switch(cmd){ + case FLOW_START: + DEBUG(0,"ircomm_accept_flow_indication:START\n"); + + self->pi = TX_READY; + self->ttp_stop = 0; + if(self->notify.flow_indication) + self->notify.flow_indication( self->notify.instance, + self, cmd); + ircomm_control_request(self); + break; + + case FLOW_STOP: + DEBUG(0,"ircomm_accept_flow_indication:STOP\n"); + self->pi = TX_BUSY; + self->ttp_stop = 1; + if(self->notify.flow_indication) + self->notify.flow_indication( self->notify.instance, + self, cmd); + break; + + default: + DEBUG(0,"ircomm_accept_flow_indication:unknown status!\n"); + } + +} + +/* + * ---------------------------------------------------------------------- + * Implementation of actions,descrived in section 7.4 of the reference. + * ---------------------------------------------------------------------- + */ + + +static void issue_connect_request(struct ircomm_cb *self, + struct sk_buff *userdata ){ + + /* TODO: we have to send/build userdata field which contains + InitialControlParameters */ + /* but userdata field is not implemeted in irttp.c.. */ + + switch(self->servicetype){ + case THREE_WIRE_RAW: + /* not implemented yet! Do nothing */ + DEBUG(0, "ircomm:issue_connect_request:" + "not implemented servicetype!"); + break; + + case DEFAULT: + irttp_connect_request(self->tsap, self->dlsap, self->daddr, + NULL, self->maxsdusize, NULL); + break; + + case THREE_WIRE: + case NINE_WIRE: + case CENTRONICS: + + irttp_connect_request(self->tsap, self->dlsap, self->daddr, + NULL, self->maxsdusize, NULL); + break; + + default: + DEBUG(0,"ircomm:issue_connect_request:Illegal servicetype %d\n" + ,self->servicetype); + } +} + + +static void disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb){ + + /* + * Not implemented parameter"Reason".That is optional. + * What is reason? maybe discribed in irmod.h? + */ + + if(self->notify.disconnect_indication) + self->notify.disconnect_indication( self->notify.instance, + self, + self->reason,skb); + +} + +static void connect_indication(struct ircomm_cb *self, struct qos_info *qos, + struct sk_buff *skb){ + +/* If controlparameters don't exist, we use the servicetype"DEFAULT".*/ +/* if( !ircomm_parse_controlchannel( self, data)) */ +/* self->servicetype = DEFAULT; TODOD:fix this! TH */ + + if(self->notify.connect_indication) + self->notify.connect_indication(self->notify.instance, self, + qos, 0, skb); +} + +#if 0 +/* it's for THREE_WIRE_RAW.*/ +static void connect_indication_three_wire_raw(void){ + DEBUG(0,"ircomm:connect_indication_threewire():not implemented!"); +} +#endif + + +static void connect_confirmation(struct ircomm_cb *self, struct sk_buff *skb){ + + /* give a connect_confirm to the client */ + if( self->notify.connect_confirm ) + self->notify.connect_confirm(self->notify.instance, + self, NULL, SAR_DISABLE, skb); +} + +static void issue_connect_response(struct ircomm_cb *self, + struct sk_buff *skb ){ + + DEBUG(0,"ircomm:issue_connect_response:\n"); + + if( self->servicetype == THREE_WIRE_RAW){ + DEBUG(0,"ircomm:issue_connect_response():3WIRE-RAW is not " + "implemented yet !\n"); + /* irlmp_connect_rsp(); */ + } else { + irttp_connect_response(self->tsap, self->maxsdusize, skb); + } +} + +static void issue_disconnect_request(struct ircomm_cb *self, + struct sk_buff *userdata ){ + if(self->servicetype == THREE_WIRE_RAW){ + DEBUG(0,"ircomm:issue_disconnect_request():3wireraw is not implemented!"); + } + else + irttp_disconnect_request(self->tsap, NULL, P_NORMAL); +} + +static void issue_data_request(struct ircomm_cb *self, + struct sk_buff *userdata ){ + int err; + + if(self->servicetype == THREE_WIRE_RAW){ + /* irlmp_data_request(self->lmhandle,userdata); */ + DEBUG(0,"ircomm:issue_data_request():not implemented!"); + return; + } + + DEBUG(4,"ircomm:issue_data_request():sending frame\n"); + err = irttp_data_request(self->tsap , userdata ); + if(err) + DEBUG(0,"ircomm:ttp_data_request failed\n"); + if(userdata && err) + dev_kfree_skb( userdata); + +} + +static void issue_control_request(struct ircomm_cb *self, + struct sk_buff *userdata ){ + if(self->servicetype == THREE_WIRE_RAW){ + DEBUG(0,"THREE_WIRE_RAW is not implemented\n"); + + }else { + irttp_data_request(self->tsap,userdata); + } +} + + +static void process_data(struct ircomm_cb *self, struct sk_buff *skb ){ + + DEBUG(4,"ircomm:process_data:skb_len is(%d),clen_is(%d)\n", + (int)skb->len ,(int)skb->data[0]); + + /* + * we always have to parse control channel + * (see page17 of IrCOMM standard) + */ + + ircomm_parse_control(self, skb, CONTROL_CHANNEL); + + if(self->notify.data_indication && skb->len) + self->notify.data_indication(self->notify.instance, self, + skb); +} + +void ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb){ + /* Not implemented yet:THREE_WIRE_RAW service uses this function. */ + DEBUG(0,"ircomm_data_indication:not implemented yet!\n"); +} + + +/* + * ---------------------------------------------------------------------- + * Implementation of state chart, + * descrived in section 7.1 of the specification. + * ---------------------------------------------------------------------- + */ + +static void ircomm_do_event( struct ircomm_cb *self, IRCOMM_EVENT event, + struct sk_buff *skb) { + + DEBUG( 4, "ircomm_do_event: STATE = %s, EVENT = %s\n", + ircommstate[self->state], ircommevent[event]); + (*state[ self->state ]) ( self, event, skb); +} + +void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state) { + self->state = state; + DEBUG( 0, "ircomm_next_state: NEXT STATE = %d(%s), sv(%d)\n", + (int)state, ircommstate[self->state],self->servicetype); +} + + +/* + * we currently need dummy (discovering) state for debugging, + * which state is not defined in the reference. + */ + +static void ircomm_state_discovery( struct ircomm_cb *self, + IRCOMM_EVENT event, struct sk_buff *skb ){ + DEBUG(0,"ircomm_state_discovery: " + "why call me? \n"); + if(skb) + dev_kfree_skb( skb); +} + + +/* + * ircomm_state_idle + */ + +static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event, + struct sk_buff *skb ){ + switch(event){ + case IRCOMM_CONNECT_REQUEST: + + ircomm_next_state(self, COMM_WAITI); + issue_connect_request( self, skb ); + break; + + case TTP_CONNECT_INDICATION: + + ircomm_next_state(self, COMM_WAITR); + connect_indication( self, self->qos, skb); + break; + + case LMP_CONNECT_INDICATION: + + /* I think this is already done in irlpt_event.c */ + + DEBUG(0,"ircomm_state_idle():LMP_CONNECT_IND is notimplemented!"); + /* connect_indication_three_wire_raw(); */ + /* ircomm_next_state(self, COMM_WAITR); */ + break; + + default: + DEBUG(0,"ircomm_state_idle():unknown event =%d(%s)\n", + event, ircommevent[event]); + } +} + +/* + * ircomm_state_waiti + */ + +static void ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event, + struct sk_buff *skb ){ + switch(event){ + case TTP_CONNECT_CONFIRM: + ircomm_next_state(self, COMM_CONN); + connect_confirmation( self, skb ); + break; + case TTP_DISCONNECT_INDICATION: + ircomm_next_state(self, COMM_IDLE); + disconnect_indication(self, skb); + break; +/* case LMP_CONNECT_CONFIRM: */ +/* ircomm_connect_cnfirmation; */ +/* ircomm_next_state(self, COMM_CONN); */ +/* break; */ +/* case LMP_DISCONNECT_INDICATION: */ +/* ircomm_disconnect_ind; */ +/* ircomm_next_state(self, COMM_IDLE); */ +/* break; */ + default: + DEBUG(0,"ircomm_state_waiti:unknown event =%d(%s)\n", + event, ircommevent[event]); + } +} + + + +/* + * ircomm_state_waitr + */ +static void ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event, + struct sk_buff *skb ) { + + switch(event){ + case IRCOMM_CONNECT_RESPONSE: + + /* issue_connect_response */ + + if(self->servicetype==THREE_WIRE_RAW){ + DEBUG(0,"ircomm:issue_connect_response:" + "THREE_WIRE_RAW is not implemented!\n"); + /* irlmp_connect_response(Vpeersap, + * ACCEPT,null); + */ + } else { + ircomm_next_state(self, COMM_CONN); + issue_connect_response(self, skb); + } + break; + + case IRCOMM_DISCONNECT_REQUEST: + ircomm_next_state(self, COMM_IDLE); + issue_disconnect_request(self, skb); + break; + + case TTP_DISCONNECT_INDICATION: + ircomm_next_state(self, COMM_IDLE); + disconnect_indication(self, skb); + break; + +/* case LMP_DISCONNECT_INDICATION: */ +/* disconnect_indication(); */ +/* ircomm_next_state(self, COMM_IDLE); */ +/* break; */ + default: + DEBUG(0,"ircomm_state_waitr:unknown event =%d(%s)\n", + event, ircommevent[event]); + } +} + +/* + * ircomm_state_conn + */ + +static void ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, + struct sk_buff *skb ){ + switch(event){ + case TTP_DATA_INDICATION: + process_data(self, skb); + /* stay CONN state*/ + break; + case IRCOMM_DATA_REQUEST: + issue_data_request(self, skb); + /* stay CONN state*/ + break; +/* case LMP_DATA_INDICATION: */ +/* ircomm_data_indicated(); */ +/* stay CONN state */ +/* break; */ + case IRCOMM_CONTROL_REQUEST: + issue_control_request(self, skb); + /* stay CONN state*/ + break; + case TTP_DISCONNECT_INDICATION: + ircomm_next_state(self, COMM_IDLE); + disconnect_indication(self, skb); + break; + case IRCOMM_DISCONNECT_REQUEST: + ircomm_next_state(self, COMM_IDLE); + issue_disconnect_request(self, skb); + break; +/* case LM_DISCONNECT_INDICATION: */ +/* disconnect_indication(); */ +/* ircomm_next_state(self, COMM_IDLE); */ +/* break; */ + default: + DEBUG(0,"ircomm_state_conn:unknown event =%d(%s)\n", + event, ircommevent[event]); + } +} + + +/* + * ---------------------------------------------------------------------- + * ircomm requests + * + * ---------------------------------------------------------------------- + */ + + +void ircomm_connect_request(struct ircomm_cb *self, int maxsdusize){ + + /* + * TODO:build a packet which contains "initial control parameters" + * and send it with connect_request + */ + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRCOMM_MAGIC, return;); + + DEBUG(0,"ircomm_connect_request:\n"); + + self->maxsdusize = maxsdusize; + ircomm_do_event( self, IRCOMM_CONNECT_REQUEST, NULL); +} + +void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata, + int maxsdusize){ + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRCOMM_MAGIC, return;); + /* ASSERT( userdata != NULL, return;); */ + + DEBUG(4,"ircomm_connect_response:\n"); + + /* + * TODO:build a packet which contains "initial control parameters" + * and send it with connect_response + */ + + if(!userdata){ + /* FIXME: check for errors and initialize? DB */ + userdata = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE); + if(!userdata){ + DEBUG(0, __FUNCTION__"alloc_skb failed\n"); + return; + } + IS_SKB(userdata, return;); + skb_reserve(userdata,COMM_HEADER_SIZE); + } + + /* enable null-modem emulation (i.e. server mode )*/ + self->null_modem_mode = 1; + + self->maxsdusize = maxsdusize; + if(maxsdusize != SAR_DISABLE) + self->max_txbuff_size = maxsdusize; + ircomm_do_event(self, IRCOMM_CONNECT_RESPONSE, userdata); +} + +void ircomm_disconnect_request(struct ircomm_cb *self, struct sk_buff *userdata){ + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRCOMM_MAGIC, return;); + + DEBUG(0,"ircomm_disconnect_request\n"); + ircomm_do_event(self, IRCOMM_DISCONNECT_REQUEST, NULL); +} + + +void ircomm_data_request(struct ircomm_cb *self, struct sk_buff *userdata){ + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRCOMM_MAGIC, return;); + ASSERT( userdata != NULL, return;); + + if(self->state != COMM_CONN){ + DEBUG(4,"ignore IRCOMM_DATA_REQUEST:not connected\n"); + if(userdata) + dev_kfree_skb(userdata); + return; + } + + DEBUG(4,"ircomm_data_request\n"); + ircomm_do_event(self, IRCOMM_DATA_REQUEST, userdata); +} + +/* + * ---------------------------------------------------------------------- + * IrCOMM_control.req and friends + * + * ---------------------------------------------------------------------- + */ + +static void ircomm_tx_ctrlbuffer(struct ircomm_cb *self ){ + + __u8 clen; + struct sk_buff *skb = self->ctrl_skb; + + DEBUG(4,"ircomm_tx_ctrlbuffer:\n"); + + /* add "clen" field */ + + clen=skb->len; + if(clen){ + skb_push(skb,1); + skb->data[0]=clen; + +#if 0 + printk("tx_ctrl:"); + { + int i; + for ( i=0;ilen;i++) + printk("%02x", skb->data[i]); + printk("\n"); + } +#endif + + ircomm_do_event(self, IRCOMM_CONTROL_REQUEST, skb); + + skb = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE); + if (skb==NULL){ + DEBUG(0,"ircomm_tx_ctrlbuffer:alloc_skb failed!\n"); + return; + } + skb_reserve(skb,COMM_HEADER_SIZE); + self->ctrl_skb = skb; + } +} + + +void ircomm_control_request(struct ircomm_cb *self){ + + struct sk_buff *skb; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRCOMM_MAGIC, return;); + + DEBUG(0, "ircomm_control_request:\n"); + + if(self->ttp_stop || self->state != COMM_CONN){ + DEBUG(0,"ircomm_control_request:can't send it.. ignore it\n"); + return; + } + + skb = self->ctrl_skb; + IS_SKB(skb,return;); + + if(skb->len) + ircomm_tx_ctrlbuffer(self); +} + + +static void append_tuple(struct ircomm_cb *self, + __u8 instruction, __u8 pl , __u8 *value){ + + __u8 *frame; + struct sk_buff *skb; + int i,c; + + skb = self->ctrl_skb; + ASSERT(skb != NULL, return;); + IS_SKB(skb,return;); + + /*if there is little room in the packet... */ + + if(skb->len > COMM_DEFAULT_DATA_SIZE - COMM_HEADER_SIZE - (pl+2)){ + if(!self->ttp_stop && self->state == COMM_CONN){ + + /* send a packet if we can */ + ircomm_tx_ctrlbuffer(self); + skb = self->ctrl_skb; + } else { + DEBUG(0, "ircomm_append_ctrl:there's no room.. ignore it\n"); + + /* TODO: we have to detect whether we have to resend some + information after ttp_stop is cleared */ + + /* self->resend_ctrl = 1; */ + return; + } + } + + frame = skb_put(skb,pl+2); + c = 0; + frame[c++] = instruction; /* PI */ + frame[c++] = pl; /* PL */ + for(i=0; i < pl ; i++) + frame[c++] = *value++; /* PV */ + +} + + + +/* + * ircomm_append_ctrl(); + * this function is exported as a request to send some control-channel tuples + * to peer device + */ + +void ircomm_append_ctrl(struct ircomm_cb *self, __u8 instruction){ + + __u8 pv[70]; + __u8 *value = &pv[0]; + __u32 temp; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRCOMM_MAGIC, return;); + + if(self->state != COMM_CONN) + return; + + if(self->servicetype == THREE_WIRE_RAW){ + DEBUG(0,"THREE_WIRE_RAW shuold not use me!\n"); + return; + } + + DEBUG(4,"ircomm_append_ctrl:\n"); + + /* find parameter and its length */ + + switch(instruction){ + + case POLL_FOR_LINE_SETTINGS: + case STATUS_QUERY: + case IEEE1284_MODE_SUPPORT: + case IEEE1284_DEVICEID: + append_tuple(self,instruction,0,NULL); + break; + + case SERVICETYPE: + value[0] = self->servicetype; + append_tuple(self,instruction,1,value); + break; + case DATA_FORMAT: + value[0] = self->data_format; + append_tuple(self,instruction,1,value); + break; + case FLOW_CONTROL: + if(self->null_modem_mode){ + + /* inside out */ + value[0] = (self->flow_ctrl & 0x55) << 1; + value[0] |= (self->flow_ctrl & 0xAA) >> 1; + }else{ + value[0] = self->flow_ctrl; + } + append_tuple(self,instruction,1,value); + break; + case LINESTATUS: + value[0] = self->line_status; + append_tuple(self,instruction,1,value); + break; + case BREAK_SIGNAL: + value[0] = self->break_signal; + append_tuple(self,instruction,1,value); + break; + case DTELINE_STATE: + if(self->null_modem_mode){ + /* null modem emulation */ + + /* output RTS as CTS */ + + if(self->dte & DELTA_RTS) + value[0] = DELTA_CTS; + if(self->dte & MCR_RTS) + value[0] |= MSR_CTS; + + /* output DTR as {DSR & CD & RI} */ + + if(self->dte & DELTA_DTR) + value[0] |= (DELTA_DSR|DELTA_RI|DELTA_DCD); + if(self->dte & MCR_DTR) + value[0] |= (MSR_DSR|MSR_RI|MSR_DCD); + append_tuple(self,DCELINE_STATE,1,value); + }else{ + value[0] = self->dte; + append_tuple(self,instruction,1,value); + } + self->dte &= ~(DELTA_RTS|DELTA_DTR); + break; + + case DCELINE_STATE: + value[0] = self->dce; + append_tuple(self,instruction,1,value); + break; + case SET_BUSY_TIMEOUT: + value[0] = self->busy_timeout; + append_tuple(self,instruction,1,value); + break; + + case XON_XOFF_CHAR: + value[0] = self->xon_char; + value[1] = self->xoff_char; + append_tuple(self,instruction,2,value); + break; + + case ENQ_ACK_CHAR: + value[0] = self->enq_char; + value[1] = self->ack_char; + append_tuple(self,instruction,2,value); + break; + + case IEEE1284_ECP_EPP_DATA_TRANSFER: + value[0] = self->ecp_epp_mode; + value[1] = self->channel_or_addr; + append_tuple(self,instruction,2,value); + break; + + case DATA_RATE: + temp = self->data_rate; + value[3] = (__u8)((temp >> 24) & 0x000000ff); + value[2] = (__u8)((temp >> 16) & 0x000000ff); + value[1] = (__u8)((temp >> 8) & 0x000000ff); + value[0] = (__u8)(temp & 0x000000ff); + append_tuple(self,instruction,4,value); + break; + +#if 0 + case PORT_NAME: + case FIXED_PORT_NAME: + temp = strlen(&self->port_name); + if(temp < 70){ + value = (__u8) (self->port_name); + append_tuple(self,instruction,temp,value); + } + break; +#endif + +/* TODO: control tuples for centronics emulation is not implemented */ +/* case IEEE1284_MODE: */ + + default: + DEBUG(0,"ircomm_append_ctrl:instruction(0x%02x)is not" + "implemented\n",instruction); + } + + +} + +static void ircomm_parse_control(struct ircomm_cb *self, + struct sk_buff *skb, + int type){ + + __u8 *data; + __u8 pi,pl,pv[64]; + int clen = 0; + int i,indicate,count = 0; + + + data = skb->data; + if(type == IAS_PARAM) + clen = ((data[count++] << 8) & data[count++]); /* MSB first */ + else /* CONTROL_CHANNEL */ + clen = data[count++]; + + + if(clen == 0){ + skb_pull( skb, 1); /* remove clen field */ + return; + } + + + + + while( count < clen ){ + /* + * parse controlparameters and set value into structure + */ + pi = data[count++]; + pl = data[count++]; + + DEBUG(0, "parse_control:instruction(0x%02x)\n",pi) ; + + + /* copy a tuple into pv[] */ + +#ifdef IRCOMM_DEBUG_TUPLE + printk("data:"); + for(i=0; i < pl; i++){ + pv[i] = data[count++]; + printk("%02x",pv[i]); + } + printk("\n"); +#else + for(i=0; i < pl; i++) + pv[i] = data[count++]; +#endif + + + /* parse pv */ + indicate = 0; + + switch(pi){ + + /* + * for 3-wire/9-wire/centronics + */ + + case SERVICETYPE: + self->peer_servicetype = pv[0]; + break; + case PORT_TYPE: + self->peer_port_type = pv[0]; + break; +#if 0 + case PORT_NAME: + self->peer_port_name = *pv; + break; + case FIXED_PORT_NAME: + self->peer_port_name = *pv; + /* + * We should not connect if user of IrCOMM can't + * recognize the port name + */ + self->port_name_critical = TRUE; + break; +#endif + case DATA_RATE: + self->peer_data_rate = (pv[3]<<24) & (pv[2]<<16) + & (pv[1]<<8) & pv[0]; + indicate = 1; + break; + case DATA_FORMAT: + self->peer_data_format = pv[0]; + break; + case FLOW_CONTROL: + self->peer_flow_ctrl = pv[0]; + indicate = 1; + break; + case XON_XOFF_CHAR: + self->peer_xon_char = pv[0]; + self->peer_xoff_char = pv[1]; + indicate = 1; + break; + case ENQ_ACK_CHAR: + self->peer_enq_char = pv[0]; + self->peer_ack_char = pv[1]; + indicate = 1; + break; + case LINESTATUS: + self->peer_line_status = pv[0]; + indicate = 1; + break; + case BREAK_SIGNAL: + self->peer_break_signal = pv[0]; + /* indicate = 1; */ + break; + + /* + * for 9-wire + */ + + case DTELINE_STATE: + if(self->null_modem_mode){ + /* input DTR as {DSR & CD & RI} */ + self->peer_dce = 0; + if(pv[0] & DELTA_DTR) + self->peer_dce |= DELTA_DSR|DELTA_RI|DELTA_DCD; + if(pv[0] & MCR_DTR) + self->peer_dce |= MSR_DSR|MSR_RI|MSR_DCD; + + /* rts as cts */ + if(pv[0] & DELTA_RTS) + self->peer_dce |= DELTA_CTS; + if(pv[0] & MCR_RTS) + self->peer_dce |= MSR_CTS; + }else{ + self->peer_dte = pv[0]; + } + indicate = 1; + break; + + case DCELINE_STATE: + self->peer_dce = pv[0]; + indicate = 1; + break; + + case POLL_FOR_LINE_SETTINGS: + ircomm_append_ctrl(self, DTELINE_STATE); + ircomm_control_request(self); + break; + + /* + * for centronics .... not implemented yet + */ +/* case STATUS_QUERY: */ +/* case SET_BUSY_TIMEOUT: */ +/* case IEEE1284_MODE_SUPPORT: */ +/* case IEEE1284_DEVICEID: */ +/* case IEEE1284_MODE: */ +/* case IEEE1284_ECP_EPP_DATA_TRANSFER: */ + + default: + DEBUG(0, "ircomm_parse_control:not implemented " + "instruction(%d)\n", pi); + break; + } + + if(indicate && self->notify.flow_indication + && type == CONTROL_CHANNEL){ + + DEBUG(0,"ircomm:parse_control:indicating..:\n"); + self->pi = pi; + if(self->notify.flow_indication) + self->notify.flow_indication(self->notify.instance, self, 0); + indicate = 0; + } + } + skb_pull( skb, 1+clen); + return; +} + +/* + * ---------------------------------------------------------------------- + * Function init_module(void) ,cleanup_module() + * + * Initializes the ircomm control structure + * These Function are called when you insmod / rmmod . + * ---------------------------------------------------------------------- + */ + +#ifdef MODULE + +int init_module(void) { + ircomm_init(); + + DEBUG( 4, "ircomm:init_module:done\n"); + return 0; +} + +void cleanup_module(void) +{ + ircomm_cleanup(); + DEBUG( 0, "ircomm_common:cleanup_module:done.\n"); +} + +#endif /* MODULE */ + +/************************************************************ + * proc stuff + ************************************************************/ + +#ifdef CONFIG_PROC_FS + +/* + * Function proc_ircomm_read (buf, start, offset, len, unused) + * + * this function is called if there is a access on /proc/irda/comm . + * + */ +int ircomm_proc_read(char *buf, char **start, off_t offset, + int len, int unused){ + int i, index; + + len = 0; + for (i=0; imagic != IRCOMM_MAGIC) { + len += sprintf(buf+len, "???\t"); + }else { + switch (ircomm[i]->servicetype) { + case UNKNOWN: + index = 0; + break; + case THREE_WIRE_RAW: + index = 1; + break; + case THREE_WIRE: + index = 2; + break; + case NINE_WIRE: + index = 3; + break; + case CENTRONICS: + index = 4; + break; + default: + index = 0; + break; + } + len += sprintf(buf+len, "service: %s\t", + ircommservicetype[index]); + if(index){ + len += sprintf(buf+len, "porttype: %s ", + ircommporttype[ircomm[i]->port_type]); + len += sprintf(buf+len, "state: %s ", + ircommstate[ircomm[i]->state]); + len += sprintf(buf+len, "user: %s ", + ircomm[i]->notify.name); + len += sprintf(buf+len, "nullmodem emulation: %s", + (ircomm[i]->null_modem_mode ? "yes":"no")); + } + } + len += sprintf(buf+len, "\n"); + } + return len; +} + + +#endif /* CONFIG_PROC_FS */ + diff --git a/net/irda/ircomm/irvtd.c b/net/irda/ircomm/irvtd.c new file mode 100644 index 000000000000..f58f18b749e5 --- /dev/null +++ b/net/irda/ircomm/irvtd.c @@ -0,0 +1,154 @@ +/********************************************************************* + * + * Filename: irvtd.c + * Version: + * Description: A virtual tty driver implementaion, + * which also may be called as "Port Emulation Entity" + * in IrCOMM specification. + * Status: Experimental. + * Author: Takahide Higuchi + * Source: irlpt.c + * + * Copyright (c) 1998, Takahide Higuchi, , + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * I, Takahide Higuchi, provide no warranty for any of this software. + * This material is provided "AS-IS" and at no charge. + * + ********************************************************************/ + +/* #include */ + +#include +#include + +#include +#include + +#include +#include + +struct irvtd_cb **irvtd = NULL; +extern struct ircomm_cb **ircomm; + +#if 0 +static char *rcsid = "$Id: irvtd.c,v 1.2 1998/09/27 08:37:04 takahide Exp $"; +#endif +static char *version = "IrVTD, $Revision: 1.2 $ $Date: 1998/09/27 08:37:04 $ (Takahide Higuchi)"; + + +/************************************************************ + * init & cleanup this module + ************************************************************/ + +/* + * Function init_module(void) + * + * Initializes the ircomm control structure + * This Function is called when you do insmod. + */ + +__initfunc(int irvtd_init(void)) +{ + int i; + + DEBUG( 4, "irvtd:init_module:\n"); + printk( KERN_INFO "%s\n", version); + + /* we allocate master array */ + + irvtd = (struct irvtd_cb **) kmalloc( sizeof(void *) * + COMM_MAX_TTY,GFP_KERNEL); + if ( irvtd == NULL) { + printk( KERN_WARNING "irvtd: Can't allocate array!\n"); + return -ENOMEM; + } + + memset( irvtd, 0, sizeof(void *) * COMM_MAX_TTY); + + + /* we initialize structure */ + + for (i=0; i < COMM_MAX_TTY; i++){ + irvtd[i] = kmalloc( sizeof(struct irvtd_cb), GFP_KERNEL); + if(irvtd[i] == NULL){ + printk(KERN_ERR "ircomm_open(): kmalloc failed!\n"); + return -ENOMEM; + } + + memset( irvtd[i], 0, sizeof(struct irvtd_cb)); + irvtd[i]->magic = IRVTD_MAGIC; + } + + /* + * initialize a "port emulation entity" + */ + + if(irvtd_register_ttydriver()){ + printk( KERN_WARNING "IrCOMM: Error in ircomm_register_device\n"); + return -ENODEV; + } + + + DEBUG( 4, "irvtd:init_module:done\n"); + return 0; +} + +void irvtd_cleanup(void) +{ + int i; + DEBUG( 4, "--> ircomm:cleanup_module\n"); + + /* + * free some resources + */ + if (irvtd) { + for (i=0; i\n"); +} + +#ifdef MODULE + +int init_module(void) +{ + irvtd_init(); + return 0; +} + + +/* + * Function ircomm_cleanup (void) + * This is called when you rmmod. + */ + +void cleanup_module(void) +{ + irvtd_cleanup(); +} + +#endif /* MODULE */ + + + diff --git a/net/irda/ircomm/irvtd_driver.c b/net/irda/ircomm/irvtd_driver.c new file mode 100644 index 000000000000..7738e3e786d0 --- /dev/null +++ b/net/irda/ircomm/irvtd_driver.c @@ -0,0 +1,1869 @@ +/********************************************************************* + * + * Filename: irvtd_driver.c + * Version: + * Description: An implementation of "port emulation entity" of IrCOMM + * Status: Experimental. + * Author: Takahide Higuchi + * Source: serial.c by Linus Torvalds + * isdn_tty.c by Fritz Elfert + * + * Copyright (c) 1998, Takahide Higuchi, , + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * I, Takahide Higuchi, provide no warranty for any of this software. + * This material is provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#define DO_RESTART +#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) + +static char *irvtd_ttyname = "irnine"; +struct tty_driver irvtd_drv, irvtd_callout_driver; +struct tty_struct *irvtd_table[COMM_MAX_TTY]; +struct termios *irvtd_termios[COMM_MAX_TTY]; +struct termios *irvtd_termios_locked[COMM_MAX_TTY]; +static int ircomm_vsd_refcount; +extern struct ircomm_cb **ircomm; +extern struct irvtd_cb **irvtd; + +/* + * prototypes + */ + +int irvtd_open(struct tty_struct *tty, struct file *filp); +void irvtd_close(struct tty_struct * tty, struct file * filp); +int irvtd_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count); +void irvtd_put_char(struct tty_struct *tty, unsigned char ch); +int irvtd_write_room(struct tty_struct *tty); +int irvtd_chars_in_buffer(struct tty_struct *tty); +int irvtd_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg); +void irvtd_set_termios(struct tty_struct *tty, struct termios * old); +void irvtd_throttle(struct tty_struct *tty); +void irvtd_unthrottle(struct tty_struct *tty); +void irvtd_stop(struct tty_struct *tty); +void irvtd_start(struct tty_struct *tty); +void irvtd_hangup(struct tty_struct *tty); +void irvtd_flush_buffer(struct tty_struct *tty); + +static void flush_txbuff(struct irvtd_cb *info); +static void change_speed(struct irvtd_cb *driver); +static void irvtd_write_to_tty( void *instance ); + +static void irvtd_break(struct tty_struct *tty, int break_state); +static void irvtd_send_xchar(struct tty_struct *tty, char ch); + +#if 0 +static char *rcsid = "$Id: irvtd_driver.c,v 1.13 1998/12/06 10:09:07 takahide Exp $"; +#endif + + + + +/* + * Function ircomm_register_device(void) + * we register "port emulation entity"(see IrCOMM specification) here + * as a tty device. + * it will be called when you insmod. + * ( This function derives from linux/drivers/char/serial.c ) + */ + +int irvtd_register_ttydriver(void){ + + DEBUG( 4, "-->irvtd_register_ttydriver\n"); + + /* setup virtual serial port device */ + + /* Initialize the tty_driver structure ,which is defined in + tty_driver.h */ + + memset(&irvtd_drv, 0, sizeof(struct tty_driver)); + irvtd_drv.magic = IRVTD_MAGIC; + irvtd_drv.name = irvtd_ttyname; + irvtd_drv.major = IRCOMM_MAJOR; + irvtd_drv.minor_start = IRVTD_MINOR; + irvtd_drv.num = COMM_MAX_TTY; + irvtd_drv.type = TTY_DRIVER_TYPE_SERIAL; /* see tty_driver.h */ + irvtd_drv.subtype = IRVTD_TYPE_NORMAL; /* private type */ + + /* + * see drivers/char/tty_io.c and termios(3) + */ + + irvtd_drv.init_termios = tty_std_termios; + irvtd_drv.init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + irvtd_drv.flags = TTY_DRIVER_REAL_RAW; /* see tty_driver.h */ + irvtd_drv.refcount = &ircomm_vsd_refcount; + + /* pointer to the tty data structures */ + + irvtd_drv.table = irvtd_table; + irvtd_drv.termios = irvtd_termios; + irvtd_drv.termios_locked = irvtd_termios_locked; + + /* + * Interface table from the kernel(tty driver) to the ircomm + * layer + */ + + irvtd_drv.open = irvtd_open; + irvtd_drv.close = irvtd_close; + irvtd_drv.write = irvtd_write; + irvtd_drv.put_char = irvtd_put_char; + irvtd_drv.flush_chars = irvtd_flush_chars; + irvtd_drv.write_room = irvtd_write_room; + irvtd_drv.chars_in_buffer = irvtd_chars_in_buffer; + irvtd_drv.flush_buffer = irvtd_flush_buffer; + irvtd_drv.ioctl = irvtd_ioctl; + irvtd_drv.throttle = irvtd_throttle; + irvtd_drv.unthrottle = irvtd_unthrottle; + irvtd_drv.set_termios = irvtd_set_termios; + irvtd_drv.stop = NULL; /* irvtd_stop; */ + irvtd_drv.start = NULL; /* irvtd_start; */ + irvtd_drv.hangup = irvtd_hangup; + + irvtd_drv.send_xchar = irvtd_send_xchar; + irvtd_drv.break_ctl = irvtd_break; + irvtd_drv.read_proc = NULL; + irvtd_drv.wait_until_sent = NULL; + + /* + * The callout device is just like normal device except for + * minor number and the subtype. + */ + + /* What is difference between callout device and normal device? */ + /* My system dosen't have /dev/cua??, so we don't need it? :{| */ + irvtd_callout_driver = irvtd_drv; + irvtd_callout_driver.name = "irninecua"; + irvtd_callout_driver.minor_start = IRVTD_CALLOUT_MINOR; + irvtd_callout_driver.subtype = IRVTD_TYPE_CALLOUT; + + + if (tty_register_driver(&irvtd_drv)){ + DEBUG(0,"IrCOMM:Couldn't register tty driver\n"); + return(1); + } + if (tty_register_driver(&irvtd_callout_driver)) + DEBUG(0,"IrCOMM:Couldn't register callout tty driver\n"); + + DEBUG( 4, "irvtd_register_ttydriver: done.\n"); + return(0); +} + + +/* + * Function irvtd_unregister_device(void) + * it will be called when you rmmod + */ + +void irvtd_unregister_ttydriver(void){ + + int err; + DEBUG( 4, "--> irvtd_unregister_device\n"); + + /* unregister tty device */ + + err = tty_unregister_driver(&irvtd_drv); + if (err) + printk("IrCOMM: failed to unregister vtd driver(%d)\n",err); + err = tty_unregister_driver(&irvtd_callout_driver); + if (err) + printk("IrCOMM: failed to unregister vtd_callout driver(%d)\n", err); + + DEBUG( 4, "irvtd_unregister_device -->\n"); + return; +} + + + +/* + * ---------------------------------------------------------------------- + * Routines for Virtual tty driver + * + * most of infomation is descrived in linux/tty_driver.h, but + * a function ircomm_receive() derives from receive_chars() which is + * in 2.0.30 kernel (driver/char/serial.c). + * if you want to understand them, please see related kernel source + * (and my comments :). + * ---------------------------------------------------------------------- + */ + +/* + * ---------------------------------------------------------------------- + * ircomm_receive_data() + * + * like interrupt handler in the serial.c,we receive data when + * ircomm_data_indication comes + * ---------------------------------------------------------------------- + */ + + + +/* + * irvtd_write_to_tty + * send incoming/queued data to tty + */ + +static void irvtd_write_to_tty( void *instance ){ + + int status, c, flag; + + struct sk_buff *skb; + struct irvtd_cb *driver = (struct irvtd_cb *)instance; + struct tty_struct *tty = driver->tty; + + /* does instance still exist ? should be checked */ + ASSERT(driver->magic == IRVTD_MAGIC, return;); + + if(driver->rx_disable ){ + DEBUG(0,__FUNCTION__"rx_disable is true:do_nothing..\n"); + return; + } + + skb = skb_dequeue(&driver->rxbuff); + ASSERT(skb != NULL, return;); /* there's nothing */ + IS_SKB(skb, return;); + +#ifdef IRVTD_DEBUG_RX + printk("received data:"); + { + int i; + for ( i=0;ilen;i++) + printk("%02x ", skb->data[i]); + printk("\n"); + } +#endif + + status = driver->comm->peer_line_status & driver->read_status_mask; + + /* + * FIXME: we must do ircomm_parse_ctrl() here, instead of + * ircomm_common.c!! + */ + + + /* + * if there are too many errors which make a character ignored, + * drop characters + */ + + if(status & driver->ignore_status_mask){ + DEBUG(0,__FUNCTION__":some error:ignore characters.\n"); + dev_kfree_skb(skb); + return; + } + + c = MIN(skb->len, (TTY_FLIPBUF_SIZE - tty->flip.count)); + DEBUG(4, __FUNCTION__"skb_len=%d, tty->flip.count=%d \n" + ,(int)skb->len, tty->flip.count); + + if (driver->comm->peer_break_signal ) { + driver->comm->peer_break_signal = 0; + DEBUG(0,"handling break....\n"); + + flag = TTY_BREAK; + if (driver->flags & IRVTD_ASYNC_SAK) + /* + * do_SAK() seems to be an implementation of the + * idea called "Secure Attention Key", + * which seems to be discribed in "Orange book". + * (which is published by U.S.military!!?? , + * see source of do_SAK()) + * + * but what kind of security do we need + * when we use infrared communication??? :p) + */ + do_SAK(tty); + }else if (status & LSR_PE) + flag = TTY_PARITY; + else if (status & LSR_FE) + flag = TTY_FRAME; + else if (status & LSR_OE) + flag = TTY_OVERRUN; + else + flag = TTY_NORMAL; + + if(c){ + DEBUG(0,"writing %d chars to tty\n",c); + memset(tty->flip.flag_buf_ptr, flag, c); + memcpy(tty->flip.char_buf_ptr, skb->data, c); + tty->flip.flag_buf_ptr += c; + tty->flip.char_buf_ptr += c; + tty->flip.count += c; + skb_pull(skb,c); + } + + if(skb->len == 0) + dev_kfree_skb(skb); + else + { + /* queue rest of data again */ + DEBUG(0,__FUNCTION__":retrying frame!\n"); + skb_queue_head( &driver->rxbuff, skb ); + } + + /* + * in order to optimize this routine, these two tasks should be + * queued in following order + * ( see run_task_queue() and queue_task() in tqueue.h + */ + if(skb_queue_len(&driver->rxbuff)) + /* let me try again! */ + queue_task(&driver->rx_tqueue, &tq_timer); + if(c) + /* read your buffer! */ + queue_task(&tty->flip.tqueue, &tq_timer); + + + if(skb_queue_len(&driver->rxbuff)< IRVTD_RX_QUEUE_LOW + && driver->ttp_stoprx){ + irttp_flow_request(driver->comm->tsap, FLOW_START); + driver->ttp_stoprx = 0; + } +} + +void irvtd_receive_data(void *instance, void *sap, struct sk_buff *skb){ + + struct irvtd_cb *driver = (struct irvtd_cb *)instance; + + ASSERT(driver != NULL, return;); + ASSERT(driver->magic == IRVTD_MAGIC, return;); + + /* queue incoming data and make bottom half handler ready */ + + skb_queue_tail( &driver->rxbuff, skb ); + if(skb_queue_len(&driver->rxbuff) == 1) + irvtd_write_to_tty(driver); + if(skb_queue_len(&driver->rxbuff) > IRVTD_RX_QUEUE_HIGH){ + irttp_flow_request(driver->comm->tsap, FLOW_STOP); + driver->ttp_stoprx = 1; + } + return; +} + +#if 0 +void irvtd_receive_data(void *instance, void *sap, struct sk_buff *skb){ + + int flag,status; + __u8 c; + struct tty_struct *tty; + struct irvtd_cb *driver = (struct irvtd_cb *)instance; + + ASSERT(driver != NULL, return;); + ASSERT(driver->magic == IRVTD_MAGIC, return;); + + if(driver->rx_disable ){ + DEBUG(0,__FUNCTION__"rx_disable is true:do nothing\n"); + return; + } + + tty = driver->tty; + status = driver->comm->peer_line_status & driver->read_status_mask; + + c = MIN(skb->len, (TTY_FLIPBUF_SIZE - tty->flip.count)); + DEBUG(0, __FUNCTION__"skb_len=%d, tty->flip.count=%d \n" + ,(int)skb->len, tty->flip.count); + +#ifdef IRVTD_DEBUG_RX + printk("received data:"); + { + int i; + for ( i=0;ilen;i++) + printk("%02x ", skb->data[i]); + printk("\n"); + } +#endif + + /* + * if there are too many errors which make a character ignored, + * drop characters + */ + + if(status & driver->ignore_status_mask){ + DEBUG(0,__FUNCTION__"I/O error:ignore characters.\n"); + dev_kfree_skb(skb, FREE_READ); + return; + } + + if (driver->comm->peer_break_signal ) { + driver->comm->peer_break_signal = 0; + DEBUG(0,"handling break....\n"); + + flag = TTY_BREAK; + if (driver->flags & IRVTD_ASYNC_SAK) + /* + * do_SAK() seems to be an implementation of the + * idea called "Secure Attention Key", + * which seems to be discribed in "Orange book". + * (which is published by U.S.military!!?? ) + * see source of do_SAK() but what is "Orange book"!? + */ + do_SAK(tty); + }else if (status & LSR_PE) + flag = TTY_PARITY; + else if (status & LSR_FE) + flag = TTY_FRAME; + else if (status & LSR_OE) + flag = TTY_OVERRUN; + else + flag = TTY_NORMAL; + + if(c){ + DEBUG(0,"writing %d chars to tty\n",c); + memset(tty->flip.flag_buf_ptr, flag, c); + memcpy(tty->flip.char_buf_ptr, skb->data, c); + tty->flip.flag_buf_ptr += c; + tty->flip.char_buf_ptr += c; + tty->flip.count += c; + skb_pull(skb,c); + queue_task_irq_off(&tty->flip.tqueue, &tq_timer); + } + if(skb->len >0) + DEBUG(0,__FUNCTION__":dropping frame!\n"); + dev_kfree_skb(skb, FREE_READ); + DEBUG(4,__FUNCTION__":done\n"); +} +#endif + +/* + * ---------------------------------------------------------------------- + * indication/confirmation handlers: + * they will be registerd in irvtd_startup() to know that we + * discovered (or we are discovered by) remote device. + * ---------------------------------------------------------------------- + */ + +/* this function is called whed ircomm_attach_cable succeed */ + +void irvtd_attached(struct ircomm_cb *comm){ + + ASSERT(comm != NULL, return;); + ASSERT(comm->magic == IRCOMM_MAGIC, return;); + + DEBUG(0,"irvtd_attached:sending connect_request" + " for servicetype(%d)..\n",comm->servicetype); + ircomm_connect_request(comm, SAR_DISABLE ); +} + + +/* + * irvtd_connect_confirm() + * ircomm_connect_request which we have send have succeed! + */ + +void irvtd_connect_confirm(void *instance, void *sap, struct qos_info *qos, + int max_sdu_size, struct sk_buff *skb){ + + struct irvtd_cb *driver = (struct irvtd_cb *)instance; + ASSERT(driver != NULL, return;); + ASSERT(driver->magic == IRVTD_MAGIC, return;); + + /* + * sending initial control parameters here + * + * TODO: it must be done in ircomm_connect_request() + */ +#if 1 + if(driver->comm->servicetype == THREE_WIRE_RAW) + return; /* do nothing */ + + ircomm_append_ctrl(driver->comm, SERVICETYPE); + /* ircomm_append_ctrl(self, DATA_RATE); */ + ircomm_append_ctrl(driver->comm, DATA_FORMAT); + ircomm_append_ctrl(driver->comm, FLOW_CONTROL); + ircomm_append_ctrl(driver->comm, XON_XOFF_CHAR); + /* ircomm_append_ctrl(driver->comm, ENQ_ACK_CHAR); */ + + switch(driver->comm->servicetype){ + case CENTRONICS: + break; + + case NINE_WIRE: + ircomm_append_ctrl(driver->comm, DTELINE_STATE); + break; + default: + } + ircomm_control_request(driver->comm); +#endif + + + wake_up_interruptible(&driver->open_wait); +} + +/* + * irvtd_connect_indication() + * we are discovered and being requested to connect by remote device ! + */ + +void irvtd_connect_indication(void *instance, void *sap, struct qos_info *qos, + int max_sdu_size, struct sk_buff *skb) +{ + + struct irvtd_cb *driver = (struct irvtd_cb *)instance; + struct ircomm_cb *comm = (struct ircomm_cb *)sap; + ASSERT(driver != NULL, return;); + ASSERT(driver->magic == IRVTD_MAGIC, return;); + ASSERT(comm != NULL, return;); + ASSERT(comm->magic == IRCOMM_MAGIC, return;); + + DEBUG(4,"irvtd_connect_indication:sending connect_response...\n"); + + /*TODO: connect_response should send initialcontrolparameters! TH*/ + + ircomm_connect_response(comm, NULL, SAR_DISABLE ); + + wake_up_interruptible(&driver->open_wait); +} + + + +void irvtd_disconnect_indication(void *instance, void *sap , LM_REASON reason, + struct sk_buff *skb){ + + struct irvtd_cb *driver = (struct irvtd_cb *)instance; + ASSERT(driver != NULL, return;); + ASSERT(driver->tty != NULL, return;); + ASSERT(driver->magic == IRVTD_MAGIC, return;); + + DEBUG(4,"irvtd_disconnect_indication:\n"); + tty_hangup(driver->tty); +} + +/* + * irvtd_control_indication + * + */ + + +void irvtd_control_indication(void *instance, void *sap, LOCAL_FLOW flow){ + + struct irvtd_cb *driver = (struct irvtd_cb *)instance; + __u8 pi; /* instruction of control channel */ + + ASSERT(driver != NULL, return;); + ASSERT(driver->magic == IRVTD_MAGIC, return;); + + DEBUG(0,"irvtd_control_indication:\n"); + + pi = driver->comm->pi; + + switch(pi){ + + case DCELINE_STATE: + driver->msr = driver->comm->peer_dce; + + if(driver->msr & (DELTA_CTS|DELTA_DSR|DELTA_RI|DELTA_DCD)){ + if(driver->msr & DELTA_CTS) + driver->icount.cts++; + if(driver->msr & DELTA_DSR) + driver->icount.dsr++; + if(driver->msr & DELTA_RI) + driver->icount.rng++; + if(driver->msr & DELTA_DCD) + driver->icount.dcd++; + wake_up_interruptible(&driver->delta_msr_wait); + } + + if ((driver->flags & IRVTD_ASYNC_CHECK_CD) && (driver->msr & DELTA_DCD)) { + + DEBUG(0,"CD now %s...\n", + (driver->msr & MSR_DCD) ? "on" : "off"); + + if (driver->msr & DELTA_DCD) + wake_up_interruptible(&driver->open_wait); + else if (!((driver->flags & IRVTD_ASYNC_CALLOUT_ACTIVE) && + (driver->flags & IRVTD_ASYNC_CALLOUT_NOHUP))) { + + DEBUG(0,"irvtd_control_indication:hangup..\n"); + tty_hangup(driver->tty); + } + } + + if (driver->comm->flow_ctrl & USE_CTS) { + if (driver->tty->hw_stopped) { + if (driver->msr & MSR_CTS) { + DEBUG(0,"CTS tx start...\n"); + + driver->cts_stoptx = 0; + driver->tty->hw_stopped = driver->ttp_stoptx; + /* + * replacement of + * rs_sched_event(info, RS_EVENT_WRITE_WAKEUP) + * in serial.c + */ + + if ((driver->tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + driver->tty->ldisc.write_wakeup) + (driver->tty->ldisc.write_wakeup)(driver->tty); + + wake_up_interruptible(&driver->tty->write_wait); + return; + } + } else { + if (!(driver->msr & MSR_CTS)) { + DEBUG(0,"CTS tx stop..."); + + driver->cts_stoptx = 1; + driver->tty->hw_stopped = 1; +/* driver->IER &= ~UART_IER_THRI; */ +/* serial_out(info, UART_IER, info->IER); */ + } + } + } + + + break; + + case TX_READY: + driver->ttp_stoptx = 0; + driver->tty->hw_stopped = driver->cts_stoptx; + + /* + * driver->tty->write_wait will keep asleep if + * our txbuff is not empty. + * so if we can really send a packet now, + * send it and then wake it up. + */ + + if(driver->cts_stoptx) + break; + + flush_txbuff(driver); + if ((driver->tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + driver->tty->ldisc.write_wakeup) + (driver->tty->ldisc.write_wakeup)(driver->tty); + break; + + case TX_BUSY: + driver->ttp_stoptx = driver->tty->hw_stopped = 1; + break; + default: + DEBUG(0,"irvtd:unknown control..\n"); + + } +} + + +/* + * ---------------------------------------------------------------------- + * irvtd_open() and friends + * + * + * ---------------------------------------------------------------------- + */ + + +static int irvtd_block_til_ready(struct tty_struct *tty, struct file * filp, + struct irvtd_cb *driver) +{ + + struct wait_queue wait = { current, NULL }; + int retval; + int do_clocal = 0; + + /* + * If the device is in the middle of being closed, then block + * (sleep) until it's done, and (when being woke up)then try again. + */ + + if (tty_hung_up_p(filp) || + (driver->flags & IRVTD_ASYNC_CLOSING)) { + if (driver->flags & IRVTD_ASYNC_CLOSING) + interruptible_sleep_on(&driver->close_wait); +#ifdef DO_RESTART + if (driver->flags & IRVTD_ASYNC_HUP_NOTIFY) + return -EAGAIN; + else + return -ERESTARTSYS; +#else + return -EAGAIN; +#endif + } + + /* + * If this is a callout device, then just make sure the normal + * device isn't being used. + */ + + if (tty->driver.subtype == IRVTD_TYPE_CALLOUT) { + if (driver->flags & IRVTD_ASYNC_NORMAL_ACTIVE) + return -EBUSY; + if ((driver->flags & IRVTD_ASYNC_CALLOUT_ACTIVE) && + (driver->flags & IRVTD_ASYNC_SESSION_LOCKOUT) && + (driver->session != current->session)) + return -EBUSY; + if ((driver->flags & IRVTD_ASYNC_CALLOUT_ACTIVE) && + (driver->flags & IRVTD_ASYNC_PGRP_LOCKOUT) && + (driver->pgrp != current->pgrp)) + return -EBUSY; + + driver->flags |= IRVTD_ASYNC_CALLOUT_ACTIVE; + return 0; + } + + /* + * If non-blocking mode is set, or the port is not enabled, + * then make the check up front and then exit. + */ + + if ((filp->f_flags & O_NONBLOCK) || + (tty->flags & (1 << TTY_IO_ERROR))) { + if (driver->flags & IRVTD_ASYNC_CALLOUT_ACTIVE) + return -EBUSY; + + driver->flags |= IRVTD_ASYNC_NORMAL_ACTIVE; + return 0; + } + + if (driver->flags & IRVTD_ASYNC_CALLOUT_ACTIVE) { + if (driver->normal_termios.c_cflag & CLOCAL) + do_clocal = 1; + } else { + if (tty->termios->c_cflag & CLOCAL) + do_clocal = 1; + } + + /* + * We wait until ircomm_connect_request() succeed or + * ircomm_connect_indication comes + * + * This is what is written in serial.c: + * "Block waiting for the carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, driver->count is dropped by one, so that + * rs_close() knows when to free things. We restore it upon + * exit, either normal or abnormal." + */ + + retval = 0; + add_wait_queue(&driver->open_wait, &wait); + + DEBUG(0,"block_til_ready before block: line%d, count = %d\n", + driver->line, driver->count); + + cli(); + if (!tty_hung_up_p(filp)) + driver->count--; + sti(); + driver->blocked_open++; + + + while (1) { + current->state = TASK_INTERRUPTIBLE; + + if (!(driver->flags & IRVTD_ASYNC_CALLOUT_ACTIVE) && + (driver->comm->state == COMM_CONN)){ + /* + * signal DTR and RTS + */ + driver->comm->dte = driver->mcr |= (MCR_DTR | MCR_RTS |DELTA_DTR|DELTA_RTS); + + ircomm_append_ctrl(driver->comm, DTELINE_STATE); + ircomm_control_request(driver->comm); + } + + if (tty_hung_up_p(filp) || + !(driver->flags & IRVTD_ASYNC_INITIALIZED)) { +#ifdef DO_RESTART + if (driver->flags & IRVTD_ASYNC_HUP_NOTIFY) + retval = -EAGAIN; + else + retval = -ERESTARTSYS; +#else + retval = -EAGAIN; +#endif + break; + } + + /* + * if clocal == 0 or received DCD or state become CONN,then break + */ + + if (!(driver->flags & IRVTD_ASYNC_CALLOUT_ACTIVE) && + !(driver->flags & IRVTD_ASYNC_CLOSING) && + (driver->comm->state == COMM_CONN) && + ( do_clocal || (driver->msr & MSR_DCD) ) + ) + break; + + if(signal_pending(current)){ + retval = -ERESTARTSYS; + break; + } + +#ifdef IRVTD_DEBUG_OPEN + printk(KERN_INFO"block_til_ready blocking:" + " ttys%d, count = %d\n", driver->line, driver->count); +#endif + schedule(); + } + + current->state = TASK_RUNNING; + remove_wait_queue(&driver->open_wait, &wait); + + if (!tty_hung_up_p(filp)) + driver->count++; + driver->blocked_open--; +#ifdef IRVTD_DEBUG_OPEN + printk("block_til_ready after blocking: ttys%d, count = %d\n", + driver->line, driver->count); +#endif + if (retval) + return retval; + driver->flags |= IRVTD_ASYNC_NORMAL_ACTIVE; + return 0; +} + +static void change_speed(struct irvtd_cb *driver){ + + unsigned cflag,cval; + + if (!driver->tty || !driver->tty->termios || !driver->comm) + return; + cflag = driver->tty->termios->c_cflag; + + + + /* + * change baud rate here. but not implemented now + */ + + + + + /* + * byte size and parity + */ + switch (cflag & CSIZE) { + case CS5: cval = 0x00; break; + case CS6: cval = 0x01; break; + case CS7: cval = 0x02; break; + case CS8: cval = 0x03; break; + default: cval = 0x00; break; /* too keep GCC shut... */ + } + if (cflag & CSTOPB) { /* use 2 stop bit mode */ + cval |= 0x04; + } + if (cflag & PARENB) + cval |= 0x08; + if (!(cflag & PARODD)) + cval |= 0x10; + + /* CTS flow control flag and modem status interrupts */ + + if (cflag & CRTSCTS) + driver->comm->flow_ctrl |= USE_CTS; + else + driver->comm->flow_ctrl |= ~USE_CTS; + + if (cflag & CLOCAL) + driver->flags &= ~IRVTD_ASYNC_CHECK_CD; + else + driver->flags |= IRVTD_ASYNC_CHECK_CD; + + /* + * Set up parity check flag + */ + + driver->read_status_mask = LSR_OE ; + if (I_INPCK(driver->tty)) + driver->read_status_mask |= LSR_FE | LSR_PE; + if (I_BRKINT(driver->tty) || I_PARMRK(driver->tty)) + driver->read_status_mask |= LSR_BI; + + driver->ignore_status_mask = 0; + + if (I_IGNBRK(driver->tty)) { + driver->ignore_status_mask |= LSR_BI; + driver->read_status_mask |= LSR_BI; + /* + * If we're ignore parity and break indicators, ignore + * overruns too. (For real raw support). + */ + if (I_IGNPAR(driver->tty)) { + driver->ignore_status_mask |= LSR_OE | \ + LSR_PE | LSR_FE; + driver->read_status_mask |= LSR_OE | \ + LSR_PE | LSR_FE; + } + } + driver->comm->data_format = cval; + ircomm_append_ctrl(driver->comm, DATA_FORMAT); + ircomm_append_ctrl(driver->comm, FLOW_CONTROL); + ircomm_control_request(driver->comm); + + /* output to IrCOMM here*/ +} + + + + +static int irvtd_startup(struct irvtd_cb *driver){ + + struct notify_t irvtd_notify; + + + DEBUG(4,"irvtd_startup:\n" ); + + /* + * initialize our tx/rx buffer + */ + + if(driver->flags & IRVTD_ASYNC_INITIALIZED) + return(0); + + skb_queue_head_init(&driver->rxbuff); + driver->rx_tqueue.data = driver; + driver->rx_tqueue.routine = irvtd_write_to_tty; + + if(!driver->txbuff){ + driver->txbuff = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE); + if (!driver->txbuff){ + DEBUG(0,"irvtd_open():alloc_skb failed!\n"); + return -ENOMEM; + } + + skb_reserve(driver->txbuff, COMM_HEADER_SIZE); + } + + irda_notify_init(&irvtd_notify); + irvtd_notify.data_indication = irvtd_receive_data; + irvtd_notify.connect_confirm = irvtd_connect_confirm; + irvtd_notify.connect_indication = irvtd_connect_indication; + irvtd_notify.disconnect_indication = irvtd_disconnect_indication; + irvtd_notify.flow_indication = irvtd_control_indication; + irvtd_notify.instance = driver; + strncpy( irvtd_notify.name, "irvtd", NOTIFY_MAX_NAME); + + /* + * register ourself as a service user of IrCOMM + * TODO: other servicetype(i.e. 3wire,3wireraw) + */ + + driver->comm = ircomm_attach_cable(NINE_WIRE, irvtd_notify, + irvtd_attached); + if(driver->comm == NULL) + return -ENODEV; + + /* + * TODO:we have to initialize control-channel here! + * i.e.set something into RTS,CTS and so on.... + */ + + if (driver->tty) + clear_bit(TTY_IO_ERROR, &driver->tty->flags); + + change_speed(driver); + + driver->flags |= IRVTD_ASYNC_INITIALIZED; + return 0; +} + + +int irvtd_open(struct tty_struct * tty, struct file * filp){ + + struct irvtd_cb *driver; + int retval; + int line; + + DEBUG(4, "irvtd_open():\n"); + + line = MINOR(tty->device) - tty->driver.minor_start; + if ((line <0) || (line >= COMM_MAX_TTY)) + return -ENODEV; + driver = irvtd[line]; + driver->line = line; + driver->count++; + + DEBUG(0, "irvtd_open : %s%d count %d\n", tty->driver.name, line, + driver->count); + + tty->driver_data = driver; + driver->tty = tty; + + + /* + * start up discovering process and ircomm_layer + */ + + retval = irvtd_startup(driver); + if (retval) + return retval; + MOD_INC_USE_COUNT; + + retval = irvtd_block_til_ready(tty, filp, driver); + if (retval){ + DEBUG(0,"irvtd_open returning after block_til_ready with %d\n", + retval); + return retval; + } + + if ((driver->count == 1) && driver->flags & IRVTD_ASYNC_SPLIT_TERMIOS){ + if(tty->driver.subtype == IRVTD_TYPE_NORMAL) + *tty->termios = driver->normal_termios; + else + *tty->termios = driver->callout_termios; + + change_speed(driver); + } + + driver->session = current->session; + driver->pgrp = current->pgrp; + driver->rx_disable = 0; + return (0); +} + + + + + +/* + * ---------------------------------------------------------------------- + * irvtd_close() and friends + * + * most of this function is stolen from serial.c + * ---------------------------------------------------------------------- + */ + + +static void irvtd_shutdown(struct irvtd_cb * driver) +{ + unsigned long flags; + + if (!(driver->flags & IRVTD_ASYNC_INITIALIZED)) + return; + + DEBUG(4,"irvtd_shutdown:\n"); + + /* + * This comment is written in serial.c: + * + * clear delta_msr_wait queue to avoid mem leaks: we may free the irq + * here so the queue might never be waken up + */ + wake_up_interruptible(&driver->delta_msr_wait); + + /* clear DTR and RTS */ + if (!driver->tty || (driver->tty->termios->c_cflag & HUPCL)) + driver->mcr &= ~(MCR_DTR|MCR_RTS); + + driver->comm->dte = driver->mcr; + ircomm_append_ctrl(driver->comm, DTELINE_STATE ); + ircomm_control_request(driver->comm); + + + save_flags(flags); cli(); /* Disable interrupts */ + + if (driver->tty) + set_bit(TTY_IO_ERROR, &driver->tty->flags); + + ircomm_detach_cable(driver->comm); + + /* + * Free the transmit buffer here + */ + if(driver->txbuff){ + dev_kfree_skb(driver->txbuff); /* is it OK?*/ + driver->txbuff = NULL; + } + + driver->flags &= ~IRVTD_ASYNC_INITIALIZED; + restore_flags(flags); +} + + + +void irvtd_close(struct tty_struct * tty, struct file * filp){ + + struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data; + int line; + unsigned long flags; + + DEBUG(0, "irvtd_close:refc(%d)\n",ircomm_vsd_refcount); + + ASSERT(driver != NULL, return;); + ASSERT(driver->magic == IRVTD_MAGIC, return;); + + save_flags(flags);cli(); + + /* + * tty_hung_up_p() is defined as + * " return(filp->f_op == &hung_up_tty_fops); " + * see driver/char/tty_io.c + */ + + if(tty_hung_up_p(filp)){ + MOD_DEC_USE_COUNT; + restore_flags(flags); + return; + } + + + line = MINOR(tty->device) - tty->driver.minor_start; + DEBUG(0, "irvtd_close : %s%d count %d\n", tty->driver.name, line, + driver->count); + + if ((tty->count == 1) && (driver->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. Driver->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * ircomm service layer won't be shutdown. + */ + printk(KERN_ERR"irvtd_close: bad serial port count;" + "tty->count is 1, but driver->count is %d\n", driver->count); + driver->count = 1; + } + if (--driver->count < 0) { + printk("irvtd_close: bad count for line%d: %d\n", + line, driver->count); + driver->count = 0; + } + + if (driver->count) { /* do nothing */ + MOD_DEC_USE_COUNT; + restore_flags(flags); + return; + } + + driver->flags |= IRVTD_ASYNC_CLOSING; + + /* + * Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + + if (driver->flags & IRVTD_ASYNC_NORMAL_ACTIVE) + driver->normal_termios = *tty->termios; + if (driver->flags & IRVTD_ASYNC_CALLOUT_ACTIVE) + driver->callout_termios = *tty->termios; + + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + tty->closing = 1; + if (driver->closing_wait != IRVTD_ASYNC_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, driver->closing_wait); + + /* + * Now we stop accepting input. + */ + + driver->rx_disable = TRUE; + + /* + * Now we flush our buffer.., and shutdown ircomm service layer + */ + + /* drop our tx/rx buffer */ + if (tty->driver.flush_buffer) + tty->driver.flush_buffer(tty); + + while(skb_queue_len(&driver->rxbuff)){ + struct sk_buff *skb; + skb = skb_dequeue( &driver->rxbuff); + dev_kfree_skb(skb); + } + + /* drop users buffer? */ + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + + + + tty->closing = 0; + driver->tty = NULL; + + /* + * ad-hoc coding: + * we wait 2 sec before ircomm_detach_cable so that + * irttp will send all contents of its queue + */ + +#if 0 + if (driver->blocked_open) { + if (driver->close_delay) { +#endif + + /* kill time */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(driver->close_delay + 2*HZ); +#if 0 + } + wake_up_interruptible(&driver->open_wait); + } +#endif + + driver->flags &= ~(IRVTD_ASYNC_NORMAL_ACTIVE| + IRVTD_ASYNC_CALLOUT_ACTIVE| + IRVTD_ASYNC_CLOSING); + wake_up_interruptible(&driver->close_wait); + + irvtd_shutdown(driver); + MOD_DEC_USE_COUNT; + restore_flags(flags); + DEBUG(4,"irvtd_close:done:refc(%d)\n",ircomm_vsd_refcount); +} + + + +/* + * ---------------------------------------------------------------------- + * irvtd_write() and friends + * This routine will be called when something data are passed from + * kernel or user. + * + * NOTE:I have stolen copy_from_user() from 2.0.30 kernel(linux/isdnif.h) + * to access user space of memory carefully. Thanks a lot!:) + * ---------------------------------------------------------------------- + */ + +int irvtd_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count){ + + struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data; + int c = 0; + int wrote = 0; + struct sk_buff *skb = NULL; + __u8 *frame; + + DEBUG(4, "irvtd_write():\n"); + + if (!tty || !driver->txbuff) + return 0; + + + + while(1){ + skb = driver->txbuff; + + c = MIN(count, (skb_tailroom(skb) - COMM_HEADER_SIZE)); + if (c <= 0) + break; + + /* write to the frame */ + + + frame = skb_put(skb,c); + if(from_user){ + copy_from_user(frame,buf,c); + } else + memcpy(frame, buf, c); + + /* flush the frame */ + irvtd_flush_chars(tty); + wrote += c; + count -= c; + } + return (wrote); +} + +/* + * ---------------------------------------------------------------------- + * irvtd_put_char() + * This routine is called by the kernel to pass a single character. + * If we exausted our buffer,we can ignore the character! + * ---------------------------------------------------------------------- + */ +void irvtd_put_char(struct tty_struct *tty, unsigned char ch){ + + __u8 *frame ; + struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data; + struct sk_buff *skb = driver->txbuff; + + ASSERT(tty->driver_data != NULL, return;); + + DEBUG(4, "irvtd_put_char:\n"); + if(!driver->txbuff) + return; + + DEBUG(4, "irvtd_put_char(0x%02x) skb_len(%d) MAX(%d):\n", + (int)ch ,(int)skb->len, + driver->comm->maxsdusize - COMM_HEADER_SIZE); + + /* append a character */ + + frame = skb_put(skb,1); + frame[0] = ch; + return; +} + +/* + * ---------------------------------------------------------------------- + * irvtd_flush_chars() and friend + * This routine will be called after a series of characters was written using + * irvtd_put_char().We have to send them down to IrCOMM. + * ---------------------------------------------------------------------- + */ + +static void flush_txbuff(struct irvtd_cb *driver){ + + struct sk_buff *skb = driver->txbuff; + struct tty_struct *tty = driver->tty; + ASSERT(tty != NULL, return;); + +#ifdef IRVTD_DEBUG_TX + printk("flush_txbuff:"); + { + int i; + for ( i=0;ilen;i++) + printk("%02x", skb->data[i]); + printk("\n"); + } +#else + DEBUG(4, "flush_txbuff:count(%d)\n",(int)skb->len); +#endif + + /* add "clen" field */ + skb_push(skb,1); + skb->data[0]=0; /* without control channel */ + + ircomm_data_request(driver->comm, driver->txbuff); + + /* allocate new frame */ + skb = driver->txbuff = dev_alloc_skb(driver->comm->max_txbuff_size); + if (skb == NULL){ + printk(KERN_ERR"flush_txbuff():alloc_skb failed!\n"); + } else { + skb_reserve(skb, COMM_HEADER_SIZE); + } + wake_up_interruptible(&driver->tty->write_wait); +} + +void irvtd_flush_chars(struct tty_struct *tty){ + + struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data; + if(!driver || driver->magic != IRVTD_MAGIC || !driver->txbuff){ + DEBUG(0,"irvtd_flush_chars:null structure:ignore\n"); + return; + } + DEBUG(4, "irvtd_flush_chars():\n"); + + while(tty->hw_stopped){ + DEBUG(4,"irvtd_flush_chars:hw_stopped:sleep..\n"); + tty_wait_until_sent(tty,0); + DEBUG(4,"irvtd_flush_chars:waken up!\n"); + if(!driver->txbuff->len) + return; + } + + flush_txbuff(driver); +} + + + + +/* + * ---------------------------------------------------------------------- + * irvtd_write_room() + * This routine returns the room that our buffer has now. + * + * NOTE: + * driver/char/n_tty.c drops a character(s) when this routine returns 0, + * and then linux will be frozen after a few minutes :( why? bug? + * ( I found this on linux-2.0.33 ) + * So this routine flushes a buffer if there is few room, TH + * ---------------------------------------------------------------------- + */ + +int irvtd_write_room(struct tty_struct *tty){ + + int ret; + struct sk_buff *skb = (struct sk_buff *)((struct irvtd_cb *) tty->driver_data)->txbuff; + + if(!skb){ + DEBUG(0,"irvtd_write_room:NULL skb\n"); + return(0); + } + + ret = skb_tailroom(skb) - COMM_HEADER_SIZE; + + if(ret < 0){ + DEBUG(0,"irvtd_write_room:error:room is %d!",ret); + ret = 0; + } + DEBUG(4, "irvtd_write_room:\n"); + DEBUG(4, "retval(%d)\n",ret); + + + /* flush buffer automatically to avoid kernel freeze :< */ + if(ret < 8) /* why 8? there's no reason :) */ + irvtd_flush_chars(tty); + + return(ret); +} + +/* + * ---------------------------------------------------------------------- + * irvtd_chars_in_buffer() + * This function returns how many characters which have not been sent yet + * are still in buffer. + * ---------------------------------------------------------------------- + */ + +int irvtd_chars_in_buffer(struct tty_struct *tty){ + + struct sk_buff *skb = + (struct sk_buff *) ((struct irvtd_cb *)tty->driver_data) ->txbuff; + DEBUG(4, "irvtd_chars_in_buffer()\n"); + + if(!skb){ + printk(KERN_ERR"irvtd_chars_in_buffer:NULL skb\n"); + return(0); + } + return (skb->len ); +} + +/* + * ---------------------------------------------------------------------- + * irvtd_break() + * routine which turns the break handling on or off + * ---------------------------------------------------------------------- + */ + +static void irvtd_break(struct tty_struct *tty, int break_state){ + + struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data; + unsigned long flags; + + DEBUG(0, __FUNCTION__"()\n"); + ASSERT(tty->driver_data != NULL, return;); + ASSERT(driver->magic == IRVTD_MAGIC, return;); + + save_flags(flags);cli(); + if (break_state == -1) + { + driver->comm->break_signal = 0x01; + ircomm_append_ctrl(driver->comm, BREAK_SIGNAL); + ircomm_control_request(driver->comm); + } + else + { + driver->comm->break_signal = 0x00; + ircomm_append_ctrl(driver->comm, BREAK_SIGNAL); + ircomm_control_request(driver->comm); + } + + restore_flags(flags); +} + +/* + * ---------------------------------------------------------------------- + * irvtd_ioctl() and friends + * This routine allows us to implement device-specific ioctl's. + * If passed ioctl number (i.e.cmd) is unknown one, we should return + * ENOIOCTLCMD. + * + * TODO: we can't use setserial on IrCOMM because some ioctls are not implemented. + * we should add some ioctls and make some tool which is resemble to setserial. + * ---------------------------------------------------------------------- + */ + +static int get_modem_info(struct irvtd_cb * driver, unsigned int *value) +{ + unsigned int result; + result = ((driver->mcr & MCR_RTS) ? TIOCM_RTS : 0) + | ((driver->mcr & MCR_DTR) ? TIOCM_DTR : 0) + | ((driver->msr & DELTA_DCD) ? TIOCM_CAR : 0) + | ((driver->msr & DELTA_RI) ? TIOCM_RNG : 0) + | ((driver->msr & DELTA_DSR) ? TIOCM_DSR : 0) + | ((driver->msr & DELTA_CTS) ? TIOCM_CTS : 0); + put_user(result,value); + return 0; +} + +static int set_modem_info(struct irvtd_cb * driver, unsigned int cmd, + unsigned int *value) +{ + int error; + unsigned int arg; + + error = get_user(arg, value); + if(error) + return error; + + switch (cmd) { + case TIOCMBIS: + if (arg & TIOCM_RTS) + driver->mcr |= MCR_RTS; + if (arg & TIOCM_DTR) + driver->mcr |= MCR_DTR; + break; + + case TIOCMBIC: + if (arg & TIOCM_RTS) + driver->mcr &= ~MCR_RTS; + if (arg & TIOCM_DTR) + driver->mcr &= ~MCR_DTR; + break; + + case TIOCMSET: + driver->mcr = ((driver->mcr & ~(MCR_RTS | MCR_DTR)) + | ((arg & TIOCM_RTS) ? MCR_RTS : 0) + | ((arg & TIOCM_DTR) ? MCR_DTR : 0)); + break; + + default: + return -EINVAL; + } + + driver->comm->dte = driver->mcr; + ircomm_append_ctrl(driver->comm, DTELINE_STATE ); + ircomm_control_request(driver->comm); + return 0; +} + +int irvtd_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg){ + + int error; + struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data; + + struct icounter_struct cnow; + struct icounter_struct *p_cuser; /* user space */ + + + DEBUG(4,"irvtd_ioctl:requested ioctl(0x%08x)\n",cmd); + +#ifdef IRVTD_DEBUG_IOCTL + { + /* kill time so that debug messages will come slowly */ + unsigned long flags; + save_flags(flags);cli(); + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + HZ/4; /*0.25sec*/ + schedule(); + restore_flags(flags); + } +#endif + + + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && + (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { + if (tty->flags & (1 << TTY_IO_ERROR)){ + DEBUG(0,"irvtd_ioctl:I/O error...\n"); + return -EIO; + } + } + + switch (cmd) { + + case TIOCMGET: + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(unsigned int)); + if (error) + return error; + return get_modem_info(driver, (unsigned int *) arg); + + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + return set_modem_info(driver, cmd, (unsigned int *) arg); +#if 0 + /* + * we wouldn't implement them since we don't use serial_struct + */ + case TIOCGSERIAL: + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(struct serial_struct)); + if (error) + return error; + return irvtd_get_serial_info(driver, + (struct serial_struct *) arg); + case TIOCSSERIAL: + error = verify_area(VERIFY_READ, (void *) arg, + sizeof(struct serial_struct)); + if (error) + return error; + return irvtd_set_serial_info(driver, + (struct serial_struct *) arg); + + + case TIOCSERGETLSR: /* Get line status register */ + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(unsigned int)); + if (error) + return error; + else + return get_lsr_info(driver, (unsigned int *) arg); +#endif + +/* + * I think we don't need them + */ +/* case TIOCSERCONFIG: */ + + +/* + * They cannot be implemented because we don't use async_struct + * which is defined in serial.h + */ + +/* case TIOCSERGSTRUCT: */ +/* error = verify_area(VERIFY_WRITE, (void *) arg, */ +/* sizeof(struct async_struct)); */ +/* if (error) */ +/* return error; */ +/* memcpy_tofs((struct async_struct *) arg, */ +/* driver, sizeof(struct async_struct)); */ +/* return 0; */ + +/* case TIOCSERGETMULTI: */ +/* error = verify_area(VERIFY_WRITE, (void *) arg, */ +/* sizeof(struct serial_multiport_struct)); */ +/* if (error) */ +/* return error; */ +/* return get_multiport_struct(driver, */ +/* (struct serial_multiport_struct *) arg); */ +/* case TIOCSERSETMULTI: */ +/* error = verify_area(VERIFY_READ, (void *) arg, */ +/* sizeof(struct serial_multiport_struct)); */ +/* if (error) */ +/* return error; */ +/* return set_multiport_struct(driver, */ +/* (struct serial_multiport_struct *) arg); */ + /* + * 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: + while (1) { + interruptible_sleep_on(&driver->delta_msr_wait); + /* see if a signal did it */ +/* if (current->signal & ~current->blocked) */ +/* return -ERESTARTSYS; */ + + if ( ((arg & TIOCM_RNG) && (driver->msr & DELTA_RI)) || + ((arg & TIOCM_DSR) && (driver->msr & DELTA_DSR)) || + ((arg & TIOCM_CD) && (driver->msr & DELTA_DCD)) || + ((arg & TIOCM_CTS) && (driver->msr & DELTA_CTS))) { + return 0; + } + } + /* NOTREACHED */ + + + case TIOCGICOUNT: + /* + * 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. + */ + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(struct icounter_struct)); + if (error) + return error; + cli(); + cnow = driver->icount; + sti(); + p_cuser = (struct icounter_struct *) arg; + put_user(cnow.cts, &p_cuser->cts); + put_user(cnow.dsr, &p_cuser->dsr); + put_user(cnow.rng, &p_cuser->rng); + put_user(cnow.dcd, &p_cuser->dcd); + return 0; + + + case TIOCGSERIAL: + case TIOCSSERIAL: + case TIOCSERGETLSR: + case TIOCSERCONFIG: + case TIOCSERGWILD: + case TIOCSERSWILD: + case TIOCSERGSTRUCT: + case TIOCSERGETMULTI: + case TIOCSERSETMULTI: + DEBUG(0,"irvtd_ioctl:sorry, ioctl(0x%08x)is not implemented\n",cmd); + return -ENOIOCTLCMD; /* ioctls which are imcompatible with serial.c */ + + case TCSETS: + case TCGETS: + case TCFLSH: + default: + return -ENOIOCTLCMD; /* ioctls which we must not touch */ + } + return 0; +} + + + +/* + * ---------------------------------------------------------------------- + * irvtd_set_termios() + * This is called when termios is changed. + * If things that changed is significant for us,(i.e. changing baud rate etc.) + * send something to peer device. + * ---------------------------------------------------------------------- + */ + +void irvtd_set_termios(struct tty_struct *tty, struct termios * old_termios){ + + struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data; + + ASSERT(driver != NULL,return;); + ASSERT(driver->magic == IRVTD_MAGIC ,return;); + + DEBUG(0, "irvtd_set_termios:\n"); + return; + + if((tty->termios->c_cflag == old_termios->c_cflag) && + (RELEVANT_IFLAG(tty->termios->c_iflag) + == RELEVANT_IFLAG(old_termios->c_iflag))) + return; + + change_speed(driver); + + if((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = driver->ttp_stoptx; + /* irvtd_start(tty); */ /* we don't need this */ + } +} + +/* + * ---------------------------------------------------------------------- + * irvtd_throttle,irvtd_unthrottle + * These routines will be called when we have to pause sending up data to tty. + * We use RTS virtual signal when servicetype is NINE_WIRE + * ---------------------------------------------------------------------- + */ + +static void irvtd_send_xchar(struct tty_struct *tty, char ch){ + + DEBUG(0, __FUNCTION__"():\n"); + irvtd_put_char(tty, ch); +} + +void irvtd_throttle(struct tty_struct *tty){ + struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data; + + DEBUG(0, "irvtd_throttle:\n"); + + if (I_IXOFF(tty)) + irvtd_put_char(tty, STOP_CHAR(tty)); + + driver->mcr &= ~MCR_RTS; + driver->mcr |= DELTA_RTS; + driver->comm->dte = driver->mcr; + ircomm_append_ctrl(driver->comm, DTELINE_STATE ); + ircomm_control_request(driver->comm); + irttp_flow_request(driver->comm->tsap, FLOW_STOP); +} + +void irvtd_unthrottle(struct tty_struct *tty){ + struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data; + DEBUG(0, "irvtd_unthrottle:\n"); + + if (I_IXOFF(tty)) + irvtd_put_char(tty, START_CHAR(tty)); + + driver->mcr |= (MCR_RTS|DELTA_RTS); + driver->comm->dte = driver->mcr; + ircomm_append_ctrl(driver->comm, DTELINE_STATE ); + ircomm_control_request(driver->comm); + irttp_flow_request(driver->comm->tsap, FLOW_START); +} + + +/* + * ------------------------------------------------------------ + * irvtd_stop() and irvtd_start() + * + * This routines are called before setting or resetting tty->stopped. + * They enable or disable an interrupt which means "transmitter-is-ready" + * in serial.c, but I think these routine are not necessary for us. + * ------------------------------------------------------------ + */ + +#if 0 +irvtd_stop(struct tty_struct *tty){ + DEBUG(0, "irvtd_stop()\n"); + + struct irvtd_cb *info = (struct irvtd_cb *)tty->driver_data; + DEBUG(0, "irvtd_start():not implemented!\n"); +} +irvtd_start(struct tty_struct *tty){ + + struct irvtd_cb *info = (struct irvtd_cb *)tty->driver_data; + DEBUG(0, "irvtd_start():not_implemented!\n"); +} +#endif + +/* + * ------------------------------------------------------------ + * irvtd_hangup() + * This routine notifies that tty layer have got HUP signal + * Is this routine right ? :{| + * ------------------------------------------------------------ + */ + +void irvtd_hangup(struct tty_struct *tty){ + + struct irvtd_cb *info = (struct irvtd_cb *)tty->driver_data; + DEBUG(0, "irvtd_hangup()\n"); + + irvtd_flush_buffer(tty); + irvtd_shutdown(info); + info->count = 0; + info->flags &= ~(IRVTD_ASYNC_NORMAL_ACTIVE|IRVTD_ASYNC_CALLOUT_ACTIVE); + info->tty = NULL; + wake_up_interruptible(&info->open_wait); +} + +void irvtd_flush_buffer(struct tty_struct *tty){ + + struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data; + struct sk_buff *skb; + + skb = (struct sk_buff *)driver->txbuff; + + DEBUG(4, "irvtd_flush_buffer:%d chars are gone..\n",(int)skb->len); + skb_trim(skb,0); + + /* write_wait is a wait queue of tty_wait_until_sent(). + * see tty_io.c of kernel + */ + wake_up_interruptible(&tty->write_wait); + + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); +} + + diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c new file mode 100644 index 000000000000..a7afc8f6e037 --- /dev/null +++ b/net/irda/irda_device.c @@ -0,0 +1,578 @@ +/********************************************************************* + * + * Filename: irda_device.c + * Version: + * Description: + * Status: Experimental. + * Author: Dag Brattli + * Created at: Wed Sep 2 20:22:08 1998 + * Modified at: Mon Dec 14 19:18:51 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +extern int irtty_init(void); +extern int pc87108_init(void); +extern int w83977af_init(void); +extern int esi_init(void); +extern int tekram_init(void); +extern int actisys_init(void); + +hashbin_t *irda_device = NULL; + +void irda_device_start_todo_timer( struct irda_device *self, int timeout); + +/* Netdevice functions */ +static int irda_device_net_rebuild_header(struct sk_buff *skb); +static int irda_device_net_hard_header(struct sk_buff *skb, + struct device *dev, + unsigned short type, void *daddr, + void *saddr, unsigned len); +static int irda_device_net_set_config( struct device *dev, struct ifmap *map); +static int irda_device_net_change_mtu( struct device *dev, int new_mtu); + +#ifdef CONFIG_PROC_FS +int irda_device_proc_read( char *buf, char **start, off_t offset, int len, + int unused); + +#endif /* CONFIG_PROC_FS */ + +__initfunc(int irda_device_init( void)) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + /* Allocate master array */ + irda_device = hashbin_new( HB_LOCAL); + if ( irda_device == NULL) { + printk( KERN_WARNING "IrDA: Can't allocate irda_device hashbin!\n"); + return -ENOMEM; + } + + /* + * Call the init function of the device drivers that has not been + * compiled as a module + */ +#ifdef CONFIG_IRTTY_SIR + irtty_init(); +#endif +#ifdef CONFIG_WINBOND_FIR + w83977af_init(); +#endif +#ifdef CONFIG_NSC_FIR + pc87108_init(); +#endif +#ifdef CONFIG_ESI_DONGLE + esi_init(); +#endif +#ifdef CONFIG_TEKRAM_DONGLE + tekram_init(); +#endif +#ifdef CONFIG_ACTISYS_DONGLE + actisys_init(); +#endif + + return 0; +} + +void irda_device_cleanup(void) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( irda_device != NULL, return;); + + hashbin_delete( irda_device, (FREE_FUNC) irda_device_close); +} + +/* + * Function irda_device_open (self) + * + * Open a new IrDA port device + * + */ +int irda_device_open( struct irda_device *self, char *name, void *priv) +{ + int result; + int i=0; + + DEBUG( 4, __FUNCTION__ "()\n"); + + /* Check that a minimum of allocation flags are specified */ + ASSERT(( self->rx_buff.flags & (GFP_KERNEL|GFP_ATOMIC)) != 0, + return -1;); + ASSERT(( self->tx_buff.flags & (GFP_KERNEL|GFP_ATOMIC)) != 0, + return -1;); + + ASSERT( self->tx_buff.truesize > 0, return -1;); + ASSERT( self->rx_buff.truesize > 0, return -1;); + + self->rx_buff.data = ( __u8 *) kmalloc( self->rx_buff.truesize, + self->rx_buff.flags); + self->tx_buff.data = ( __u8 *) kmalloc( self->tx_buff.truesize, + self->tx_buff.flags); + + if ( self->rx_buff.data == NULL || self->tx_buff.data == NULL) { + DEBUG( 0, "IrDA Self: no space for buffers!\n"); + irda_device_close( self); + return -ENOMEM; + } + + memset( self->rx_buff.data, 0, self->rx_buff.truesize); + memset( self->tx_buff.data, 0, self->tx_buff.truesize); + + self->magic = IRDA_DEVICE_MAGIC; + + self->rx_buff.in_frame = FALSE; + self->rx_buff.state = OUTSIDE_FRAME; + + /* Initialize timers */ + init_timer( &self->media_busy_timer); + + /* Open new IrLAP layer instance */ + self->irlap = irlap_open( self); + + /* A pointer to the low level implementation */ + self->priv = priv; + strncpy( self->name, name, 16); + + /* Initialize IrDA net device */ + do { + sprintf( self->name, "%s%d", "irda", i++); + } while ( dev_get( self->name) != NULL); + + self->netdev.name = self->name; + self->netdev.priv = (void *) self; + self->netdev.next = NULL; + + if (( result = register_netdev( &self->netdev)) != 0) { + DEBUG( 0, "IrDA Device, register_netdev() failed!\n"); + return -1; + } + + hashbin_insert( irda_device, (QUEUE *) self, (int) self, NULL); + + /* Open network device */ + dev_open( &self->netdev); + + printk( "IrDA irda_device %s registered.\n", self->name); + + irda_device_set_media_busy( self, FALSE); + + return 0; +} + +/* + * Function irda_device_close (self) + * + * Close this instance of the irda_device, just deallocate buffers + * + */ +void __irda_device_close( struct irda_device *self) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRDA_DEVICE_MAGIC, return;); + + dev_close( &self->netdev); + + /* Remove netdevice */ + unregister_netdev( &self->netdev); + + /* Stop timers */ + del_timer( &self->todo_timer); + del_timer( &self->media_busy_timer); + + if ( self->tx_buff.data) { + kfree( self->tx_buff.data); + } + + if ( self->rx_buff.data) { + kfree( self->rx_buff.data); + } + + self->magic = 0; +} + +/* + * Function irda_device_close (self) + * + * + * + */ +void irda_device_close( struct irda_device *self) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRDA_DEVICE_MAGIC, return;); + + /* Stop IrLAP */ + irlap_close( self->irlap); + self->irlap = NULL; + + hashbin_remove( irda_device, (int) self, NULL); + + __irda_device_close( self); +} + +/* + * Function irda_device_set_media_busy (self, status) + * + * Called when we have detected that another station is transmiting + * in contention mode. + */ +void irda_device_set_media_busy( struct irda_device *self, int status) +{ + DEBUG( 4, __FUNCTION__ "(%s)\n", status ? "TRUE" : "FALSE"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRDA_DEVICE_MAGIC, return;); + + if ( status) { + self->media_busy = TRUE; + irda_device_start_mbusy_timer( self); + DEBUG( 4, "Media busy!\n"); + } else { + self->media_busy = FALSE; + del_timer( &self->media_busy_timer); + } +} + +/* + * Function __irda_device_change_speed (self, speed) + * + * When this function is called, we will have a process context so its + * possible for us to sleep, wait or whatever :-) + */ +static void __irda_device_change_speed( struct irda_device *self, int speed) +{ + ASSERT( self != NULL, return;); + + if ( self->magic != IRDA_DEVICE_MAGIC) { + DEBUG( 0, __FUNCTION__ + "(), irda device is gone! Maybe you need to update " + "your irmanager and/or irattach!"); + + return; + } + + /* + * Is is possible to change speed yet? Wait until the last byte + * has been transmitted. + */ + if ( self->wait_until_sent) { + self->wait_until_sent( self); + + if ( self->change_speed) { + self->change_speed( self, speed); + + /* Update the QoS value only */ + self->qos.baud_rate.value = speed; + } + } else { + DEBUG( 0, __FUNCTION__ "(), Warning, wait_until_sent() " + "is not implemented by the irda_device!\n"); + + } +} + +/* + * Function irda_device_change_speed (self, speed) + * + * Change the speed of the currently used irda_device + * + */ +inline void irda_device_change_speed( struct irda_device *self, int speed) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRDA_DEVICE_MAGIC, return;); + + irda_execute_as_process( self, + (TODO_CALLBACK) __irda_device_change_speed, + speed); +} + +inline int irda_device_is_media_busy( struct irda_device *self) +{ + ASSERT( self != NULL, return FALSE;); + ASSERT( self->magic == IRDA_DEVICE_MAGIC, return FALSE;); + + return self->media_busy; +} + +inline int irda_device_is_receiving( struct irda_device *self) +{ + ASSERT( self != NULL, return FALSE;); + ASSERT( self->magic == IRDA_DEVICE_MAGIC, return FALSE;); + + if ( self->is_receiving) + return self->is_receiving( self); + else + return FALSE; +} + +inline struct qos_info *irda_device_get_qos( struct irda_device *self) +{ + ASSERT( self != NULL, return NULL;); + ASSERT( self->magic == IRDA_DEVICE_MAGIC, return NULL;); + + return &self->qos; +} + +void irda_device_todo_expired( unsigned long data) +{ + struct irda_device *self = ( struct irda_device *) data; + + DEBUG( 4, __FUNCTION__ "()\n"); + + /* Check that we still exist */ + if ( !self || self->magic != IRDA_DEVICE_MAGIC) { + return; + } + __irda_device_change_speed( self, self->new_speed); +} + +/* + * Function irda_device_start_todo_timer (self, timeout) + * + * Start todo timer. This function is used to delay execution of certain + * functions. Its implemented using timers since delaying a timer or a + * bottom halves function can be very difficult othervise. + * + */ +void irda_device_start_todo_timer( struct irda_device *self, int timeout) +{ + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRDA_DEVICE_MAGIC, return;); + + del_timer( &self->todo_timer); + + self->todo_timer.data = (unsigned long) self; + self->todo_timer.function = &irda_device_todo_expired; + self->todo_timer.expires = jiffies + timeout; + + add_timer( &self->todo_timer); +} + +static struct enet_statistics *irda_device_get_stats( struct device *dev) +{ + struct irda_device *priv = (struct irda_device *) dev->priv; + + return &priv->stats; +} + +/* + * Function irda_device_setup (dev) + * + * This function should be used by low level device drivers in a similar way + * as ether_setup() is used by normal network device drivers + */ +int irda_device_setup( struct device *dev) +{ + struct irda_device *self; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( dev != NULL, return -1;); + + self = (struct irda_device *) dev->priv; + + ASSERT( self != NULL, return -1;); + ASSERT( self->magic == IRDA_DEVICE_MAGIC, return -1;); + + dev->get_stats = irda_device_get_stats; + dev->rebuild_header = irda_device_net_rebuild_header; + dev->set_config = irda_device_net_set_config; + dev->change_mtu = irda_device_net_change_mtu; + dev->hard_header = irda_device_net_hard_header; + dev->hard_header_len = 0; + dev->addr_len = 0; + + dev->type = ARPHRD_IRDA; + dev->tx_queue_len = 10; /* Short queues in IrDA */ + + memcpy( dev->dev_addr, &self->irlap->saddr, 4); + memset( dev->broadcast, 0xff, 4); + + dev->mtu = 2048; + dev->tbusy = 1; + + dev_init_buffers( dev); + + dev->flags = 0; /* IFF_NOARP | IFF_POINTOPOINT; */ + + return 0; +} + +/* + * Function irda_device_net_rebuild_header (buff, dev, dst, skb) + * + * + * + */ +static int irda_device_net_rebuild_header( struct sk_buff *skb) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + return 0; +} + +static int irda_device_net_hard_header (struct sk_buff *skb, + struct device *dev, + unsigned short type, void *daddr, + void *saddr, unsigned len) +{ + DEBUG( 0, __FUNCTION__ "()\n"); + + skb->mac.raw = skb->data; + /* skb_push(skb,PPP_HARD_HDR_LEN); */ +/* return PPP_HARD_HDR_LEN; */ + + return 0; +} + +static int irda_device_net_set_config( struct device *dev, struct ifmap *map) +{ + DEBUG( 0, __FUNCTION__ "()\n"); + + return 0; +} + +static int irda_device_net_change_mtu( struct device *dev, int new_mtu) +{ + DEBUG( 0, __FUNCTION__ "()\n"); + + return 0; +} + +/* + * Function irda_device_transmit_finished (void) + * + * Check if there is still some frames in the transmit queue for this + * device + * + */ +int irda_device_txqueue_empty( struct irda_device *self) +{ + ASSERT( self != NULL, return -1;); + ASSERT( self->magic == IRDA_DEVICE_MAGIC, return -1;); + + /* FIXME: check if this is the right way of doing it? */ + if ( skb_queue_len( &self->netdev.qdisc->q)) + return FALSE; + + return TRUE; +} + +/* + * Function irda_get_mtt (skb) + * + * Utility function for getting the + * + */ +__inline__ int irda_get_mtt( struct sk_buff *skb) +{ + return ((struct irlap_skb_cb *)(skb->cb))->mtt; +} + +/* + * Function setup_dma (idev, buffer, count, mode) + * + * Setup the DMA channel + * + */ +void setup_dma( int channel, char *buffer, int count, int mode) +{ + unsigned long flags; + + save_flags(flags); + cli(); + + disable_dma( channel); + clear_dma_ff( channel); + set_dma_mode( channel, mode); + set_dma_addr( channel, virt_to_bus(buffer)); + set_dma_count( channel, count); + enable_dma( channel); + + restore_flags(flags); +} + +#ifdef CONFIG_PROC_FS +/* + * Function irlap_proc_read (buf, start, offset, len, unused) + * + * Give some info to the /proc file system + * + */ +int irda_device_proc_read( char *buf, char **start, off_t offset, int len, + int unused) +{ + struct irda_device *self; + unsigned long flags; + + save_flags(flags); + cli(); + + len = 0; + + self = (struct irda_device *) hashbin_get_first( irda_device); + while ( self != NULL) { + len += sprintf( buf+len, "Irda_Device name: %s\n", self->name); + len += sprintf( buf+len, " bps\tmaxtt\tdsize\twinsize\taddbofs\tmintt\tldisc\n"); + + len += sprintf( buf+len, " %d\t", + self->qos.baud_rate.value); + len += sprintf( buf+len, "%d\t", + self->qos.max_turn_time.value); + len += sprintf( buf+len, "%d\t", + self->qos.data_size.value); + len += sprintf( buf+len, "%d\t", + self->qos.window_size.value); + len += sprintf( buf+len, "%d\t", + self->qos.additional_bofs.value); + len += sprintf( buf+len, "%d\t", + self->qos.min_turn_time.value); + len += sprintf( buf+len, "%d", + self->qos.link_disc_time.value); + len += sprintf( buf+len, "\n"); + + self = (struct irda_device *) hashbin_get_next( irda_device); + } + restore_flags(flags); + + return len; +} + +#endif /* CONFIG_PROC_FS */ + diff --git a/net/irda/iriap.c b/net/irda/iriap.c new file mode 100644 index 000000000000..e2ee2c4ab74d --- /dev/null +++ b/net/irda/iriap.c @@ -0,0 +1,922 @@ +/********************************************************************* + * + * Filename: iriap.c + * Version: 0.1 + * Description: Information Access Protocol (IAP) + * Status: Experimental. + * Author: Dag Brattli + * Created at: Thu Aug 21 00:02:07 1997 + * Modified at: Wed Dec 9 02:19:23 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli , + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +hashbin_t *iriap = NULL; + +static struct iriap_cb *iriap_open( __u8 slsap, int mode); +static void __iriap_close( struct iriap_cb *self); +static void iriap_disconnect_indication( void *instance, void *sap, + LM_REASON reason, + struct sk_buff *skb); + +/* + * Function iriap_init (void) + * + * Initializes the IrIAP layer, called by the module initialization code + * in irmod.c + */ +int iriap_init(void) +{ + struct ias_object *obj; + + DEBUG( 4, "--> iriap_init\n"); + + /* Allocate master array */ + iriap = hashbin_new( HB_LOCAL); + if ( iriap == NULL) { + printk( KERN_WARNING "IrIAP: Can't allocate iriap hashbin!\n"); + return -ENOMEM; + } + + objects = hashbin_new( HB_LOCAL); + if ( objects == NULL) { + printk( KERN_WARNING + "IrIAP: Can't allocate objects hashbin!\n"); + return -ENOMEM; + } + + /* + * Register some default services for IrLMP + */ + irlmp_register_layer( S_COMPUTER, SERVER | CLIENT, FALSE, NULL); + irlmp_register_layer( S_PNP, SERVER, FALSE, NULL); + + /* + * Register the Device object with LM-IAS + */ + obj = irias_new_object( "Device", IAS_DEVICE_ID); + irias_add_string_attrib( obj, "DeviceName", "Linux"); + irias_insert_object( obj); + + /* + * Register server support with IrLMP so we can accept incoming + * connections + */ + iriap_open( LSAP_IAS, IAS_SERVER); + + DEBUG( 4, "iriap_init -->\n"); + + return 0; +} + +/* + * Function iriap_cleanup (void) + * + * Initializes the IrIAP layer, called by the module cleanup code in + * irmod.c + */ +void iriap_cleanup(void) +{ + DEBUG( 4, "--> iriap_cleanup\n"); + + irlmp_unregister_layer( S_COMPUTER, SERVER | CLIENT); + irlmp_unregister_layer( S_PNP, SERVER); + + hashbin_delete( iriap, (FREE_FUNC) __iriap_close); + hashbin_delete( objects, (FREE_FUNC) __irias_delete_object); + + DEBUG( 4, "iriap_cleanup -->\n"); +} + +/* + * Function iriap_open (void) + * + * Opens an instance of the IrIAP layer, and registers with IrLMP + */ +struct iriap_cb *iriap_open( __u8 slsap_sel, int mode) +{ + struct iriap_cb *self; + struct notify_t notify; + struct lsap_cb *lsap; + + DEBUG( 4, __FUNCTION__ "()\n"); + + self = kmalloc( sizeof(struct iriap_cb), GFP_ATOMIC); + if ( self == NULL) { + DEBUG( 0, "iriap_open(), Unable to kmalloc!\n"); + return NULL; + } + + /* + * Initialize instance + */ + memset( self, 0, sizeof(struct iriap_cb)); + + irda_notify_init( ¬ify); + notify.connect_confirm = iriap_connect_confirm; + notify.connect_indication = iriap_connect_indication; + notify.disconnect_indication = iriap_disconnect_indication; + notify.data_indication = iriap_data_indication; + notify.instance = self; + if ( mode == IAS_CLIENT) + strcpy( notify.name, "IrIAS cli"); + else + strcpy( notify.name, "IrIAS srv"); + + lsap = irlmp_open_lsap( slsap_sel, ¬ify); + if ( lsap == NULL) { + DEBUG( 0, "iriap_open: Unable to allocated LSAP!\n"); + return NULL; + } + DEBUG( 4, "iriap_register: source LSAP sel=%02x\n", slsap_sel); + + self->magic = IAS_MAGIC; + self->lsap = lsap; + self->slsap_sel = slsap_sel; + self->mode = mode; + + init_timer( &self->watchdog_timer); + + hashbin_insert( iriap, (QUEUE*) self, slsap_sel, NULL); + + iriap_next_client_state( self, S_DISCONNECT); + iriap_next_call_state( self, S_MAKE_CALL); + iriap_next_server_state( self, R_DISCONNECT); + iriap_next_r_connect_state( self, R_WAITING); + + return self; +} + +/* + * Function __iriap_close (self) + * + * Removes (deallocates) the IrIAP instance + * + */ +static void __iriap_close( struct iriap_cb *self) +{ + ASSERT( self != NULL, return;); + ASSERT( self->magic == IAS_MAGIC, return;); + + del_timer( &self->watchdog_timer); + + self->magic = 0; + + kfree( self); +} + +/* + * Function iriap_close (void) + * + * Closes IrIAP and deregisters with IrLMP + */ +void iriap_close( struct iriap_cb *self) +{ + DEBUG( 4, "iriap_close()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IAS_MAGIC, return;); + + if ( self->lsap) { + irlmp_close_lsap( self->lsap); + self->lsap = NULL; + } + + hashbin_remove( iriap, self->slsap_sel, NULL); + + __iriap_close( self); +} + +/* + * Function iriap_disconnect_indication (handle, reason) + * + * Got disconnect, so clean up everything assosiated with this connection + * + */ +void iriap_disconnect_indication( void *instance, void *sap, LM_REASON reason, + struct sk_buff *userdata) +{ + struct iriap_cb *self; + + DEBUG( 4, __FUNCTION__ "()\n"); + + self = (struct iriap_cb *) instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IAS_MAGIC, return;); + + ASSERT( iriap != NULL, return;); + + del_timer( &self->watchdog_timer); + + if ( self->mode == IAS_CLIENT) { + DEBUG( 4, __FUNCTION__ "(), disconnect as client\n"); + + /* Inform service user */ + if ( self->confirm) + self->confirm( 0, NULL, self->priv); + + iriap_do_client_event( self, IAP_LM_DISCONNECT_INDICATION, + NULL); + /* Close instance only if client */ + iriap_close( self); + + } else { + DEBUG( 4, __FUNCTION__ "(), disconnect as server\n"); + iriap_do_server_event( self, IAP_LM_DISCONNECT_INDICATION, + NULL); + } + + if ( userdata) { + dev_kfree_skb( userdata); + } +} + +/* + * Function iriap_disconnect_request (handle) + * + * + * + */ +void iriap_disconnect_request( struct iriap_cb *self) +{ + struct sk_buff *skb; + + DEBUG( 4, "iriap_disconnect_request()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IAS_MAGIC, return;); + + skb = dev_alloc_skb( 64); + if (skb == NULL) { + DEBUG( 0,"iriap_getvaluebyclass: " + "Could not allocate an sk_buff of length %d\n", 64); + return; + } + + /* + * Reserve space for MUX and LAP header + */ + skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER); + + irlmp_disconnect_request( self->lsap, skb); +} + +void iriap_getinfobasedetails_request(void) +{ + DEBUG( 0, __FUNCTION__ "(), Not implemented!\n"); +} + +void iriap_getinfobasedetails_confirm(void) +{ + DEBUG( 0, __FUNCTION__ "(), Not implemented!\n"); +} + +void iriap_getobjects_request(void) +{ + DEBUG( 0, __FUNCTION__ "(), Not implemented!\n"); +} + +void iriap_getobjects_confirm(void) +{ + DEBUG( 0, __FUNCTION__ "(), Not implemented!\n"); +} + +void iriap_getvalue(void) +{ + DEBUG( 0, __FUNCTION__ "(), Not implemented!\n"); +} + +/* + * Function iriap_getvaluebyclass (addr, name, attr) + * + * Retreive all values from attribute in all objects with given class + * name + */ +void iriap_getvaluebyclass_request( __u32 daddr, char *name, char *attr, + CONFIRM_CALLBACK callback, + void *priv) +{ + struct sk_buff *skb; + struct iriap_cb *self; + __u8 *frame; + int name_len, attr_len; + __u8 slsap = LSAP_ANY; /* Source LSAP to use */ + + DEBUG( 4, "iriap_getvaluebyclass_request()\n"); + + self = iriap_open( slsap, IAS_CLIENT); + if ( self == NULL) + return; + + self->mode = IAS_CLIENT; + self->confirm = callback; + self->priv = priv; + self->daddr = daddr; + + /* + * Save operation, so we know what the later indication is about + */ + self->operation = GET_VALUE_BY_CLASS; + + /* Give ourselves 7 secs to finish this operation */ + iriap_start_watchdog_timer( self, 700); + + skb = dev_alloc_skb( 64); + if (skb == NULL) { + DEBUG( 0,"iriap_getvaluebyclass: " + "Could not allocate an sk_buff of length %d\n", 64); + return; + } + + name_len = strlen( name); + attr_len = strlen( attr); + + /* Reserve space for MUX and LAP header */ + skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER); + skb_put( skb, 3+name_len+attr_len); + frame = skb->data; + + /* Build frame */ + frame[0] = LST | GET_VALUE_BY_CLASS; + frame[1] = name_len; /* Insert length of name */ + memcpy( frame+2, name, name_len); /* Insert name */ + frame[2+name_len] = attr_len; /* Insert length of attr */ + memcpy( frame+3+name_len, attr, attr_len); /* Insert attr */ + + iriap_do_client_event( self, IAP_CALL_REQUEST_GVBC, skb); +} + +/* + * Function iriap_getvaluebyclass_confirm (self, skb) + * + * Got result from GetValueByClass command. Parse it and return result + * to service user. + * + */ +void iriap_getvaluebyclass_confirm( struct iriap_cb *self, + struct sk_buff *skb) +{ + struct ias_value *value; + __u16 obj_id; + int len; + __u8 type; + int value_len; + __u8 *fp; + int n; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IAS_MAGIC, return;); + ASSERT( skb != NULL, return;); + + /* Initialize variables */ + fp = skb->data; + n = 2; + + /* Get length, MSB first */ + len = ntohs( *(__u16 *)( fp+n)); n += 2; + + DEBUG( 4, "iriap_getvaluebyclass_confirm: len=%d\n", len); + + /* Get object ID, MSB first */ + obj_id = ntohs( *(__u16 *)( fp+n)); n += 2; + + type = fp[n++]; + DEBUG( 4, __FUNCTION__ "(), Value type = %d\n", type); + + + switch( type) { + case IAS_INTEGER: + value = irias_new_integer_value( ntohl(*(__u32 *)(fp+n))); + /* + * Legal values restricted to 0x01-0x6f, page 15 irttp + */ + DEBUG( 4, "iriap_getvaluebyclass_confirm: lsap=%d\n", + value->t.integer); + break; + case IAS_STRING: + /* FIXME: check len of string, and if string is/should be + * null terminated? */ + ASSERT( fp[n++] == 0, return;); /* ASCII only! */ + value_len = fp[n++]; + DEBUG( 0, __FUNCTION__ "(), strlen=%d\n", value_len); + ASSERT( value_len < 64, return;); + + DEBUG( 0, "Got string %s\n", fp+n); + + value = irias_new_string_value( fp+n); + + break; + case IAS_OCT_SEQ: + value_len = ntohs( *(__u16 *)( fp+n)); n += 2; + + /* FIXME:should be 1024, but.... */ + DEBUG( 0, __FUNCTION__ "():octet sequence:len=%d\n", + value_len); + ASSERT(value_len <= 55, return;); + + value = irias_new_octseq_value( fp+n, value_len); + + break; + default: + value = &missing; + break; + } + + if ( self->confirm) + self->confirm(obj_id, value, self->priv); + + /* + * Finished, close connection! + */ + iriap_disconnect_request( self); +} + +/* + * Function iriap_getvaluebyclass_response () + * + * Send answer to getvaluebyclass_indication back to peer LM-IAS + * + */ +void iriap_getvaluebyclass_response( struct iriap_cb *self, + __u16 obj_id, + __u8 ret_code, + struct ias_value *value) +{ + struct sk_buff *skb; + __u8 *fp; + int n; + + DEBUG( 4, "iriap_getvaluebyclass_response()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IAS_MAGIC, return;); + + /* Initialize variables */ + n = 0; + + /* + * FIXME: adjust the size of the response after the length of the + * value + */ + skb = dev_alloc_skb( 64); + if (skb == NULL) { + DEBUG( 0, __FUNCTION__ "()," + "Could not allocate an skb of length %d\n", 64); + return; + } + + /* Reserve space for MUX and LAP header */ + skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER); + skb_put( skb, 6); + + fp = skb->data; + + /* Build frame */ + fp[n++] = GET_VALUE_BY_CLASS | LST; + fp[n++] = ret_code; + + /* Insert list length (MSB first) */ + *((__u16 *) (fp+n)) = __constant_htons( 0x0001); n += 2; + + /* Insert object identifier ( MSB first) */ + *((__u16 *) (fp+n)) = htons( obj_id); n += 2; + + switch( value->type) { + case IAS_STRING: + skb_put( skb, 3 + value->len); + fp[n++] = value->type; + fp[n++] = 0; /* ASCII */ + fp[n++] = (__u8) value->len; + memcpy( fp+n, value->t.string, value->len); n+=value->len; + break; + case IAS_INTEGER: + skb_put( skb, 5); + fp[n++] = value->type; + + *((__u32 *)(fp+n)) = htonl(value->t.integer); n+=4; + break; + case IAS_OCT_SEQ: + + /* FIXME: + * we can send only 55 octets at this time. + * we should be able to send 1024 octets. TH + */ + + ASSERT(value->len <= 55, return ;); + skb_put( skb, 3 + value->len); + fp[n++] = value->type; + *((__u16 *)(fp+n)) = htons(value->len); n+=2; + memcpy(fp+n, value->t.oct_seq, value->len); n+=value->len; + + break; + case IAS_MISSING: + DEBUG( 3, __FUNCTION__ ": sending IAS_MISSING\n"); + skb_put( skb, 1); + fp[n++] = value->type; + break; + + default: + DEBUG( 0, "iriap_getvaluebyclass_response: " + "type not implemented!\n"); + break; + } + iriap_do_r_connect_event( self, IAP_CALL_RESPONSE, skb); +} + +/* + * Function iriap_getvaluebyclass_indication (self, skb) + * + * getvaluebyclass is requested from peer LM-IAS + * + */ +void iriap_getvaluebyclass_indication( struct iriap_cb *self, + struct sk_buff *skb) +{ + __u8 *fp; + int n; + int name_len; + int attr_len; + char name[64]; + char attr[64]; + char both[128]; + struct ias_object *obj; + struct ias_attrib *attrib; + + DEBUG( 4, "iriap_getvaluebyclass_indication()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IAS_MAGIC, return;); + ASSERT( skb != NULL, return;); + + fp = skb->data; + n = 1; + + name_len = fp[n++]; + memcpy( name, fp+n, name_len); n+=name_len; + name[name_len] = '\0'; + + attr_len = fp[n++]; + memcpy( attr, fp+n, attr_len); n+=attr_len; + attr[attr_len] = '\0'; + + dev_kfree_skb( skb); + + /* + * Now, do some advanced parsing! :-) + */ + DEBUG( 9, "LM-IAS: Looking up %s: %s\n", name, attr); + + sprintf( both, "%s:%s", name, attr); + DEBUG( 0, "LM-IAS: looking for %s\n", both); + + obj = irias_find_object( name); + + if ( obj == NULL) { + DEBUG( 0, "LM-IAS: Object not found\n"); + iriap_getvaluebyclass_response( self, 0x1235, + IAS_CLASS_UNKNOWN, &missing); + return; + } + DEBUG( 0, "LM-IAS: found %s, id=%d\n", obj->name, obj->id); + + attrib = irias_find_attrib( obj, attr); + if ( attrib == NULL) { + DEBUG( 0, "LM-IAS: Attribute %s not found\n", attr); + iriap_getvaluebyclass_response( self, obj->id, + IAS_ATTRIB_UNKNOWN, &missing); + return; + } + + DEBUG( 0, "LM-IAS: found %s\n", attrib->name); + + /* + * We have a match; send the value. + */ + iriap_getvaluebyclass_response( self, obj->id, IAS_SUCCESS, + attrib->value); + + return; +} + +/* + * Function iriap_send_ack (void) + * + * + * + */ +void iriap_send_ack( struct iriap_cb *self) +{ + struct sk_buff *skb; + __u8 *frame; + + DEBUG( 6, "iriap_send_ack()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IAS_MAGIC, return;); + + skb = dev_alloc_skb( 64); + if (skb == NULL) { + DEBUG( 0, "iriap_send_ack: " + "Could not allocate an sk_buff of length %d\n", 64); + return; + } + + /* Reserve space for MUX and LAP header */ + skb_reserve( skb, 4); + skb_put( skb, 3); + frame = skb->data; + + /* Build frame */ + frame[0] = LST | self->operation; +} + +/* + * Function iriap_connect_confirm (handle, skb) + * + * LSAP connection confirmed! + * + */ +void iriap_connect_confirm( void *instance, void *sap, struct qos_info *qos, + int max_sdu_size, struct sk_buff *userdata) +{ + struct iriap_cb *self; + + self = ( struct iriap_cb *) instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IAS_MAGIC, return;); + ASSERT( userdata != NULL, return;); + + DEBUG( 4, "iriap_connect_confirm()\n"); + + del_timer( &self->watchdog_timer); + + iriap_do_client_event( self, IAP_LM_CONNECT_CONFIRM, userdata); +} + +/* + * Function iriap_connect_indication ( handle, skb) + * + * Remote LM-IAS is requesting connection + * + */ +void iriap_connect_indication( void *instance, void *sap, + struct qos_info *qos, int max_sdu_size, + struct sk_buff *userdata) +{ + struct iriap_cb *self; + + DEBUG( 4, "iriap_connect_indication()\n"); + + self = ( struct iriap_cb *) instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IAS_MAGIC, return;); + ASSERT( self->mode == IAS_SERVER, return;); + + iriap_do_server_event( self, IAP_LM_CONNECT_INDICATION, userdata); +} + +/* + * Function iriap_data_indication (handle, skb) + * + * Receives data from connection identified by handle from IrLMP + * + */ +void iriap_data_indication( void *instance, void *sap, struct sk_buff *skb) +{ + struct iriap_cb *self; + __u8 *frame; + __u8 opcode; + + DEBUG( 4, "iriap_data_indication()\n"); + + self = ( struct iriap_cb *) instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IAS_MAGIC, return;); + + ASSERT( skb != NULL, return;); + + frame = skb->data; + + if ( self->mode == IAS_SERVER) { + /* Call server */ + DEBUG( 4, __FUNCTION__ "(), Calling server!\n"); + iriap_do_r_connect_event( self, IAP_RECV_F_LST, skb); + + return; + } + opcode = frame[0]; + if ( ~opcode & 0x80) { + printk( KERN_ERR "IrIAS multiframe commands or results is " + "not implemented yet!\n"); + return; + } + + if ( ~opcode &0x40) { + DEBUG( 4, "Got ack frame!\n"); + /* return; */ + } + + opcode &= 0x7f; /* Mask away LST bit */ + + switch( opcode) { + case GET_INFO_BASE: + DEBUG( 0, "IrLMP GetInfoBaseDetails not implemented!\n"); + break; + case GET_VALUE_BY_CLASS: + DEBUG( 4,"IrLMP GetValueByClass\n"); + + if ( frame[1] == 0x01) { + printk( KERN_WARNING "IrIAP No such class!\n"); + } else if ( frame[1] == 0x02) { + printk( KERN_WARNING + "IrIAP No such attribute!\n"); + } else { + iriap_getvaluebyclass_confirm( self, skb); + } + iriap_do_call_event( self, IAP_RECV_F_LST, skb); + + /* + * We remove LSAPs used by IrIAS as a client since these + * are more difficult to reuse! + */ + iriap_close( self); + break; + default: + DEBUG( 0, "iriap_data_indication: Unknown op-code: %02x\n", + opcode); + break; + } +} + +/* + * Function iriap_call_indication (self, skb) + * + * Received call to server from peer LM-IAS + * + */ +void iriap_call_indication( struct iriap_cb *self, struct sk_buff *skb) +{ + __u8 *fp; + __u8 opcode; + + DEBUG( 4, "iriap_call_indication()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IAS_MAGIC, return;); + ASSERT( skb != NULL, return;); + + fp = skb->data; + + opcode = fp[0]; + if ( ~opcode & 0x80) { + printk( KERN_ERR "IrIAS multiframe commands or results is " + "not implemented yet!\n"); + return; + } + opcode &= 0x7f; /* Mask away LST bit */ + + switch( opcode) { + case GET_INFO_BASE: + DEBUG( 0, "IrLMP GetInfoBaseDetails not implemented!\n"); + break; + case GET_VALUE_BY_CLASS: + iriap_getvaluebyclass_indication( self, skb); + break; + } +} + +void iriap_watchdog_timer_expired( unsigned long data) +{ + struct iriap_cb *self = ( struct iriap_cb *) data; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IAS_MAGIC, return;); + + DEBUG( 0, __FUNCTION__ "() Timeout! closing myself!\n"); + iriap_close( self); +} + +#ifdef CONFIG_PROC_FS + +static char *ias_value_types[] = { + "IAS_MISSING", + "IAS_INTEGER", + "IAS_OCT_SEQ", + "IAS_STRING" +}; + +/* FIXME: This one should go in irlmp.c */ +static char *ias_charset_types[] = { + "CS_ASCII", + "CS_ISO_8859_1", + "CS_ISO_8859_2", + "CS_ISO_8859_3", + "CS_ISO_8859_4", + "CS_ISO_8859_5", + "CS_ISO_8859_6", + "CS_ISO_8859_7", + "CS_ISO_8859_8", + "CS_ISO_8859_9", + "CS_UNICODE" +}; + +int irias_proc_read( char *buf, char **start, off_t offset, int len, + int unused) +{ + struct ias_object *obj; + struct ias_attrib *attrib; + unsigned long flags; + + ASSERT( objects != NULL, return 0;); + + save_flags( flags); + cli(); + + len = 0; + + len += sprintf( buf+len, "LM-IAS Objects:\n"); + + /* List all objects */ + obj = (struct ias_object *) hashbin_get_first( objects); + while ( obj != NULL) { + ASSERT( obj->magic == IAS_OBJECT_MAGIC, return 0;); + + len += sprintf( buf+len, "name: %s, ", obj->name); + len += sprintf( buf+len, "id=%d", obj->id); + len += sprintf( buf+len, "\n"); + + /* List all attributes for this object */ + attrib = (struct ias_attrib *) + hashbin_get_first( obj->attribs); + while ( attrib != NULL) { + ASSERT( attrib->magic == IAS_ATTRIB_MAGIC, return 0;); + + len += sprintf( buf+len, " - Attribute name: \"%s\", ", + attrib->name); + len += sprintf( buf+len, "value[%s]: ", + ias_value_types[ attrib->value->type]); + + switch( attrib->value->type) { + case IAS_INTEGER: + len += sprintf( buf+len, "%d\n", + attrib->value->t.integer); + break; + case IAS_STRING: + len += sprintf( buf+len, "\"%s\"\n", + attrib->value->t.string); + break; + case IAS_OCT_SEQ: + len += sprintf( buf+len, "octet sequence\n"); + break; + case IAS_MISSING: + len += sprintf( buf+len, "missing\n"); + break; + default: + DEBUG( 0, __FUNCTION__ + "(), Unknown value type!\n"); + return -1; + } + len += sprintf( buf+len, "\n"); + + attrib = ( struct ias_attrib *) + hashbin_get_next( obj->attribs); + } + obj = ( struct ias_object *) hashbin_get_next( objects); + } + restore_flags( flags); + + return len; +} + +#endif /* PROC_FS */ diff --git a/net/irda/iriap_event.c b/net/irda/iriap_event.c new file mode 100644 index 000000000000..c0ba0058e224 --- /dev/null +++ b/net/irda/iriap_event.c @@ -0,0 +1,529 @@ +/********************************************************************* + * + * Filename: iriap_event.c + * Version: 0.1 + * Description: IAP Finite State Machine + * Status: Experimental. + * Author: Dag Brattli + * Created at: Thu Aug 21 00:02:07 1997 + * Modified at: Wed Dec 9 02:20:02 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1997 Dag Brattli , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include +#include +#include + +static void state_s_disconnect ( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb); +static void state_s_connecting ( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb); +static void state_s_call ( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb); + +static void state_s_make_call ( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb); +static void state_s_calling ( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb); +static void state_s_outstanding ( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb); +static void state_s_replying ( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb); +static void state_s_wait_for_call( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb); +static void state_s_wait_active ( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb); + +static void state_r_disconnect ( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb); +static void state_r_call ( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb); +static void state_r_waiting ( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb); +static void state_r_wait_active ( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb); +static void state_r_receiving ( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb); +static void state_r_execute ( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb); +static void state_r_returning ( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb); + +static void (*iriap_state[])( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb) = { + /* Client FSM */ + state_s_disconnect, + state_s_connecting, + state_s_call, + + /* S-Call FSM */ + state_s_make_call, + state_s_calling, + state_s_outstanding, + state_s_replying, + state_s_wait_for_call, + state_s_wait_active, + + /* Server FSM */ + state_r_disconnect, + state_r_call, + + /* R-Connect FSM */ + state_r_waiting, + state_r_wait_active, + state_r_receiving, + state_r_execute, + state_r_returning, +}; + +void iriap_next_client_state( struct iriap_cb *self, IRIAP_STATE state) +{ + ASSERT( self != NULL, return;); + ASSERT( self->magic == IAS_MAGIC, return;); + + switch ( state) { + /* case S_DISCONNECT: DEBUG( 0, "IAP Client = S_DISCONNECT\n"); break; */ +/* case S_CONNECTING: DEBUG( 0, "IAP Client = S_CONNECTING\n"); break; */ +/* case S_CALL: DEBUG( 0, "IAP Client = S_CALL\n"); break; */ + default: + break; + } + self->client_state = state; +} + +void iriap_next_call_state( struct iriap_cb *self, IRIAP_STATE state) +{ + ASSERT( self != NULL, return;); + ASSERT( self->magic == IAS_MAGIC, return;); + +/* switch ( state) { */ +/* case S_MAKE_CALL: DEBUG( 0, "IAP Call = S_MAKE_CALL\n"); break; */ +/* case S_CALLING: DEBUG( 0, "IAP Call = S_CALLING\n"); break; */ +/* case S_OUTSTANDING: DEBUG( 0, "IAP Call = S_OUTSTANDING\n");break; */ +/* case S_REPLYING: DEBUG( 0, "IAP Call = S_REPLYING\n"); break; */ +/* case S_WAIT_FOR_CALL: DEBUG( 0, "IAP Call = S_WAIT_FOR_CALL\n"); break; */ +/* case S_WAIT_ACTIVE: DEBUG( 0, "IAP Call = S_WAIT_ACTIVE\n"); break; */ +/* default: */ +/* break; */ +/* } */ + self->call_state = state; +} + +void iriap_next_server_state( struct iriap_cb *self, IRIAP_STATE state) +{ + ASSERT( self != NULL, return;); + ASSERT( self->magic == IAS_MAGIC, return;); + + self->server_state = state; +} + +void iriap_next_r_connect_state( struct iriap_cb *self, IRIAP_STATE state) +{ + ASSERT( self != NULL, return;); + ASSERT( self->magic == IAS_MAGIC, return;); + + self->r_connect_state = state; +} + +void iriap_do_client_event( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb) +{ + ASSERT( self != NULL, return;); + ASSERT( self->magic == IAS_MAGIC, return;); + + (*iriap_state[ self->client_state]) ( self, event, skb); +} + +void iriap_do_call_event( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb) +{ + ASSERT( self != NULL, return;); + ASSERT( self->magic == IAS_MAGIC, return;); + + (*iriap_state[ self->call_state]) ( self, event, skb); +} + +void iriap_do_server_event( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb) +{ + ASSERT( self != NULL, return;); + ASSERT( self->magic == IAS_MAGIC, return;); + + (*iriap_state[ self->server_state]) ( self, event, skb); +} + +void iriap_do_r_connect_event( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb) +{ + ASSERT( self != NULL, return;); + ASSERT( self->magic == IAS_MAGIC, return;); + + (*iriap_state[ self->r_connect_state]) ( self, event, skb); +} + + +/* + * Function state_s_disconnect (event, skb) + * + * S-Disconnect, The device has no LSAP connection to a particular + * remote device. + */ +static void state_s_disconnect( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb) +{ + ASSERT( self != NULL, return;); + ASSERT( self->magic == IAS_MAGIC, return;); + + switch( event) { + case IAP_CALL_REQUEST_GVBC: + iriap_next_client_state( self, S_CONNECTING); + self->skb = skb; + irlmp_connect_request( self->lsap, LSAP_IAS, self->daddr, + NULL, NULL); + break; + case IAP_LM_DISCONNECT_INDICATION: + break; + default: + DEBUG( 0, "state_s_disconnect: Unknown event %d\n", event); + break; + } +} + +/* + * Function state_s_connecting (self, event, skb) + * + * S-Connecting + * + */ +static void state_s_connecting( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb) +{ + ASSERT( self != NULL, return;); + ASSERT( self->magic == IAS_MAGIC, return;); + + switch( event) { + case IAP_LM_CONNECT_CONFIRM: + /* + * Jump to S-Call FSM + */ + iriap_do_call_event( self, IAP_CALL_REQUEST, skb); + /* iriap_call_request( self, 0,0,0); */ + iriap_next_client_state( self, S_CALL); + break; + case IAP_LM_DISCONNECT_INDICATION: + /* Abort calls */ + iriap_next_call_state( self, S_MAKE_CALL); + iriap_next_client_state( self, S_DISCONNECT); + break; + default: + DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event); + break; + } +} + +/* + * Function state_s_call (self, event, skb) + * + * S-Call, The device can process calls to a specific remote + * device. Whenever the LSAP connection is disconnected, this state + * catches that event and clears up + */ +static void state_s_call( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb) +{ + ASSERT( self != NULL, return;); + + switch( event) { + case IAP_LM_DISCONNECT_INDICATION: + /* Abort calls */ + iriap_next_call_state( self, S_MAKE_CALL); + iriap_next_client_state( self, S_DISCONNECT); + break; + default: + DEBUG( 0, "state_s_call: Unknown event %d\n", event); + break; + } +} + +/* + * Function state_s_make_call (event, skb) + * + * S-Make-Call + * + */ +static void state_s_make_call( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb) +{ + ASSERT( self != NULL, return;); + + switch( event) { + case IAP_CALL_REQUEST: + irlmp_data_request( self->lsap, self->skb); + iriap_next_call_state( self, S_OUTSTANDING); + break; + default: + DEBUG( 0, "state_s_make_call: Unknown event %d\n", event); + break; + } + if ( skb) { + dev_kfree_skb( skb); + } +} + +/* + * Function state_s_calling (event, skb) + * + * S-Calling + * + */ +static void state_s_calling( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb) +{ + DEBUG( 0, __FUNCTION__ "(), Not implemented\n"); +} + +/* + * Function state_s_outstanding (event, skb) + * + * S-Outstanding, The device is waiting for a response to a command + * + */ +static void state_s_outstanding( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb) +{ + ASSERT( self != NULL, return;); + + switch( event) { + case IAP_RECV_F_LST: + iriap_send_ack( self); + /*LM_Idle_request(idle); */ + + dev_kfree_skb( skb); + iriap_next_call_state( self, S_WAIT_FOR_CALL); + break; + default: + DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event); + break; + } +} + +/* + * Function state_s_replying (event, skb) + * + * S-Replying, The device is collecting a multiple part response + */ +static void state_s_replying( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb) +{ + DEBUG( 0, __FUNCTION__ "(), Not implemented\n"); +} + +/* + * Function state_s_wait_for_call (event, skb) + * + * S-Wait-for-Call + * + */ +static void state_s_wait_for_call( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb) +{ + DEBUG( 0, __FUNCTION__ "(), Not implemented\n"); +} + + +/* + * Function state_s_wait_active (event, skb) + * + * S-Wait-Active + * + */ +static void state_s_wait_active( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb) +{ + DEBUG( 0, __FUNCTION__ "(), Not implemented\n"); +} + +/************************************************************************** + * + * Server FSM + * + **************************************************************************/ + +/* + * Function state_r_disconnect (self, event, skb) + * + * LM-IAS server is disconnected (not processing any requests!) + * + */ +static void state_r_disconnect( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb) +{ + struct sk_buff *tx_skb; + + switch( event) { + case IAP_LM_CONNECT_INDICATION: + tx_skb = dev_alloc_skb( 64); + if ( tx_skb == NULL) { + DEBUG( 0,"state_r_disconnect: " + "Could not allocate an sk_buff of length %d\n", + 64); + return; + } + + /* Reserve space for MUX_CONTROL and LAP header */ + skb_reserve( tx_skb, LMP_CONTROL_HEADER+LAP_HEADER); + + irlmp_connect_response( self->lsap, tx_skb); + /*LM_Idle_request(idle); */ + + iriap_next_server_state( self, R_CALL); + + /* + * Jump to R-Connect FSM, we skip R-Waiting since we do not + * care about LM_Idle_request()! + */ + iriap_next_r_connect_state( self, R_RECEIVING); + + if (skb) + dev_kfree_skb( skb); + + break; + default: + DEBUG( 0, "state_r_disconnect: Unknown event %d\n", event); + break; + } +} + +/* + * Function state_r_call (self, event, skb) + * + * + * + */ +static void state_r_call( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb) +{ + DEBUG( 4, "state_r_call()\n"); + + switch( event) { + case IAP_LM_DISCONNECT_INDICATION: + /* Abort call */ + iriap_next_server_state( self, R_DISCONNECT); + iriap_next_r_connect_state( self, R_WAITING); + + break; + default: + DEBUG( 0, "state_r_call, unknown event!\n"); + break; + } +} + +/* + * R-Connect FSM +*/ + +/* + * Function state_r_waiting (self, event, skb) + * + * + * + */ +static void state_r_waiting( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb) +{ + DEBUG( 0, __FUNCTION__ "(), Not implemented\n"); +} + +static void state_r_wait_active( struct iriap_cb *self, + IRIAP_EVENT event, struct sk_buff *skb) +{ + DEBUG( 0, __FUNCTION__ "(), Not implemented\n"); +} + +/* + * Function state_r_receiving (self, event, skb) + * + * We are receiving a command + * + */ +static void state_r_receiving( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + switch( event) { + case IAP_RECV_F_LST: + iriap_next_r_connect_state( self, R_EXECUTE); + + iriap_call_indication( self, skb); + break; + default: + DEBUG( 0, __FUNCTION__ "(), unknown event!\n"); + break; + } + +} + +/* + * Function state_r_execute (self, event, skb) + * + * The server is processing the request + * + */ +static void state_r_execute( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( skb != NULL, return;); + + if ( !self || self->magic != IAS_MAGIC) { + DEBUG( 0, "state_r_execute: bad pointer self\n"); + return; + } + + switch( event) { + case IAP_CALL_RESPONSE: + /* + * Since we don't implement the Waiting state, we return + * to state Receiving instead, DB. + */ + iriap_next_r_connect_state( self, R_RECEIVING); + + irlmp_data_request( self->lsap, skb); + break; + default: + DEBUG( 0, __FUNCTION__ "(), unknown event!\n"); + break; + } +} + +static void state_r_returning( struct iriap_cb *self, IRIAP_EVENT event, + struct sk_buff *skb) +{ + DEBUG( 0, __FUNCTION__ "(), event=%d\n", event); + + switch( event) { + case IAP_RECV_F_LST: + + break; + default: + break; + } +} + + + diff --git a/net/irda/irias_object.c b/net/irda/irias_object.c new file mode 100644 index 000000000000..41d5c660b552 --- /dev/null +++ b/net/irda/irias_object.c @@ -0,0 +1,500 @@ +/********************************************************************* + * + * Filename: irias_object.c + * Version: 0.1 + * Description: IAS object database and functions + * Status: Experimental. + * Author: Dag Brattli + * Created at: Thu Oct 1 22:50:04 1998 + * Modified at: Sat Dec 5 13:54:39 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include + +#include +#include +#include + +hashbin_t *objects = NULL; + +/* + * Used when a missing value needs to be returned + */ +struct ias_value missing = { + IAS_MISSING, 0, 0, { 0 } +}; + +/* + * Function strdup (str) + * + * My own kernel version of strdup! + * + */ +char *strdup( char *str) +{ + char *new_str; + + if ( str == NULL) + return NULL; + + ASSERT( strlen( str) < 64, return NULL;); + + new_str = kmalloc( strlen( str)+1, GFP_ATOMIC); + if ( new_str == NULL) + return NULL; + + strcpy( new_str, str); + + return new_str; +} + +/* + * Function ias_new_object (name, id) + * + * Create a new IAS object + * + */ +struct ias_object *irias_new_object( char *name, int id) +{ + struct ias_object *obj; + + DEBUG( 4, __FUNCTION__ "()\n"); + + obj = (struct ias_object *) kmalloc( sizeof( struct ias_object), + GFP_ATOMIC); + if ( obj == NULL) { + DEBUG( 0, __FUNCTION__ "(), Unable to allocate object!\n"); + return NULL; + } + memset( obj, 0, sizeof( struct ias_object)); + + obj->magic = IAS_OBJECT_MAGIC; + obj->name = strdup( name); + obj->id = id; + + obj->attribs = hashbin_new( HB_LOCAL); + + return obj; +} + +/* + * Function irias_delete_attrib (attrib) + * + * Delete given attribute and deallocate all its memory + * + */ +void __irias_delete_attrib( struct ias_attrib *attrib) +{ + ASSERT( attrib != NULL, return;); + ASSERT( attrib->magic == IAS_ATTRIB_MAGIC, return;); + + if ( attrib->name) + kfree( attrib->name); + + irias_delete_value( attrib->value); + attrib->magic = ~IAS_ATTRIB_MAGIC; + + kfree( attrib); +} + +/* + * Function irias_delete_object (obj) + * + * Remove object from hashbin and deallocate all attributes assosiated with + * with this object and the object itself + * + */ +void __irias_delete_object( struct ias_object *obj) +{ + ASSERT( obj != NULL, return;); + ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;); + + if ( obj->name) + kfree( obj->name); + + hashbin_delete( obj->attribs, (FREE_FUNC) __irias_delete_attrib); + + obj->magic = ~IAS_OBJECT_MAGIC; + + kfree( obj); +} + +/* + * Function irias_remove_object (obj) + * + * Remove object with give name from the LM-IAS object database + * + */ +void irias_delete_object( char *obj_name) +{ + struct ias_object *obj; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( obj_name != NULL, return;); + + obj = hashbin_remove( objects, 0, obj_name); + + __irias_delete_object( obj); +} + +/* + * Function irias_insert_object (obj) + * + * Insert an object into the LM-IAS database + * + */ +void irias_insert_object( struct ias_object *obj) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( obj != NULL, return;); + ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;); + + hashbin_insert( objects, (QUEUE *) obj, 0, obj->name); +} + +/* + * Function irias_find_object (name) + * + * Find object with given name + * + */ +struct ias_object *irias_find_object( char *name) +{ + ASSERT( name != NULL, return NULL;); + + return hashbin_find( objects, 0, name); +} + +/* + * Function irias_find_attrib (obj, name) + * + * Find named attribute in object + * + */ +struct ias_attrib *irias_find_attrib( struct ias_object *obj, char *name) +{ + struct ias_attrib *attrib; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( obj != NULL, return NULL;); + ASSERT( obj->magic == IAS_OBJECT_MAGIC, return NULL;); + ASSERT( name != NULL, return NULL;); + + attrib = hashbin_find( obj->attribs, 0, name); + if ( attrib == NULL) + return NULL; + + return attrib; +} + +/* + * Function irias_add_attribute (obj, attrib) + * + * Add attribute to object + * + */ +void irias_add_attrib( struct ias_object *obj, struct ias_attrib *attrib) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( obj != NULL, return;); + ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;); + + ASSERT( attrib != NULL, return;); + ASSERT( attrib->magic == IAS_ATTRIB_MAGIC, return;); + + hashbin_insert( obj->attribs, (QUEUE *) attrib, 0, attrib->name); +} + +/* + * Function irias_object_change_attribute (obj_name, attrib_name, new_value) + * + * Change the value of an objects attribute. + * + * TODO: not tested yet! + */ +int irias_object_change_attribute( char *obj_name, char *attrib_name, + struct ias_value *new_value) +{ + struct ias_object *obj; + struct ias_attrib *attrib; + + /* Find object */ + obj = hashbin_find( objects, 0, obj_name); + if ( obj == NULL) { + DEBUG( 0, __FUNCTION__ "(), Unable to find object: %s\n", + obj_name); + return -1; + } + + /* Find attribute */ + attrib = hashbin_find( obj->attribs, 0, attrib_name); + if ( attrib == NULL) { + DEBUG( 0, __FUNCTION__ "(), Unable to find attribute: %s\n", + attrib_name); + return -1; + } + + if ( attrib->value->type != new_value->type) { + DEBUG( 0, __FUNCTION__ + "(), changing value type not allowed!\n"); + return -1; + } + + /* Delete old value */ + irias_delete_value( attrib->value); + + /* Insert new value */ + attrib->value = new_value; + + /* Success */ + return 0; +} + +/* + * Function irias_object_add_integer_attrib (obj, name, value) + * + * Add an integer attribute to an LM-IAS object + * + */ +void irias_add_integer_attrib( struct ias_object *obj, char *name, int value) +{ + struct ias_attrib *attrib; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( obj != NULL, return;); + ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;); + ASSERT( name != NULL, return;); + + attrib = (struct ias_attrib *) kmalloc( sizeof( struct ias_attrib), + GFP_ATOMIC); + if ( attrib == NULL) { + DEBUG( 0, __FUNCTION__ + "(), Unable to allocate attribute!\n"); + return; + } + memset( attrib, 0, sizeof( struct ias_attrib)); + + attrib->magic = IAS_ATTRIB_MAGIC; + attrib->name = strdup( name); +/* attrib->attr = NULL; */ + + /* Insert value */ + attrib->value = irias_new_integer_value( value); + + irias_add_attrib( obj, attrib); +} + + /* + * Function irias_add_octseq_attrib (obj, name, octet_seq, len) + * + * Add a octet sequence attribute to an LM-IAS object + * + */ + +void irias_add_octseq_attrib( struct ias_object *obj, char *name, + __u8 *octets, int len) +{ + struct ias_attrib *attrib; + + DEBUG( 0, __FUNCTION__ "()\n"); + + DEBUG( 0, __FUNCTION__ ": name=%s\n", name); + DEBUG( 0, __FUNCTION__ ": len=%d\n", len); + + ASSERT( obj != NULL, return;); + ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;); + + ASSERT( name != NULL, return;); + ASSERT( octets != NULL, return;); + ASSERT( len < 55, return;); /* FIXME: must be 1024, but... */ + + attrib = (struct ias_attrib *) kmalloc( sizeof( struct ias_attrib), + GFP_ATOMIC); + if ( attrib == NULL) { + DEBUG( 0, __FUNCTION__ + "(), Unable to allocate attribute!\n"); + return; + } + memset( attrib, 0, sizeof( struct ias_attrib)); + + attrib->magic = IAS_ATTRIB_MAGIC; + attrib->name = strdup( name); + + attrib->value = irias_new_octseq_value( octets, len); + + irias_add_attrib( obj, attrib); +} + +/* + * Function irias_object_add_string_attrib (obj, string) + * + * Add a string attribute to an LM-IAS object + * + */ +void irias_add_string_attrib( struct ias_object *obj, char *name, char *value) +{ + struct ias_attrib *attrib; + + DEBUG( 4, __FUNCTION__ "()\n"); + + DEBUG( 4, __FUNCTION__ ": name=%s\n", name); + DEBUG( 4, __FUNCTION__ ": name=%s\n", value); + + ASSERT( obj != NULL, return;); + ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;); + + ASSERT( name != NULL, return;); + ASSERT( value != NULL, return;); + + attrib = (struct ias_attrib *) kmalloc( sizeof( struct ias_attrib), + GFP_ATOMIC); + if ( attrib == NULL) { + DEBUG( 0, __FUNCTION__ + "(), Unable to allocate attribute!\n"); + return; + } + memset( attrib, 0, sizeof( struct ias_attrib)); + + attrib->magic = IAS_ATTRIB_MAGIC; + attrib->name = strdup( name); + + attrib->value = irias_new_string_value( value); + + irias_add_attrib( obj, attrib); +} + +/* + * Function irias_new_integer_value (integer) + * + * Create new IAS integer value + * + */ +struct ias_value *irias_new_integer_value( int integer) +{ + struct ias_value *value; + + value = kmalloc( sizeof( struct ias_value), GFP_ATOMIC); + if ( value == NULL) { + DEBUG( 0, __FUNCTION__ "(), Unable to kmalloc!\n"); + return NULL; + } + memset( value, 0, sizeof( struct ias_value)); + + value->type = IAS_INTEGER; + value->len = 4; + value->t.integer = integer; + + return value; +} + +/* + * Function irias_new_string_value (string) + * + * Create new IAS string value + * + */ +struct ias_value *irias_new_string_value( char *string) +{ + struct ias_value *value; + + value = kmalloc( sizeof( struct ias_value), GFP_ATOMIC); + if ( value == NULL) { + DEBUG( 0, __FUNCTION__ "(), Unable to kmalloc!\n"); + return NULL; + } + memset( value, 0, sizeof( struct ias_value)); + + value->type = IAS_STRING; + value->charset = CS_ASCII; + value->len = strlen( string); + value->t.string = strdup( string); + + return value; +} + + +/* + * Function irias_new_octseq_value (octets, len) + * + * Create new IAS octet-sequence value + * + */ +struct ias_value *irias_new_octseq_value( __u8 *octseq , int len) +{ + struct ias_value *value; + + ASSERT(len <= 55, return NULL;); /*FIXME: must be 1024, but.....*/ + + value = kmalloc( sizeof( struct ias_value), GFP_ATOMIC); + if ( value == NULL) { + DEBUG( 0, __FUNCTION__ "(), Unable to kmalloc!\n"); + return NULL; + } + memset( value, 0, sizeof( struct ias_value)); + + value->type = IAS_OCT_SEQ; + value->len = len; + + value->t.oct_seq = kmalloc(len, GFP_ATOMIC); + if( value->t.oct_seq == NULL){ + DEBUG(0, __FUNCTION__"(), Unable to kmalloc!\n"); + return NULL; + } + memcpy(value->t.oct_seq, octseq , len); + return value; +} + +/* + * Function irias_delete_value (value) + * + * Delete IAS value + * + */ +void irias_delete_value( struct ias_value *value) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( value != NULL, return;); + + switch( value->type) { + case IAS_INTEGER: /* Fallthrough */ + case IAS_MISSING: + /* No need to deallocate */ + break; + case IAS_STRING: + /* If string, deallocate string */ + if ( value->t.string != NULL) + kfree( value->t.string); + break; + case IAS_OCT_SEQ: + /* If byte stream, deallocate byte stream */ + if ( value->t.oct_seq != NULL) + kfree(value->t.oct_seq); + break; + default: + DEBUG( 0, __FUNCTION__ "(), Unknown value type!\n"); + break; + } + kfree( value); +} + + + diff --git a/net/irda/irlan/Config.in b/net/irda/irlan/Config.in new file mode 100644 index 000000000000..a9a7b84f2ab0 --- /dev/null +++ b/net/irda/irlan/Config.in @@ -0,0 +1,7 @@ + +dep_tristate 'IrLAN protocol' CONFIG_IRLAN $CONFIG_IRDA + +if [ "$CONFIG_IRLAN" != "n" ]; then + dep_tristate ' IrLAN client support' CONFIG_IRLAN_CLIENT $CONFIG_IRLAN + dep_tristate ' IrLAN server support' CONFIG_IRLAN_SERVER $CONFIG_IRLAN +fi diff --git a/net/irda/irlan/Makefile b/net/irda/irlan/Makefile new file mode 100644 index 000000000000..d5b37b9d8b44 --- /dev/null +++ b/net/irda/irlan/Makefile @@ -0,0 +1,52 @@ +# +# Makefile for the Linux IrDA IrLAN protocol layer. +# +# 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 definition is now in the main makefile... + +MOD_LIST_NAME := IRDA_MODULES +O_TARGET := irlan.o +O_OBJS := irlan_common.o irlan_eth.o irlan_event.o +M_OBJS := $(O_TARGET) +MI_OBJS := + +OX_OBJS += + +ifeq ($(CONFIG_IRLAN_CLIENT),y) +O_OBJS += irlan_cli.o irlan_cli_event.o +else + ifeq ($(CONFIG_IRLAN_CLIENT),m) +# MI_OBJS += irlan_cli.o irlan_cli_event.o + M_OBJS += irlan_client.o + endif +endif + +ifeq ($(CONFIG_IRLAN_SERVER),y) +O_OBJS += irlan_srv.o irlan_srv_event.o +else + ifeq ($(CONFIG_IRLAN_SERVER),m) +# MI_OBJS += irlan_srv.o irlan_srv_event.o + M_OBJS += irlan_server.o + endif +endif + +# Special rule to build the composite modules +ifeq ($(CONFIG_IRLAN),m) +irlan_client.o: irlan_cli.o irlan_cli_event.o + $(LD) $(LD_RFLAG) -r -o $@ irlan_cli.o irlan_cli_event.o + +irlan_server.o: irlan_srv.o irlan_srv_event.o + $(LD) $(LD_RFLAG) -r -o $@ irlan_srv.o irlan_srv_event.o +endif + +include $(TOPDIR)/Rules.make + +tar: + tar -cvf /dev/f1 . + + + + diff --git a/net/irda/irlan/irlan_cli.c b/net/irda/irlan/irlan_cli.c new file mode 100644 index 000000000000..b99f6a9f4007 --- /dev/null +++ b/net/irda/irlan/irlan_cli.c @@ -0,0 +1,678 @@ +/********************************************************************* + * + * Filename: irlan_cli.c + * Version: 0.8 + * Description: IrDA LAN Access Protocol Client + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sun Aug 31 20:14:37 1997 + * Modified at: Mon Dec 14 10:44:07 1998 + * Modified by: Dag Brattli + * Sources: skeleton.c by Donald Becker + * slip.c by Laurence Culhane, + * Fred N. van Kempen, + * + * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* + * Private functions + */ +static struct irlan_cb *irlan_client_open( __u32 saddr, __u32 daddr); +static void irlan_client_close( struct irlan_cb *self); + + +static int irlan_client_eth_open( struct device *dev) +{ + /* struct irlan_cb *self = (struct irlan_cb *) dev->priv; */ + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( dev != NULL, return -1;); + + /* Ready to play! */ + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + MOD_INC_USE_COUNT; + + return 0; +} + +/* + * Function irlan_eth_close (dev) + * + * Stop the Client ether network device, his function will be called by + * ifconfig down. + */ +static int irlan_client_eth_close(struct device *dev) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( dev != NULL, return -1;); + + /* Stop device */ + dev->tbusy = 1; + dev->start = 0; + + MOD_DEC_USE_COUNT; + + return 0; +} + +/* + * Function irlan_client_eth_init (dev) + * + * + * + */ +int irlan_client_eth_init( struct device *dev) +{ + irlan_eth_init( dev); + + /* Overrride some functions */ + dev->open = irlan_client_eth_open; + dev->stop = irlan_client_eth_close; + + return 0; +} + +/* + * Function irlan_client_init (dev) + * + * Allocates the master array. Called by modprobe(). + */ +__initfunc(int irlan_client_init( void)) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + /* Register with IrLMP as a service user */ + irlmp_register_layer( S_LAN, CLIENT, TRUE, + irlan_discovery_indication); + + /* Do some fast discovery! */ + irlmp_discovery_request( 8); + + return 0; +} + +/* + * Function irlan_client_cleanup (void) + * + * Removes all instances of the IrLAN network device driver, and the + * master array. Called by rmmod(). + * + */ +void irlan_client_cleanup(void) +{ + DEBUG( 0, "--> irlan_client_cleanup\n"); + + irlmp_unregister_layer( S_LAN, CLIENT); + + DEBUG( 4, "irlan_client_cleanup -->\n"); +} + +/* + * Function irlan_client_open (void) + * + * This function allocates and opens a new instance of the IrLAN network + * device driver. + * + */ +static struct irlan_cb *irlan_client_open( __u32 saddr, __u32 daddr) +{ + struct irlan_cb *self; + int result; + + DEBUG( 4, "IrLAN: irlan_client_open()\n"); + + ASSERT( irlan != NULL, return NULL;); + + self = irlan_open(); + if ( self == NULL) + return NULL; + + /* Use default name instead! */ + /* sprintf( self->ifname, "irlan%d", ); */ + self->dev.name = self->ifname; + self->dev.priv = (void *) self; + self->dev.next = NULL; + self->dev.init = irlan_client_eth_init; + + self->saddr = saddr; + self->daddr = daddr; + + /* + * Insert ourself into the hashbin + */ + hashbin_insert( irlan, (QUEUE *) self, saddr, NULL); + + if (( result = register_netdev( &self->dev)) != 0) { + DEBUG( 0, "IrLAN, Register_netdev() failed!\n"); + return NULL; + } + + irlan_next_state( self, IRLAN_IDLE); + + irlan_client_open_tsaps( self); + + return self; +} + +/* + * Function irlan_client_close (self) + * + * + * + */ +static void irlan_client_close( struct irlan_cb *self) +{ + struct irlan_cb *entry; + + DEBUG( 0, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + entry = hashbin_remove( irlan, self->daddr, NULL); + + ASSERT( entry == self, return;); + + /* __irlan_close( self); */ +} + +/* + * Function irlan_discovery_indication (daddr) + * + * Remote device with IrLAN server support discovered + * + */ +void irlan_discovery_indication( DISCOVERY *discovery) +{ + struct irlan_cb *self; + __u32 saddr, daddr; + + ASSERT( irlan != NULL, return;); + ASSERT( discovery != NULL, return;); + + saddr = discovery->saddr; + daddr = discovery->daddr; + + /* + * Check if an instance is already dealing with this device + * (saddr) + */ + self = (struct irlan_cb *) hashbin_find( irlan, saddr, NULL); + if ( self != NULL) { + ASSERT( self->magic == IRLAN_MAGIC, return;); + + DEBUG( 0, "Found instance!\n"); + if ( self->state == IRLAN_IDLE) { + /* daddr may have changed! */ + self->daddr = daddr; + + irlan_do_client_event( self, + IRLAN_DISCOVERY_INDICATION, + NULL); + } else { + DEBUG( 0, __FUNCTION__ "(), state=%s\n", + irlan_state[ self->state]); + /* + * If we get here, it's obvious that the last + * connection attempt has failed, so its best + * to go back to idle! + */ + irlan_do_client_event( self, IRLAN_LMP_DISCONNECT, + NULL); + } + return; + } + + /* + * We have no instance for daddr, so time to start a new instance. + */ + DEBUG( 0, __FUNCTION__ "(), Opening new instance for saddr=%#x\n", + saddr); + + if (( self = irlan_client_open( saddr, daddr)) == NULL) { + DEBUG( 0, "irlan_client_open failed!\n"); + return; + } + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + DEBUG( 4, "Setting irlan_client state!\n"); + if ( self->state == IRLAN_IDLE) { + irlan_do_client_event( self, IRLAN_DISCOVERY_INDICATION, NULL); + } else { + DEBUG( 0, __FUNCTION__ "(), Hmm, got here too!\n"); + } +} + +/* + * Function irlan_client_disconnect_indication (handle) + * + * Callback function for the IrTTP layer. Indicates a disconnection of + * the specified connection (handle) + */ +void irlan_client_disconnect_indication( void *instance, void *sap, + LM_REASON reason, + struct sk_buff *userdata) +{ + struct irlan_cb *self; + struct tsap_cb *tsap; + + self = ( struct irlan_cb *) instance; + tsap = ( struct tsap_cb *) sap; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + ASSERT( tsap != NULL, return;); + ASSERT( tsap->magic == TTP_TSAP_MAGIC, return;); + + DEBUG( 4, __FUNCTION__ "(), reason=%d\n", reason); + + if ( tsap == self->tsap_data) { + DEBUG( 0, "IrLAN, data channel disconnected by peer!\n"); + self->connected = FALSE; + } else if ( tsap == self->tsap_ctrl) { + DEBUG( 0, "IrLAN, control channel disconnected by peer!\n"); + } else { + DEBUG( 0, "Error, disconnect on unknown handle!\n"); + } + + /* Stop IP from transmitting more packets */ + /* irlan_client_flow_indication( handle, FLOW_STOP, priv); */ + + irlan_do_client_event( self, IRLAN_LMP_DISCONNECT, NULL); +} + +/* + * Function irlan_control_data_indication (handle, skb) + * + * This function gets the data that is received on the control channel + * + */ +void irlan_client_ctrl_data_indication( void *instance, void *sap, + struct sk_buff *skb) +{ + struct irlan_cb *self; + + DEBUG( 4, __FUNCTION__ "()\n"); + + self = ( struct irlan_cb *) instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + ASSERT( skb != NULL, return;); + + DEBUG( 4, "Got IRLAN_DATA_INDICATION!\n"); + irlan_do_client_event( self, IRLAN_DATA_INDICATION, skb); +} + +/* + * Function irlan_client_open_tsaps (self) + * + * Initialize callbacks and open IrTTP TSAPs + * + */ +void irlan_client_open_tsaps( struct irlan_cb *self) +{ + /* struct irlan_frame frame; */ + struct notify_t notify_ctrl; + struct notify_t notify_data; + + DEBUG( 4, __FUNCTION__ "()\n"); + + irda_notify_init( ¬ify_ctrl); + irda_notify_init( ¬ify_data); + + /* Set up callbacks */ + notify_ctrl.data_indication = irlan_client_ctrl_data_indication; + notify_ctrl.connect_confirm = irlan_client_connect_confirm; + notify_ctrl.disconnect_indication = irlan_client_disconnect_indication; + notify_ctrl.instance = self; + strncpy( notify_ctrl.name, "IrLAN ctrl", NOTIFY_MAX_NAME); + + notify_data.data_indication = irlan_eth_rx; + notify_data.udata_indication = irlan_eth_rx; + notify_data.connect_confirm = irlan_client_connect_confirm; + notify_data.flow_indication = irlan_eth_flow_indication; + notify_data.disconnect_indication = irlan_client_disconnect_indication; + notify_data.instance = self; + strncpy( notify_data.name, "IrLAN data", NOTIFY_MAX_NAME); + + /* Create TSAP's */ + self->tsap_ctrl = irttp_open_tsap( LSAP_ANY, + DEFAULT_INITIAL_CREDIT, + ¬ify_ctrl); + self->tsap_data = irttp_open_tsap( LSAP_ANY, + DEFAULT_INITIAL_CREDIT, + ¬ify_data); +} + +/* + * Function irlan_client_connect_confirm (handle, skb) + * + * Connection to peer IrLAN laye confirmed + * + */ +void irlan_client_connect_confirm( void *instance, void *sap, + struct qos_info *qos, int max_sdu_size, + struct sk_buff *skb) +{ + struct irlan_cb *self; + + DEBUG( 4, __FUNCTION__ "()\n"); + + self = ( struct irlan_cb *) instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + /* TODO: we could set the MTU depending on the max_sdu_size */ + + irlan_do_client_event( self, IRLAN_CONNECT_COMPLETE, NULL); +} + +/* + * Function irlan_client_reconnect_data_channel (self) + * + * Try to reconnect data channel (currently not used) + * + */ +void irlan_client_reconnect_data_channel( struct irlan_cb *self) +{ + struct sk_buff *skb; + __u8 *frame; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + skb = dev_alloc_skb( 128); + if (skb == NULL) { + DEBUG( 0, __FUNCTION__ + "(), Could not allocate an sk_buff of length %d\n", 64); + return; + } + + /* Reserve space for TTP, LMP, and LAP header */ + skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_put( skb, 2); + + frame = skb->data; + + frame[0] = CMD_RECONNECT_DATA_CHAN; + frame[1] = 0x01; + insert_array_param( skb, "RECONNECT_KEY", + self->t.client.reconnect_key, + self->t.client.key_len); + + irttp_data_request( self->tsap_ctrl, skb); +} + +/* + * Function irlan_client_extract_params (skb) + * + * Extract all parameters from received buffer, then feed them to + * check_params for parsing + * + */ +void irlan_client_extract_params( struct irlan_cb *self, + struct sk_buff *skb) +{ + __u8 *frame; + __u8 *ptr; + int count; + int ret; + int val_len; + int i; + + ASSERT( skb != NULL, return;); + + DEBUG( 4, __FUNCTION__ "() skb->len=%d\n", (int) skb->len); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + if ( skb == NULL) { + DEBUG( 0, __FUNCTION__ "(), Got NULL skb!\n"); + return; + } + frame = skb->data; + + /* + * Check return code and print it if not success + */ + if ( frame[0]) + print_ret_code( frame[0]); + + /* How many parameters? */ + count = frame[1]; + + DEBUG( 4, "Got %d parameters\n", count); + + ptr = frame+2; + + /* For all parameters */ + for ( i=0; iname, self->value, + &val_len); + if ( ret == -1) { + DEBUG( 0, __FUNCTION__ "(), IrLAN, Error!\n"); + return; + } + ptr+=ret; + check_response_param( self, self->name, self->value, val_len); + } +} + +/* + * Function check_param (param, value) + * + * Check which parameter is received and update local variables + * + */ +void check_response_param( struct irlan_cb *self, char *param, + char *value, int val_len) +{ + int i; + __u8 *bytes; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + /* + * Media type + */ + if ( strcmp( param, "MEDIA") == 0) { + if ( strcmp( value, "802.3") == 0) + self->media = MEDIA_802_3; + else + self->media = MEDIA_802_5; + return; + } + /* + * IRLAN version + */ + if ( strcmp( param, "IRLAN_VER") == 0) { + DEBUG( 4, "IrLAN version %d.%d\n", + (__u8) value[0], (__u8) value[1]); + return; + } + /* + * Which remote TSAP to use for data channel + */ + if ( strcmp( param, "DATA_CHAN") == 0) { + self->dtsap_sel_data = value[0]; + DEBUG( 4, "Data TSAP = %02x\n", self->dtsap_sel_data); + return; + } + /* + * RECONNECT_KEY, in case the link goes down! + */ + if ( strcmp( param, "RECONNECT_KEY") == 0) { + DEBUG( 4, "Got reconnect key: "); + /* for (i = 0; i < val_len; i++) */ +/* printk( "%02x", value[i]); */ + memcpy( self->t.client.reconnect_key, value, val_len); + self->t.client.key_len = val_len; + DEBUG( 4, "\n"); + } + /* + * FILTER_ENTRY, have we got the ethernet address? + */ + if ( strcmp( param, "FILTER_ENTRY") == 0) { + bytes = value; + DEBUG( 4, "Ethernet address = %02x:%02x:%02x:%02x:%02x:%02x\n", + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], + bytes[5]); + for (i = 0; i < 6; i++) + self->dev.dev_addr[i] = bytes[i]; +#if 0 + /* + * When we get a new MAC address do a gratuitous ARP. This is useful + * if we have changed access points on the same subnet. + */ + DEBUG( 4, "IrLAN: Sending gratuitous ARP\n"); + arp_send( ARPOP_REQUEST, ETH_P_ARP, self->dev.pa_addr, + &self->dev, self->dev.pa_addr, NULL, + self->dev.dev_addr, NULL); +#endif + } +} + +/* + * Function irlan_client_get_value_confirm (obj_id, value) + * + * Got results from previous GetValueByClass request + * + */ +void irlan_client_get_value_confirm( __u16 obj_id, struct ias_value *value, + void *priv) +{ + struct irlan_cb *self; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( priv != NULL, return;); + + self = ( struct irlan_cb *) priv; + + ASSERT( self->magic == IRLAN_MAGIC, return;); + + switch ( value->type) { + case IAS_INTEGER: + self->dtsap_sel_ctrl = value->t.integer; + + if ( value->t.integer != -1) { + irlan_do_client_event( self, IRLAN_IAS_PROVIDER_AVAIL, + NULL); + return; + } + break; + case IAS_STRING: + DEBUG( 0, __FUNCTION__ "(), got string %s\n", value->t.string); + break; + case IAS_OCT_SEQ: + DEBUG( 0, __FUNCTION__ "(), OCT_SEQ not implemented\n"); + break; + case IAS_MISSING: + DEBUG( 0, __FUNCTION__ "(), MISSING not implemented\n"); + break; + default: + DEBUG( 0, __FUNCTION__ "(), unknown type!\n"); + break; + } + irlan_do_client_event( self, IRLAN_IAS_PROVIDER_NOT_AVAIL, NULL); +} + +#ifdef MODULE + +MODULE_AUTHOR("Dag Brattli "); +MODULE_DESCRIPTION("The Linux IrDA LAN protocol"); + +/* + * Function init_module (void) + * + * Initialize the IrLAN module, this function is called by the + * modprobe(1) program. + */ +int init_module(void) +{ + DEBUG( 4, __FUNCTION__ "(), irlan_client.c\n"); + + irlan_client_init(); + + return 0; +} + +/* + * Function cleanup_module (void) + * + * Remove the IrLAN module, this function is called by the rmmod(1) + * program + */ +void cleanup_module(void) +{ + DEBUG( 4, "--> irlan, cleanup_module\n"); + /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ + + /* Free some memory */ + irlan_client_cleanup(); + + DEBUG( 4, "irlan, cleanup_module -->\n"); +} + +#endif /* MODULE */ + + + + + + + + + diff --git a/net/irda/irlan/irlan_cli_event.c b/net/irda/irlan/irlan_cli_event.c new file mode 100644 index 000000000000..2f01a4b4a783 --- /dev/null +++ b/net/irda/irlan/irlan_cli_event.c @@ -0,0 +1,494 @@ +/********************************************************************* + * + * Filename: irlan_cli_event.c + * Version: 0.1 + * Description: IrLAN Client FSM (Finite State Machine) + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sun Aug 31 20:14:37 1997 + * Modified at: Wed Dec 9 02:36:49 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli , + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +static int irlan_client_state_idle ( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb); +static int irlan_client_state_query( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb); +static int irlan_client_state_conn ( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb); +static int irlan_client_state_info ( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb); +static int irlan_client_state_media( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb); +static int irlan_client_state_open ( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb); +static int irlan_client_state_wait ( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb); +static int irlan_client_state_arb ( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb); +static int irlan_client_state_data ( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb); +static int irlan_client_state_close( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb); +static int irlan_client_state_sync ( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb); + +static int (*state[])( struct irlan_cb *, IRLAN_EVENT event, + struct sk_buff *) = +{ + irlan_client_state_idle, + irlan_client_state_query, + irlan_client_state_conn, + irlan_client_state_info, + irlan_client_state_media, + irlan_client_state_open, + irlan_client_state_wait, + irlan_client_state_arb, + irlan_client_state_data, + irlan_client_state_close, + irlan_client_state_sync +}; + +void irlan_do_client_event( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb) +{ + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + (*state[ self->state]) ( self, event, skb); +} + +/* + * Function irlan_client_state_idle (event, skb, info) + * + * IDLE, We are waiting for an indication that there is a provider + * available. + */ +static int irlan_client_state_idle( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb) +{ + DEBUG( 4, "irlan_client_state_idle()\n"); + + ASSERT( self != NULL, return -1;); + ASSERT( self->magic == IRLAN_MAGIC, return -1;); + + switch( event) { + case IRLAN_DISCOVERY_INDICATION: + /* Get some values from peer IAS */ +#if 0 + iriap_getvaluebyclass_request( self->daddr, + /* "PnP", "DeviceID", */ + "Device", "DeviceName", + irlan_client_get_value_confirm, + self); +#endif + iriap_getvaluebyclass_request( self->daddr, + "IrLAN", "IrDA:TinyTP:LsapSel", + irlan_client_get_value_confirm, + self); + + irlan_next_state( self, IRLAN_QUERY); + break; + default: + DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event); + break; + } + if ( skb) { + dev_kfree_skb( skb); + } + return 0; +} + +/* + * Function irlan_client_state_query (event, skb, info) + * + * QUERY, We have queryed the remote IAS and is ready to connect + * to provider, just waiting for the confirm. + * + */ +static int irlan_client_state_query( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return -1;); + ASSERT( self->magic == IRLAN_MAGIC, return -1;); + + switch( event) { + case IRLAN_IAS_PROVIDER_AVAIL: + ASSERT( self->dtsap_sel_ctrl != 0, return -1;); + + self->t.client.open_retries = 0; + + irttp_connect_request( self->tsap_ctrl, self->dtsap_sel_ctrl, + self->daddr, NULL, IRLAN_MTU, NULL); + irlan_next_state( self, IRLAN_CONN); + break; + case IRLAN_IAS_PROVIDER_NOT_AVAIL: + DEBUG( 0, __FUNCTION__ "(), IAS_PROVIDER_NOT_AVAIL\n"); + irlan_next_state( self, IRLAN_IDLE); + break; + case IRLAN_LMP_DISCONNECT: + case IRLAN_LAP_DISCONNECT: + irlan_next_state( self, IRLAN_IDLE); + break; + default: + DEBUG( 0, __FUNCTION__"(), Unknown event %d\n", event); + break; + } + if ( skb) { + dev_kfree_skb( skb); + } + + return 0; +} + +/* + * Function irlan_client_state_conn (event, skb, info) + * + * CONN, We have connected to a provider but has not issued any + * commands yet. + * + */ +static int irlan_client_state_conn( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return -1;); + + switch( event) { + case IRLAN_CONNECT_COMPLETE: + /* Send getinfo cmd */ + irlan_get_provider_info( self); + irlan_next_state( self, IRLAN_INFO); + break; + case IRLAN_LMP_DISCONNECT: + case IRLAN_LAP_DISCONNECT: + irlan_next_state( self, IRLAN_IDLE); + break; + default: + DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event); + break; + } + if ( skb) { + dev_kfree_skb( skb); + } + + return 0; +} + +/* + * Function irlan_client_state_info (self, event, skb, info) + * + * INFO, We have issued a GetInfo command and is awaiting a reply. + */ +static int irlan_client_state_info( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return -1;); + + switch( event) { + case IRLAN_DATA_INDICATION: + ASSERT( skb != NULL, return -1;); + + irlan_client_extract_params( self, skb); + + irlan_next_state( self, IRLAN_MEDIA); + + irlan_get_media_char( self); + break; + + case IRLAN_LMP_DISCONNECT: + case IRLAN_LAP_DISCONNECT: + irlan_next_state( self, IRLAN_IDLE); + break; + default: + DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event); + break; + } + if ( skb) { + dev_kfree_skb( skb); + } + + return 0; +} + +/* + * Function irlan_client_state_media (self, event, skb, info) + * + * MEDIA, The irlan_client has issued a GetMedia command and is awaiting a + * reply. + * + */ +static int irlan_client_state_media( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return -1;); + + switch( event) { + case IRLAN_DATA_INDICATION: + irlan_client_extract_params( self, skb); + irlan_open_data_channel( self); + irlan_next_state( self, IRLAN_OPEN); + break; + case IRLAN_LMP_DISCONNECT: + case IRLAN_LAP_DISCONNECT: + irlan_next_state( self, IRLAN_IDLE); + break; + default: + DEBUG( 0, "irlan_client_state_media, Unknown event %d\n", + event); + break; + } + if ( skb) { + dev_kfree_skb( skb); + } + + return 0; +} + +/* + * Function irlan_client_state_open (self, event, skb, info) + * + * OPEN, The irlan_client has issued a OpenData command and is awaiting a + * reply + * + */ +static int irlan_client_state_open( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb) +{ + struct qos_info qos; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return -1;); + + switch( event) { + case IRLAN_DATA_INDICATION: + irlan_client_extract_params( self, skb); + + /* + * Check if we have got the remote TSAP for data + * communications + */ + ASSERT( self->dtsap_sel_data != 0, return -1;); + + qos.link_disc_time.bits = 0x01; /* 3 secs */ + + irttp_connect_request( self->tsap_data, + self->dtsap_sel_data, self->daddr, + NULL, IRLAN_MTU, NULL); + + irlan_next_state( self, IRLAN_DATA); + break; + + case IRLAN_LMP_DISCONNECT: + case IRLAN_LAP_DISCONNECT: + irlan_next_state( self, IRLAN_IDLE); + break; + default: + DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", + event); + break; + } + + if ( skb) { + dev_kfree_skb( skb); + } + + return 0; +} + +/* + * Function irlan_client_state_wait (self, event, skb, info) + * + * WAIT, The irlan_client is waiting for the local provider to enter the + * provider OPEN state. + * + */ +static int irlan_client_state_wait( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb) +{ + DEBUG( 4, "irlan_client_state_wait()\n"); + + ASSERT( self != NULL, return -1;); + + switch( event) { + case IRLAN_LMP_DISCONNECT: + case IRLAN_LAP_DISCONNECT: + irlan_next_state( self, IRLAN_IDLE); + break; + default: + DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", + event); + break; + } + if ( skb) { + dev_kfree_skb( skb); + } + + return 0; +} + +static int irlan_client_state_arb( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb) +{ + DEBUG( 0, __FUNCTION__ "(), not implemented!\n"); + + if ( skb) { + dev_kfree_skb( skb); + } + return 0; +} + +/* + * Function irlan_client_state_data (self, event, skb, info) + * + * DATA, The data channel is connected, allowing data transfers between + * the local and remote machines. + * + */ +static int irlan_client_state_data( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb) +{ + struct irmanager_event mgr_event; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return -1;); + ASSERT( self->magic == IRLAN_MAGIC, return -1;); + + switch( event) { + case IRLAN_CONNECT_COMPLETE: + irlan_get_unicast_addr( self); + irlan_open_unicast_addr( self); + /* irlan_set_broadcast_filter( self, TRUE); */ + + DEBUG( 4, "IrLAN, We are now connected!\n"); + + /* irlan_next_state( LAN_DATA); */ + break; + case IRLAN_DATA_INDICATION: + irlan_client_extract_params( self, skb); + + /* irlan_client_flow_indication( self->data_tsap, FLOW_START, */ +/* self); */ + + /* Make sure the code below only runs once */ + if ( !self->connected) { + mgr_event.event = EVENT_IRLAN_START; + sprintf( mgr_event.devname, "%s", self->ifname); + irmanager_notify( &mgr_event); + + self->connected = TRUE; + } + break; + + case IRLAN_LMP_DISCONNECT: + case IRLAN_LAP_DISCONNECT: + mgr_event.event = EVENT_IRLAN_STOP; + sprintf( mgr_event.devname, "%s", self->ifname); + irmanager_notify( &mgr_event); + + irlan_next_state( self, IRLAN_IDLE); + break; + default: + DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event); + break; + } + if ( skb) { + dev_kfree_skb( skb); + } + + return 0; +} + +/* + * Function irlan_client_state_close (self, event, skb, info) + * + * + * + */ +static int irlan_client_state_close( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb) +{ + DEBUG( 0, __FUNCTION__ "()\n"); + + if ( skb) { + dev_kfree_skb( skb); + } + + return 0; +} + +/* + * Function irlan_client_state_sync (self, event, skb, info) + * + * + * + */ +static int irlan_client_state_sync( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb) +{ + DEBUG( 0, __FUNCTION__ "()\n"); + + if ( skb) { + dev_kfree_skb( skb); + } + + return 0; +} + diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c new file mode 100644 index 000000000000..342070a5a18b --- /dev/null +++ b/net/irda/irlan/irlan_common.c @@ -0,0 +1,896 @@ +/********************************************************************* + * + * Filename: irlan_common.c + * Version: 0.1 + * Description: IrDA LAN Access Protocol Implementation + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sun Aug 31 20:14:37 1997 + * Modified at: Mon Dec 14 10:43:05 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1997 Dag Brattli , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +static void __irlan_close( struct irlan_cb *self); + +/* + * Master structure + */ +hashbin_t *irlan = NULL; + +#ifdef CONFIG_PROC_FS +static int irlan_proc_read( char *buf, char **start, off_t offset, + int len, int unused); + +extern struct proc_dir_entry proc_irda; + +struct proc_dir_entry proc_irlan = { + 0, 5, "irlan", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, NULL, + &irlan_proc_read, +}; +#endif + +/* + * Function irlan_init (void) + * + * Initialize IrLAN layer + * + */ +__initfunc(int irlan_init( void)) +{ + /* Allocate master array */ + irlan = hashbin_new( HB_LOCAL); + if ( irlan == NULL) { + printk( KERN_WARNING "IrLAN: Can't allocate hashbin!\n"); + return -ENOMEM; + } +#ifdef CONFIG_PROC_FS + proc_register( &proc_irda, &proc_irlan); +#endif /* CONFIG_PROC_FS */ + + return 0; +} + +void irlan_cleanup(void) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + +#ifdef CONFIG_PROC_FS + proc_unregister( &proc_irda, proc_irlan.low_ino); +#endif + /* + * Delete hashbin and close all irlan client instances in it + */ + hashbin_delete( irlan, (FREE_FUNC) __irlan_close); +} + + +/* + * Function irlan_open (void) + * + * + * + */ +struct irlan_cb *irlan_open(void) +{ + struct irlan_cb *self; + + DEBUG( 4, __FUNCTION__ "()\n"); + + /* + * Initialize the irlan structure. + */ + self = kmalloc( sizeof(struct irlan_cb), GFP_ATOMIC); + if ( self == NULL) + return NULL; + + memset( self, 0, sizeof( struct irlan_cb)); + + /* + * Initialize local device structure + */ + self->magic = IRLAN_MAGIC; + + return self; +} +/* + * Function irlan_close (self) + * + * This function closes and deallocates the IrLAN client instances. Be + * aware that other functions which calles client_close() must call + * hashbin_remove() first!!! + * + */ +void __irlan_close( struct irlan_cb *self) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + /* + * Disconnect open TSAP connections + */ + if ( self->tsap_data) { + irttp_disconnect_request( self->tsap_data, NULL, P_HIGH); + + /* FIXME: this will close the tsap before the disconenct + * frame has been sent + */ + /* irttp_close_tsap( self->tsap_data); */ + } + if ( self->tsap_ctrl) { + irttp_disconnect_request( self->tsap_ctrl, NULL, P_HIGH); + + /* irttp_close_tsap( self->tsap_control); */ + } + + unregister_netdev( &self->dev); + + /* + * Make sure that nobody uses this instance anymore! + */ + self->magic = 0; + + /* + * Dealloacte structure + */ + kfree( self); +} + +/* + * Function irlan_close (self) + * + * + * + */ +void irlan_close( struct irlan_cb *self) +{ + struct irlan_cb *entry; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + entry = hashbin_remove( irlan, self->daddr, NULL); + + ASSERT( entry == self, return;); + + __irlan_close( self); +} + +/* + * Function irlan_get_provider_info (self) + * + * Send Get Provider Information command to peer IrLAN layer + * + */ +void irlan_get_provider_info( struct irlan_cb *self) +{ + struct sk_buff *skb; + __u8 *frame; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + skb = dev_alloc_skb( 64); + if (skb == NULL) { + DEBUG( 0, __FUNCTION__ + "(), Could not allocate an skb of length %d\n", 64); + return; + } + + /* Reserve space for TTP, LMP, and LAP header */ + skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_put( skb, 2); + + frame = skb->data; + + frame[0] = CMD_GET_PROVIDER_INFO; + frame[1] = 0x00; /* Zero parameters */ + + irttp_data_request( self->tsap_ctrl, skb); +} + +/* + * Function irlan_open_data_channel (self) + * + * Send an Open Data Command to provider + * + */ +void irlan_open_data_channel( struct irlan_cb *self) +{ + struct sk_buff *skb; + __u8 *frame; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + skb = dev_alloc_skb( 64); + if (skb == NULL) { + DEBUG( 0, __FUNCTION__ + "(), Could not allocate an skb of length %d\n", 64); + return; + } + + /* Reserve space for TTP, LMP, and LAP header */ + skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_put( skb, 2); + + frame = skb->data; + + /* Build frame */ + frame[0] = CMD_OPEN_DATA_CHANNEL; + frame[1] = 0x02; /* Two parameters */ + + insert_string_param( skb, "MEDIA", "802.3"); + insert_string_param( skb, "ACCESS_TYPE", "DIRECT"); + /* insert_string_param( skb, "MODE", "UNRELIABLE"); */ + +/* self->use_udata = TRUE; */ + + irttp_data_request( self->tsap_ctrl, skb); +} + +/* + * Function irlan_open_unicast_addr (self) + * + * Make IrLAN provider accept ethernet frames addressed to the unicast + * address. + * + */ +void irlan_open_unicast_addr( struct irlan_cb *self) +{ + struct sk_buff *skb; + __u8 *frame; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + skb = dev_alloc_skb( 128); + if (skb == NULL) { + DEBUG( 0, __FUNCTION__ + "(), Could not allocate an skb of length %d\n", 64); + return; + } + + /* Reserve space for TTP, LMP, and LAP header */ + skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_put( skb, 2); + + frame = skb->data; + + frame[0] = CMD_FILTER_OPERATION; + frame[1] = 0x03; /* Three parameters */ + insert_byte_param( skb, "DATA_CHAN" , self->dtsap_sel_data); + insert_string_param( skb, "FILTER_TYPE", "DIRECTED"); + insert_string_param( skb, "FILTER_MODE", "FILTER"); + + irttp_data_request( self->tsap_ctrl, skb); +} + +/* + * Function irlan_set_broadcast_filter (self, status) + * + * Make IrLAN provider accept ethernet frames addressed to the broadcast + * address. Be careful with the use of this one, sice there may be a lot + * of broadcast traffic out there. We can still function without this + * one but then _we_ have to initiate all communication with other + * hosts, sice ARP request for this host will not be answered. + */ +void irlan_set_broadcast_filter( struct irlan_cb *self, int status) +{ + struct sk_buff *skb; + __u8 *frame; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + /* Should only be used by client */ + if (!self->client) + return; + + skb = dev_alloc_skb( 128); + if (skb == NULL) { + DEBUG( 0, __FUNCTION__ + "(), Could not allocate an skb of length %d\n", 64); + return; + } + + /* Reserve space for TTP, LMP, and LAP header */ + skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_put( skb, 2); + + frame = skb->data; + + frame[0] = CMD_FILTER_OPERATION; + frame[1] = 0x03; /* Three parameters */ + insert_byte_param( skb, "DATA_CHAN", self->dtsap_sel_data); + insert_string_param( skb, "FILTER_TYPE", "BROADCAST"); + if ( status) + insert_string_param( skb, "FILTER_MODE", "FILTER"); + else + insert_string_param( skb, "FILTER_MODE", "NONE"); + + irttp_data_request( self->tsap_ctrl, skb); +} + +/* + * Function irlan_set_multicast_filter (self, status) + * + * Make IrLAN provider accept ethernet frames addressed to the multicast + * address. + * + */ +void irlan_set_multicast_filter( struct irlan_cb *self, int status) +{ + struct sk_buff *skb; + __u8 *frame; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + /* Should only be used by client */ + if (!self->client) + return; + + skb = dev_alloc_skb( 128); + if (skb == NULL) { + DEBUG( 0, __FUNCTION__ + "(), Could not allocate an skb of length %d\n", 64); + return; + } + + /* Reserve space for TTP, LMP, and LAP header */ + skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_put( skb, 2); + + frame = skb->data; + + frame[0] = CMD_FILTER_OPERATION; + frame[1] = 0x03; /* Three parameters */ + insert_byte_param( skb, "DATA_CHAN", self->dtsap_sel_data); + insert_string_param( skb, "FILTER_TYPE", "MULTICAST"); + if ( status) + insert_string_param( skb, "FILTER_MODE", "ALL"); + else + insert_string_param( skb, "FILTER_MODE", "NONE"); + + irttp_data_request( self->tsap_ctrl, skb); +} + +/* + * Function irlan_get_unicast_addr (self) + * + * Retrives the unicast address from the IrLAN provider. This address + * will be inserted into the devices structure, so the ethernet layer + * can construct its packets. + * + */ +void irlan_get_unicast_addr( struct irlan_cb *self) +{ + struct sk_buff *skb; + __u8 *frame; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + skb = dev_alloc_skb( 128); + if (skb == NULL) { + DEBUG( 0, "irlan_client_get_unicast_addr: " + "Could not allocate an sk_buff of length %d\n", 64); + return; + } + + /* Reserve space for TTP, LMP, and LAP header */ + skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_put( skb, 2); + + frame = skb->data; + + frame[0] = CMD_FILTER_OPERATION; + frame[1] = 0x03; /* Three parameters */ + insert_byte_param( skb, "DATA_CHAN", self->dtsap_sel_data); + insert_string_param( skb, "FILTER_TYPE", "DIRECTED"); + insert_string_param( skb, "FILTER_OPERATION", "DYNAMIC"); + + irttp_data_request( self->tsap_ctrl, skb); +} + +/* + * Function irlan_get_media_char (self) + * + * + * + */ +void irlan_get_media_char( struct irlan_cb *self) +{ + struct sk_buff *skb; + __u8 *frame; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + skb = dev_alloc_skb( 64); + if (skb == NULL) { + DEBUG( 0,"irlan_server_get_media_char: " + "Could not allocate an sk_buff of length %d\n", 64); + return; + } + + /* Reserve space for TTP, LMP, and LAP header */ + skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_put( skb, 2); + + frame = skb->data; + + /* Build frame */ + frame[0] = CMD_GET_MEDIA_CHAR; + frame[1] = 0x01; /* One parameter */ + + insert_string_param( skb, "MEDIA", "802.3"); + + irttp_data_request( self->tsap_ctrl, skb); +} + +/* + * Function insert_byte_param (skb, param, value) + * + * Insert byte parameter into frame + * + */ +int insert_byte_param( struct sk_buff *skb, char *param, __u8 value) +{ + __u8 *frame; + __u8 len_param; + __u16 len_value; + int n=0; + + if ( skb == NULL) { + DEBUG( 0, "insert_param: Got NULL skb\n"); + return 0; + } + + len_param = strlen( param); + len_value = 1; + + /* + * Insert at end of sk-buffer + */ + frame = skb->tail; + + /* Make space for data */ + if ( skb_tailroom(skb) < (len_param+len_value+3)) { + DEBUG( 0, "insert_param: No more space at end of skb\n"); + return 0; + } + skb_put( skb, len_param+len_value+3); + + /* Insert parameter length */ + frame[n++] = len_param; + + /* Insert parameter */ + memcpy( frame+n, param, len_param); + n += len_param; + + /* Insert value length ( 2 byte little endian format, LSB first) */ + frame[n++] = len_value & 0xff; + frame[n++] = len_value >> 8; + + frame[n++] = value; + + return len_param+len_value+3; +} + +/* + * Function insert_string (skb, param, value) + * + * Insert string parameter into frame + * + */ +int insert_string_param( struct sk_buff *skb, char *param, char *value) +{ + __u8 *frame; + __u8 len_param; + __u16 len_value; + int n=0; + + if ( skb == NULL) { + DEBUG( 0, "insert_param: Got NULL skb\n"); + return 0; + } + len_param = strlen( param); + len_value = strlen( value); + + /* + * Insert at end of sk-buffer + */ + frame = skb->tail; + + /* Make space for data */ + if ( skb_tailroom(skb) < (len_param+len_value+3)) { + DEBUG( 0, "insert_param: No more space at end of skb\n"); + return 0; + } + skb_put( skb, len_param+len_value+3); + + /* Insert parameter length */ + frame[n++] = len_param; + + /* Insert parameter */ + memcpy( frame+n, param, len_param); + n += len_param; + + /* Insert value length ( 2 byte little endian format, LSB first) */ + frame[n++] = len_value & 0xff; + frame[n++] = len_value >> 8; + + memcpy( frame+n, value, len_value); + n+=len_value; + + return len_param+len_value+3; +} + +/* + * Function insert_array_param( skb, param, value, len_value) + * + * Insert array parameter into frame + * + */ +int insert_array_param( struct sk_buff *skb, char *name, __u8 *value, + __u16 value_len) +{ + __u8 *frame; + __u8 name_len; + int n=0; + + if ( skb == NULL) { + DEBUG( 0, __FUNCTION__ "(), Got NULL skb\n"); + return 0; + } + name_len = strlen( name); + + /* + * Insert at end of sk-buffer + */ + frame = skb->tail; + + /* Make space for data */ + if ( skb_tailroom(skb) < (name_len+value_len+3)) { + DEBUG( 0, __FUNCTION__ "(), No more space at end of skb\n"); + return 0; + } + skb_put( skb, name_len+value_len+3); + + /* Insert parameter length */ + frame[n++] = name_len; + + /* Insert parameter */ + memcpy( frame+n, name, name_len); + n += name_len; + + /* Insert value length ( 2 byte little endian format, LSB first) */ + /* FIXME: should we use htons() here? */ + frame[n++] = value_len & 0xff; + frame[n++] = value_len >> 8; + + memcpy( frame+n, value, value_len); + n+=value_len; + + return name_len+value_len+3; +} + +/* + * Function insert_param (skb, param, value, byte) + * + * Insert parameter at end of buffer, structure of a parameter is: + * + * ----------------------------------------------------------------------- + * | Name Length[1] | Param Name[1..255] | Val Length[2] | Value[0..1016]| + * ----------------------------------------------------------------------- + */ +int insert_param( struct sk_buff *skb, char *param, int type, char *value_char, + __u8 value_byte, __u16 value_short) +{ + __u8 *frame; + __u8 len_param; + __u16 len_value; + int n; + + if ( skb == NULL) { + DEBUG( 0, "insert_param: Got NULL skb\n"); + return 0; + } + + n = 0; + + len_param = strlen( param); + switch ( type) { + case 1: + ASSERT( value_char != NULL, return 0;); + len_value = strlen( value_char); + break; + case 2: + len_value = 1; + break; + case 3: + len_value = 2; + break; + default: + DEBUG( 0, "Error in insert_param!\n"); + return 0; + break; + } + + /* + * Insert at end of sk-buffer + */ + frame = skb->tail; + + /* Make space for data */ + if ( skb_tailroom(skb) < (len_param+len_value+3)) { + DEBUG( 0, "insert_param: No more space at end of skb\n"); + return 0; + } + skb_put( skb, len_param+len_value+3); + + /* Insert parameter length */ + frame[n++] = len_param; + + /* Insert parameter */ + memcpy( frame+n, param, len_param); n += len_param; + + /* Insert value length ( 2 byte little endian format, LSB first) */ + frame[n++] = len_value & 0xff; + frame[n++] = len_value >> 8; + + /* Insert value */ + switch (type) { + case 1: + memcpy( frame+n, value_char, len_value); n+=len_value; + break; + case 2: + frame[n++] = value_byte; + break; + case 3: + frame[n++] = value_short & 0xff; + frame[n++] = (value_short >> 8) & 0xff; + break; + default: + break; + } + ASSERT( n == (len_param+len_value+3), return 0;); + + return len_param+len_value+3; +} + +/* + * Function irlan_get_response_param (buf, param, value) + * + * Extracts a single parameter name/value pair from buffer and updates + * the buffer pointer to point to the next name/value pair. + * + */ +int irlan_get_response_param( __u8 *buf, char *name, char *value, int *len) +{ + __u8 name_len; + __u16 val_len; + int n=0; + + DEBUG( 4, "irlan_get_response_param()\n"); + + /* get length of parameter name ( 1 byte) */ + name_len = buf[n++]; + + if (name_len > 254) { + DEBUG( 0, __FUNCTION__ "(), name_len > 254\n"); + return -1; + } + + /* get parameter name */ + memcpy( name, buf+n, name_len); + name[ name_len] = '\0'; + n+=name_len; + + /* + * Get length of parameter value ( 2 bytes in little endian + * format) + */ + val_len = buf[n++] & 0xff; + val_len |= buf[n++] << 8; + + if (val_len > 1016) { + DEBUG( 0, __FUNCTION__ "(), parameter length to long\n"); + return -1; + } + + *len = val_len; + + /* get parameter value */ + memcpy( value, buf+n, val_len); + value[ val_len] = '\0'; + n+=val_len; + + DEBUG( 4, "Parameter: %s ", name); + DEBUG( 4, "Value: %s\n", value); + + return n; +} + +#ifdef CONFIG_PROC_FS +/* + * Function irlan_client_proc_read (buf, start, offset, len, unused) + * + * Give some info to the /proc file system + */ +static int irlan_proc_read( char *buf, char **start, off_t offset, + int len, int unused) +{ + struct irlan_cb *self; + + ASSERT( irlan != NULL, return 0;); + + len = 0; + + len += sprintf( buf+len, "IrLAN\n"); + + self = ( struct irlan_cb *) hashbin_get_first( irlan); + while ( self != NULL) { + ASSERT( self->magic == IRLAN_MAGIC, return len;); + + len += sprintf( buf+len, "ifname: %s, ", + self->ifname); + /* len += sprintf( buf+len, "state: %s, ", */ +/* irlan_client_state[ self->state]); */ + len += sprintf( buf+len, "saddr: %#08x\n", + self->saddr); + len += sprintf( buf+len, "daddr: %#08x\n", + self->daddr); + len += sprintf( buf+len, "tbusy: %s\n", self->dev.tbusy ? + "TRUE" : "FALSE"); + + len += sprintf( buf+len, "\n"); + + self = ( struct irlan_cb *) hashbin_get_next( irlan); + DEBUG( 4, "self=%p\n", self); + } + return len; +} +#endif + +/* + * Function print_ret_code (code) + * + * Print return code of request to peer IrLAN layer. + * + */ +void print_ret_code( __u8 code) +{ + switch( code) { + case 0: + printk( KERN_INFO "Success\n"); + break; + case 1: + printk( KERN_WARNING "Insufficient resources\n"); + break; + case 2: + printk( KERN_WARNING "Invalid command format\n"); + break; + case 3: + printk( KERN_WARNING "Command not supported\n"); + break; + case 4: + printk( KERN_WARNING "Parameter not supported\n"); + break; + case 5: + printk( KERN_WARNING "Value not supported\n"); + break; + case 6: + printk( KERN_WARNING "Not open\n"); + break; + case 7: + printk( KERN_WARNING "Authentication required\n"); + break; + case 8: + printk( KERN_WARNING "Invalid password\n"); + break; + case 9: + printk( KERN_WARNING "Protocol error\n"); + break; + case 255: + printk( KERN_WARNING "Asynchronous status\n"); + break; + } +} + +#ifdef MODULE + +MODULE_AUTHOR("Dag Brattli "); +MODULE_DESCRIPTION("The Linux IrDA LAN protocol"); + +/* + * Function init_module (void) + * + * Initialize the IrLAN module, this function is called by the + * modprobe(1) program. + */ +int init_module(void) +{ + DEBUG( 4, __FUNCTION__ "(), irlan.c\n"); + + irlan_init(); + + return 0; +} + +/* + * Function cleanup_module (void) + * + * Remove the IrLAN module, this function is called by the rmmod(1) + * program + */ +void cleanup_module(void) +{ + DEBUG( 4, "--> irlan, cleanup_module\n"); + /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ + + /* Free some memory */ + irlan_cleanup(); + + DEBUG( 4, "irlan, cleanup_module -->\n"); +} + +#endif /* MODULE */ + + diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c new file mode 100644 index 000000000000..c84aa0aa9165 --- /dev/null +++ b/net/irda/irlan/irlan_eth.c @@ -0,0 +1,396 @@ +/********************************************************************* + * + * Filename: irlan_eth.c + * Version: + * Description: + * Status: Experimental. + * Author: Dag Brattli + * Created at: Thu Oct 15 08:37:58 1998 + * Modified at: Wed Dec 9 11:14:53 1998 + * Modified by: Dag Brattli + * Sources: skeleton.c by Donald Becker + * slip.c by Laurence Culhane, + * Fred N. van Kempen, + * + * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include +#include +#include + +#include +#include +#include + +/* + * Function irlan_eth_init (dev) + * + * The network device initialization function. Called only once. + * + */ +int irlan_eth_init( struct device *dev) +{ + struct irlan_cb *self; + + DEBUG( 4, __FUNCTION__"()\n"); + + ASSERT( dev != NULL, return -1;); + + self = (struct irlan_cb *) dev->priv; + +/* dev->open = irlan_eth_open; */ +/* dev->stop = irlan_eth_close; */ + + dev->hard_start_xmit = irlan_eth_tx; + dev->get_stats = irlan_eth_get_stats; + dev->set_multicast_list = irlan_eth_set_multicast_list; + + dev->tbusy = 1; + + ether_setup( dev); + + dev->tx_queue_len = TTP_MAX_QUEUE; + + return 0; +} + +/* + * Function irlan_eth_open (dev) + * + * Start the IrLAN ether network device, this function will be called by + * "ifconfig irlan0 up". + * + */ +int irlan_eth_open( struct device *dev) +{ + /* struct irlan_cb *self = (struct irlan_cb *) dev->priv; */ + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( dev != NULL, return -1;); + + /* Ready to play! */ + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + /* MOD_INC_USE_COUNT; */ + + return 0; +} + +/* + * Function irlan_eth_close (dev) + * + * Stop the Client ether network device, his function will be called by + * ifconfig down. + */ +int irlan_eth_close(struct device *dev) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( dev != NULL, return -1;); + + /* Stop device */ + dev->tbusy = 1; + dev->start = 0; + + /* MOD_DEC_USE_COUNT; */ + + return 0; +} + +/* + * Function irlan_eth_tx (skb) + * + * Transmits ethernet frames over IrDA link. + * + */ +int irlan_eth_tx( struct sk_buff *skb, struct device *dev) +{ + struct irlan_cb *self; + + DEBUG( 4, __FUNCTION__ "()\n"); + + self = (struct irlan_cb *) dev->priv; + + ASSERT( self != NULL, return 0;); + ASSERT( self->magic == IRLAN_MAGIC, return 0;); + + if ( dev->tbusy) { + /* + * If we get here, some higher level has decided we are broken. + * There should really be a "kick me" function call instead. + */ + int tickssofar = jiffies - dev->trans_start; + DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n"); + + if ( tickssofar < 5) + return -EBUSY; + + dev->tbusy = 0; + dev->trans_start = jiffies; + } + /* + * If some higher layer thinks we've missed an tx-done interrupt + * we are passed NULL. Caution: dev_tint() handles the cli()/sti() + * itself. + */ + if ( skb == NULL) { + DEBUG( 0, __FUNCTION__ "(), skb==NULL\n"); + + return 0; + } + /* + * Check that we are connected + */ + if ( !self->connected) { + DEBUG( 4, __FUNCTION__ "(), Not connected, dropping frame!\n"); + + dev_kfree_skb( skb); + ++self->stats.tx_dropped; + + return 0; + } + + /* + * Block a timer-based transmit from overlapping. This could better be + * done with atomic_swap(1, dev->tbusy), but set_bit() works as well. + */ + if ( test_and_set_bit(0, (void*) &dev->tbusy) != 0) { + printk( KERN_WARNING "%s: Transmitter access conflict.\n", + dev->name); + return 0; + } + DEBUG( 4, "Room left at head: %d\n", skb_headroom(skb)); + DEBUG( 4, "Room left at tail: %d\n", skb_tailroom(skb)); + DEBUG( 4, "Required room: %d\n", IRLAN_MAX_HEADER); + + /* Skb headroom large enough to contain IR-headers? */ + if (( skb_headroom( skb) < IRLAN_MAX_HEADER) || ( skb_shared( skb))) { + struct sk_buff *new_skb = + skb_realloc_headroom(skb, IRLAN_MAX_HEADER); + ASSERT( new_skb != NULL, return 0;); + ASSERT( skb_headroom( new_skb) >= IRLAN_MAX_HEADER, return 0;); + + /* Free original skb, and use the new one */ + dev_kfree_skb( skb); + skb = new_skb; + } + + dev->trans_start = jiffies; + self->stats.tx_packets++; + self->stats.tx_bytes += skb->len; + + /* + * Now queue the packet in the transport layer + * FIXME: clean up the code below! DB + */ + if ( self->use_udata) { + irttp_udata_request( self->tsap_data, skb); + dev->tbusy = 0; + + return 0; + } + + if ( irttp_data_request( self->tsap_data, skb) == -1) { + /* + * IrTTPs tx queue is full, so we just have to drop the + * frame! You might think that we should just return -1 + * and don't deallocate the frame, but that is dangerous + * since it's possible that we have replaced the original + * skb with a new one with larger headroom, and that would + * really confuse do_dev_queue_xmit() in dev.c! I have + * tried :-) DB + */ + DEBUG( 4, __FUNCTION__ "(), Dropping frame\n"); + dev_kfree_skb( skb); + ++self->stats.tx_dropped; + + return 0; + } + dev->tbusy = 0; + + return 0; +} + +/* + * Function irlan_eth_rx (handle, skb) + * + * This function gets the data that is received on the data channel + * + */ +void irlan_eth_rx( void *instance, void *sap, struct sk_buff *skb) +{ + struct irlan_cb *self; + + self = ( struct irlan_cb *) instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + if (skb == NULL) { + ++self->stats.rx_dropped; + return; + } + IS_SKB( skb, return;); + ASSERT( skb->len > 1, return;); + + DEBUG( 4, "Got some ether data: length=%d\n", (int)skb->len); + + /* + * Adopt this frame! Important to set all these fields since they + * might have been previously set by the low level IrDA network + * device driver + */ + skb->dev = &self->dev; + skb->protocol=eth_type_trans( skb, skb->dev); /* Remove eth header */ + + netif_rx( skb); /* Eat it! */ + + self->stats.rx_packets++; + self->stats.rx_bytes += skb->len; +} + +/* + * Function irlan_eth_flow (status) + * + * Do flow control between IP/Ethernet and IrLAN/IrTTP. This is done by + * controlling the dev->tbusy variable. + */ +void irlan_eth_flow_indication( void *instance, void *sap, LOCAL_FLOW flow) +{ + struct irlan_cb *self; + struct device *dev; + + DEBUG( 4, __FUNCTION__ "()\n"); + + self = (struct irlan_cb *) instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + dev = &self->dev; + + ASSERT( dev != NULL, return;); + + switch ( flow) { + case FLOW_STOP: + DEBUG( 4, "IrLAN, stopping Ethernet layer\n"); + + dev->tbusy = 1; + break; + case FLOW_START: + /* + * Tell upper layers that its time to transmit frames again + */ + DEBUG( 4, "IrLAN, starting Ethernet layer\n"); + + dev->tbusy = 0; + + /* + * Ready to receive more frames, so schedule the network + * layer + */ + mark_bh( NET_BH); + break; + default: + DEBUG( 0, __FUNCTION__ "(), Unknown flow command!\n"); + } +} + +/* + * Function irlan_eth_rebuild_header (buff, dev, dest, skb) + * + * If we don't want to use ARP. Currently not used!! + * + */ +void irlan_eth_rebuild_header( void *buff, struct device *dev, + unsigned long dest, struct sk_buff *skb) +{ + struct ethhdr *eth = ( struct ethhdr *) buff; + + memcpy( eth->h_source, dev->dev_addr, dev->addr_len); + memcpy( eth->h_dest, dev->dev_addr, dev->addr_len); + + /* return 0; */ +} + +/* + * Function set_multicast_list (dev) + * + * Configure the filtering of the device + * + */ +#define HW_MAX_ADDRS 4 /* Must query to get it! */ +void irlan_eth_set_multicast_list( struct device *dev) +{ + struct irlan_cb *self; + + self = dev->priv; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + if (dev->flags&IFF_PROMISC) { + /* Enable promiscuous mode */ + DEBUG( 0, "Promiscous mode not implemented\n"); + /* outw(MULTICAST|PROMISC, ioaddr); */ + } + else if ((dev->flags&IFF_ALLMULTI) || dev->mc_count > HW_MAX_ADDRS) { + /* Disable promiscuous mode, use normal mode. */ + DEBUG( 4, __FUNCTION__ "(), Setting multicast filter\n"); + /* hardware_set_filter(NULL); */ + + irlan_set_multicast_filter( self, TRUE); + } + else if (dev->mc_count) { + DEBUG( 4, __FUNCTION__ "(), Setting multicast filter\n"); + /* Walk the address list, and load the filter */ + /* hardware_set_filter(dev->mc_list); */ + + irlan_set_multicast_filter( self, TRUE); + } + else { + DEBUG( 4, __FUNCTION__ "(), Clearing multicast filter\n"); + irlan_set_multicast_filter( self, FALSE); + } + + if ( dev->flags & IFF_BROADCAST) { + DEBUG( 4, __FUNCTION__ "(), Setting broadcast filter\n"); + irlan_set_broadcast_filter( self, TRUE); + } else { + DEBUG( 4, __FUNCTION__ "(), Clearing broadcast filter\n"); + irlan_set_broadcast_filter( self, FALSE); + } +} + +/* + * Function irlan_get_stats (dev) + * + * Get the current statistics for this device + * + */ +struct enet_statistics *irlan_eth_get_stats( struct device *dev) +{ + struct irlan_cb *self = (struct irlan_cb *) dev->priv; + + ASSERT( self != NULL, return NULL;); + ASSERT( self->magic == IRLAN_MAGIC, return NULL;); + + return &self->stats; +} diff --git a/net/irda/irlan/irlan_event.c b/net/irda/irlan/irlan_event.c new file mode 100644 index 000000000000..96fbccb58ef9 --- /dev/null +++ b/net/irda/irlan/irlan_event.c @@ -0,0 +1,48 @@ +/********************************************************************* + * + * Filename: irlan_event.c + * Version: + * Description: + * Status: Experimental. + * Author: Dag Brattli + * Created at: Tue Oct 20 09:10:16 1998 + * Modified at: Sat Dec 5 14:52:22 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include + +char *irlan_state[] = { + "IRLAN_IDLE", + "IRLAN_QUERY", + "IRLAN_CONN", + "IRLAN_INFO", + "IRLAN_MEDIA", + "IRLAN_OPEN", + "IRLAN_WAIT", + "IRLAN_ARB", + "IRLAN_DATA", + "IRLAN_CLOSE", + "IRLAN_SYNC", +}; + +void irlan_next_state( struct irlan_cb *self, + IRLAN_STATE state) +{ + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + self->state = state; +} diff --git a/net/irda/irlan/irlan_srv.c b/net/irda/irlan/irlan_srv.c new file mode 100644 index 000000000000..df4c6f954263 --- /dev/null +++ b/net/irda/irlan/irlan_srv.c @@ -0,0 +1,915 @@ +/********************************************************************* + * + * Filename: irlan_srv.c + * Version: 0.1 + * Description: IrDA LAN Access Protocol Implementation + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sun Aug 31 20:14:37 1997 + * Modified at: Mon Dec 14 19:10:49 1998 + * Modified by: Dag Brattli + * Sources: skeleton.c by Donald Becker + * slip.c by Laurence Culhane, + * Fred N. van Kempen, + * + * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* + * Private functions + */ +static void __irlan_server_close( struct irlan_cb *self); +static int irlan_server_dev_init( struct device *dev); +static int irlan_server_dev_open(struct device *dev); +static int irlan_server_dev_close(struct device *dev); +static void irlan_check_param( struct irlan_cb *self, char *param, char *value); + +/* + * Function irlan_server_init (dev) + * + * Allocates the master array. Called by modprobe(). + */ +__initfunc(int irlan_server_init( void)) +{ + DEBUG( 4, "--> irlan_server_init\n"); + + /* Register with IrLMP as a service */ + irlmp_register_layer( S_LAN, SERVER, FALSE, NULL); + + irlan_server_register(); + + DEBUG( 4, "irlan_server_init -->\n"); + + return 0; +} + +/* + * Function irlan_server_cleanup (void) + * + * Removes all instances of the IrLAN network device driver, and the + * master array. Called by rmmod(). + */ +void irlan_server_cleanup(void) +{ + DEBUG( 4, "--> irlan_server_cleanup\n"); + + irlmp_unregister_layer( S_LAN, SERVER); + + /* + * Delete hashbin and close all irlan client instances in it + */ + /* hashbin_delete( irlan, (FREE_FUNC) __irlan_server_close); */ + + DEBUG( 4, "irlan_server_cleanup -->\n"); +} + +/* + * Function irlan_server_open (void) + * + * This function allocates and opens a new instance of the IrLAN network + * device driver. + */ +struct irlan_cb *irlan_server_open(void) +{ + struct irlan_cb *self; + int result; + + DEBUG( 4, __FUNCTION__ "()\n"); + + /* + * Initialize the irlan_server structure. + */ + + self = kmalloc( sizeof(struct irlan_cb), GFP_ATOMIC); + if ( self == NULL) { + DEBUG( 0, __FUNCTION__ "(), Unable to kmalloc!\n"); + return NULL; + } + memset( self, 0, sizeof(struct irlan_cb)); + + /* + * Initialize local device structure + */ + self->magic = IRLAN_MAGIC; + + self->dev.name = self->ifname; + self->dev.init = irlan_server_dev_init; + self->dev.priv = (void *) self; + self->dev.next = NULL; + + if (( result = register_netdev( &self->dev)) != 0) { + DEBUG( 0, __FUNCTION__ "(), register_netdev() failed!\n"); + return NULL; + } + + irlan_next_state( self, IRLAN_IDLE); + + hashbin_insert( irlan , (QUEUE *) self, (int) self, NULL); + + return self; +} + +/* + * Function irlan_server_dev_init (dev) + * + * The network device initialization function. Called only once. + * + */ +static int irlan_server_dev_init( struct device *dev) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( dev != NULL, return -1;); + + irlan_eth_init( dev); + + /* Overrride some functions */ + dev->open = irlan_server_dev_open; + dev->stop = irlan_server_dev_close; + + /* + * OK, since we are emulating an IrLAN sever we will have to give + * ourself an ethernet address! + * FIXME: this must be more dynamically + */ + dev->dev_addr[0] = 0x40; + dev->dev_addr[1] = 0x00; + dev->dev_addr[2] = 0x00; + dev->dev_addr[3] = 0x00; + dev->dev_addr[4] = 0x23; + dev->dev_addr[5] = 0x45; + + return 0; +} + +/* + * Function irlan_server_dev_open (dev) + * + * Start the Servers ether network device, this function will be called by + * "ifconfig server0 up". + */ +static int irlan_server_dev_open( struct device *dev) +{ + /* struct irlan_cb *self = (struct irlan_cb *) dev->priv; */ + + DEBUG( 4, "irlan_server_dev_open()\n"); + + ASSERT( dev != NULL, return -1;); + + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + MOD_INC_USE_COUNT; + + return 0; +} + +static void __irlan_server_close( struct irlan_cb *self) +{ + DEBUG( 4, "--> irlan_server_close()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + /* + * Disconnect open TSAP connections + */ + if ( self->tsap_data) { + irttp_disconnect_request( self->tsap_data, NULL, P_HIGH); + + /* FIXME: this will close the tsap before the disconenct + * frame has been sent + */ + /* irttp_close_tsap( self->tsap_data); */ + } + if ( self->tsap_ctrl) { + irttp_disconnect_request( self->tsap_ctrl, NULL, P_HIGH); + + /* irttp_close_tsap( self->tsap_control); */ + } + + unregister_netdev( &self->dev); + + self->magic = ~IRLAN_MAGIC; + + kfree( self); + + DEBUG( 4, "irlan_server_close() -->\n"); +} + +/* + * Function irlan_server_close (self) + * + * This function closes and marks the IrLAN instance as not in use. + */ +void irlan_server_close( struct irlan_cb *self) +{ + struct irlan_cb *entry; + + DEBUG( 4, "--> irlan_server_close()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + entry = hashbin_remove( irlan, (int) self, NULL); + + ASSERT( entry == self, return;); + + __irlan_server_close( self); + + DEBUG( 4, "irlan_server_close() -->\n"); +} + +/* + * Function irlan_server_dev_close (dev) + * + * Stop the IrLAN ether network device, his function will be called by + * ifconfig down. + */ +static int irlan_server_dev_close( struct device *dev) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( dev != NULL, return -1;); + + dev->tbusy = 1; + dev->start = 0; + + MOD_DEC_USE_COUNT; + + return 0; +} + + +/* + * Function irlan_server_disconnect_indication (handle, reason, priv) + * + * Callback function for the IrTTP layer. Indicates a disconnection of + * the specified connection (handle) + * + */ +void irlan_server_disconnect_indication( void *instance, void *sap, + LM_REASON reason, + struct sk_buff *skb) +{ + struct irlan_info info; + struct irlan_cb *self; + struct tsap_cb *tsap; + + DEBUG( 4, __FUNCTION__ "(), Reason=%d\n", reason); + + self = ( struct irlan_cb *) instance; + tsap = ( struct tsap_cb *) sap; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + info.daddr = self->daddr; + + if ( tsap == self->tsap_data) { + DEBUG( 0, "IrLAN, data channel disconnected by peer!\n"); + self->connected = FALSE; + } else if ( tsap == self->tsap_ctrl) { + DEBUG( 0, "IrLAN, control channel disconnected by peer!\n"); + } else { + DEBUG( 0, "Error, disconnect on unknown handle!\n"); + } + + /* Stop IP from transmitting more packets */ + /* irlan_flow_indication( handle, FLOW_STOP, priv); */ + + irlan_do_server_event( self, IRLAN_LMP_DISCONNECT, NULL, NULL); +} + +/* + * Function irlan_server_control_data_indication (handle, skb) + * + * This function gets the data that is received on the control channel + * + */ +void irlan_server_control_data_indication( void *instance, void *sap, + struct sk_buff *skb) +{ + struct irlan_cb *self; + __u8 code; + + DEBUG( 4, __FUNCTION__ "()\n"); + + self = ( struct irlan_cb *) instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + ASSERT( skb != NULL, return;); + + code = skb->data[0]; + switch( code) { + case CMD_GET_PROVIDER_INFO: + DEBUG( 4, "Got GET_PROVIDER_INFO command!\n"); + irlan_do_server_event( self, IRLAN_GET_INFO_CMD, skb, NULL); + break; + + case CMD_GET_MEDIA_CHAR: + DEBUG( 4, "Got GET_MEDIA_CHAR command!\n"); + irlan_do_server_event( self, IRLAN_GET_MEDIA_CMD, skb, NULL); + break; + case CMD_OPEN_DATA_CHANNEL: + DEBUG( 4, "Got OPEN_DATA_CHANNEL command!\n"); + irlan_do_server_event( self, IRLAN_OPEN_DATA_CMD, skb, NULL); + break; + case CMD_FILTER_OPERATION: + DEBUG( 4, "Got FILTER_OPERATION command!\n"); + irlan_do_server_event( self, IRLAN_FILTER_CONFIG_CMD, skb, + NULL); + break; + case CMD_RECONNECT_DATA_CHAN: + DEBUG( 0, __FUNCTION__"(), Got RECONNECT_DATA_CHAN command\n"); + DEBUG( 0, __FUNCTION__"(), NOT IMPLEMENTED\n"); + break; + case CMD_CLOSE_DATA_CHAN: + DEBUG( 0, "Got CLOSE_DATA_CHAN command!\n"); + DEBUG( 0, __FUNCTION__"(), NOT IMPLEMENTED\n"); + break; + default: + DEBUG( 0, __FUNCTION__ "(), Unknown command!\n"); + break; + } +} + +/* + * Function irlan_server_connect_indication (handle, skb, priv) + * + * Got connection from peer IrLAN layer + * + */ +void irlan_server_connect_indication( void *instance, void *sap, + struct qos_info *qos, int max_sdu_size, + struct sk_buff *skb) +{ + struct irlan_cb *self; + struct irlan_info info; + struct tsap_cb *tsap; + + DEBUG( 4, __FUNCTION__ "()\n"); + + self = ( struct irlan_cb *) instance; + tsap = ( struct tsap_cb *) sap; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + info.tsap = tsap; + + if ( tsap == self->tsap_data) + irlan_do_server_event( self, IRLAN_DATA_CONNECT_INDICATION, + NULL, &info); + else + irlan_do_server_event( self, IRLAN_CONNECT_INDICATION, NULL, + &info); +} + +/* + * Function irlan_server_connect_response (handle) + * + * Accept incomming connection + * + */ +void irlan_server_connect_response( struct irlan_cb *self, + struct tsap_cb *tsap) +{ + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + /* FIXME: define this value */ + irttp_connect_response( tsap, 1518, NULL); +} + +/* + * Function irlan_server_get_provider_info (self) + * + * Send Get Provider Information command to peer IrLAN layer + * + */ +void irlan_server_get_provider_info( struct irlan_cb *self) +{ + struct sk_buff *skb; + __u8 *frame; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + skb = dev_alloc_skb( 64); + if (skb == NULL) { + DEBUG( 0,"irlan_server_get_provider_info: " + "Could not allocate an sk_buff of length %d\n", 64); + return; + } + + /* Reserve space for TTP, LMP, and LAP header */ + skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_put( skb, 2); + + frame = skb->data; + + frame[0] = CMD_GET_PROVIDER_INFO; + frame[1] = 0x00; /* Zero parameters */ + + irttp_data_request( self->tsap_ctrl, skb); +} + +/* + * Function irlan_parse_open_data_cmd (self, skb) + * + * + * + */ +int irlan_parse_open_data_cmd( struct irlan_cb *self, struct sk_buff *skb) +{ + int ret = RSP_SUCCESS; + + irlan_server_extract_params( self, CMD_OPEN_DATA_CHANNEL, skb); + + return ret; +} + +/* + * Function extract_params (skb) + * + * Extract all parameters from received buffer, then feed them to + * check_params for parsing + * + */ +int irlan_server_extract_params( struct irlan_cb *self, int cmd, + struct sk_buff *skb) +{ + __u8 *frame; + __u8 *ptr; + int count; + __u8 name_len; + __u16 val_len; + int i; + + ASSERT( skb != NULL, return -RSP_PROTOCOL_ERROR;); + + DEBUG( 4, __FUNCTION__ "(), skb->len=%d\n", (int)skb->len); + + ASSERT( self != NULL, return -RSP_PROTOCOL_ERROR;); + ASSERT( self->magic == IRLAN_MAGIC, return -RSP_PROTOCOL_ERROR;); + + if ( skb == NULL) { + DEBUG( 0, "extract_params: Got NULL skb!\n"); + return -RSP_PROTOCOL_ERROR; + } + frame = skb->data; + + /* How many parameters? */ + count = frame[1]; + + DEBUG( 4, "Got %d parameters\n", count); + + ptr = frame+2; + + /* For all parameters */ + for ( i=0; i 255) { + DEBUG( 0, "extract_params, name_len > 255\n"); + return -RSP_PROTOCOL_ERROR; + } + + /* get parameter name */ + memcpy( self->name, ptr, name_len); + self->name[ name_len] = '\0'; + ptr+=name_len; + + /* + * Get length of parameter value ( 2 bytes in little endian + * format) + */ + val_len = *ptr++ & 0xff; + val_len |= *ptr++ << 8; + + if (val_len > 1016) { + DEBUG( 0, + "extract_params, parameter length to long\n"); + return -RSP_PROTOCOL_ERROR; + } + + /* get parameter value */ + memcpy( self->value, ptr, val_len); + self->value[ val_len] = '\0'; + ptr+=val_len; + + DEBUG( 4, "Parameter: %s ", self->name); + DEBUG( 4, "Value: %s\n", self->value); + + irlan_check_param( self, self->name, self->value); + } + return RSP_SUCCESS; +} + +/* + * Function handle_filter_request (self, skb) + * + * Handle filter request from client peer device + * + */ +void handle_filter_request( struct irlan_cb *self, struct sk_buff *skb) +{ + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + if (( self->t.server.filter_type == IR_DIRECTED) && + ( self->t.server.filter_operation == DYNAMIC)) + { + DEBUG( 0, "Giving peer a dynamic Ethernet address\n"); + + self->t.server.mac_address[0] = 0x40; + self->t.server.mac_address[1] = 0x00; + self->t.server.mac_address[2] = 0x00; + self->t.server.mac_address[3] = 0x00; + self->t.server.mac_address[4] = 0x12; + self->t.server.mac_address[5] = 0x34; + + skb->data[0] = 0x00; /* Success */ + skb->data[1] = 0x03; + insert_param( skb, "FILTER_MODE", 1, "NONE", 0, 0); + insert_param( skb, "MAX_ENTRY", 3, NULL, 0, 0x0001); + insert_array_param( skb, "FILTER_ENTRY", self->t.server.mac_address, 6); + return; + } + + if (( self->t.server.filter_type == IR_DIRECTED) && + ( self->t.server.filter_mode == FILTER)) + { + DEBUG( 0, "Directed filter on\n"); + skb->data[0] = 0x00; /* Success */ + skb->data[1] = 0x00; + return; + } + if (( self->t.server.filter_type == IR_DIRECTED) && + ( self->t.server.filter_mode == NONE)) + { + DEBUG( 0, "Directed filter off\n"); + skb->data[0] = 0x00; /* Success */ + skb->data[1] = 0x00; + return; + } + + if (( self->t.server.filter_type == IR_BROADCAST) && + ( self->t.server.filter_mode == FILTER)) + { + DEBUG( 0, "Broadcast filter on\n"); + skb->data[0] = 0x00; /* Success */ + skb->data[1] = 0x00; + return; + } + if (( self->t.server.filter_type == IR_BROADCAST) && + ( self->t.server.filter_mode == NONE)) + { + DEBUG( 0, "Broadcast filter off\n"); + skb->data[0] = 0x00; /* Success */ + skb->data[1] = 0x00; + return; + } + if (( self->t.server.filter_type == IR_MULTICAST) && + ( self->t.server.filter_mode == FILTER)) + { + DEBUG( 0, "Multicast filter on\n"); + skb->data[0] = 0x00; /* Success */ + skb->data[1] = 0x00; + return; + } + if (( self->t.server.filter_type == IR_MULTICAST) && + ( self->t.server.filter_mode == NONE)) + { + DEBUG( 0, "Multicast filter off\n"); + skb->data[0] = 0x00; /* Success */ + skb->data[1] = 0x00; + return; + } + if (( self->t.server.filter_type == IR_MULTICAST) && + ( self->t.server.filter_operation == GET)) + { + DEBUG( 0, "Multicast filter get\n"); + skb->data[0] = 0x00; /* Success? */ + skb->data[1] = 0x02; + insert_param( skb, "FILTER_MODE", 1, "NONE", 0, 0); + insert_param( skb, "MAX_ENTRY", 3, NULL, 0, 16); + return; + } + skb->data[0] = 0x00; /* Command not supported */ + skb->data[1] = 0x00; + + DEBUG( 0, "Not implemented!\n"); +} + +/* + * Function check_request_param (self, param, value) + * + * Check parameters in request from peer device + * + */ +static void irlan_check_param( struct irlan_cb *self, char *param, char *value) +{ + __u8 *bytes; + + DEBUG( 4, __FUNCTION__ "()\n"); + + bytes = value; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + DEBUG( 4, "%s, %s\n", param, value); + + /* + * This is experimental!! DB. + */ + if ( strcmp( param, "MODE") == 0) { + DEBUG( 0, __FUNCTION__ "()\n"); + self->use_udata = TRUE; + return; + } + + /* + * FILTER_TYPE + */ + if ( strcmp( param, "FILTER_TYPE") == 0) { + if ( strcmp( value, "DIRECTED") == 0) { + self->t.server.filter_type = IR_DIRECTED; + return; + } + if ( strcmp( value, "MULTICAST") == 0) { + self->t.server.filter_type = IR_MULTICAST; + return; + } + if ( strcmp( value, "BROADCAST") == 0) { + self->t.server.filter_type = IR_BROADCAST; + return; + } + } + /* + * FILTER_MODE + */ + if ( strcmp( param, "FILTER_MODE") == 0) { + if ( strcmp( value, "ALL") == 0) { + self->t.server.filter_mode = ALL; + return; + } + if ( strcmp( value, "FILTER") == 0) { + self->t.server.filter_mode = FILTER; + return; + } + if ( strcmp( value, "NONE") == 0) { + self->t.server.filter_mode = FILTER; + return; + } + } + /* + * FILTER_OPERATION + */ + if ( strcmp( param, "FILTER_OPERATION") == 0) { + if ( strcmp( value, "DYNAMIC") == 0) { + self->t.server.filter_operation = DYNAMIC; + return; + } + if ( strcmp( value, "GET") == 0) { + self->t.server.filter_operation = GET; + return; + } + } +} + +/* + * Function irlan_server_send_reply (self, info) + * + * Send reply to query to peer IrLAN layer + * + */ +void irlan_server_send_reply( struct irlan_cb *self, int command, int ret_code) +{ + struct sk_buff *skb; + + DEBUG( 4, "irlan_server_send_reply()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRLAN_MAGIC, return;); + + skb = dev_alloc_skb( 128); + if (skb == NULL) { + DEBUG( 0,"irlan_server_send_reply: " + "Could not allocate an sk_buff of length %d\n", 128); + return; + } + + /* Reserve space for TTP, LMP, and LAP header */ + skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_put( skb, 2); + + switch ( command) { + case CMD_GET_PROVIDER_INFO: + skb->data[0] = 0x00; /* Success */ + skb->data[1] = 0x02; /* 2 parameters */ + insert_param( skb, "MEDIA", 1, "802.3", 0, 0); + insert_param( skb, "IRLAN_VER", 3, NULL, 0, 0x0101); + break; + case CMD_GET_MEDIA_CHAR: + skb->data[0] = 0x00; /* Success */ + skb->data[1] = 0x05; /* 5 parameters */ + insert_param( skb, "FILTER_TYPE", 1, "DIRECTED", 0, 0); + insert_param( skb, "FILTER_TYPE", 1, "BROADCAST", 0, 0); + insert_param( skb, "FILTER_TYPE", 1, "MULTICAST", 0, 0); + insert_param( skb, "ACCESS_TYPE", 1, "DIRECTED", 0, 0); + insert_param( skb, "MAX_FRAME", 3, NULL, 0, 0x05ee); + break; + case CMD_OPEN_DATA_CHANNEL: + skb->data[0] = 0x00; /* Success */ + skb->data[1] = 0x02; /* 2 parameters */ + insert_param( skb, "DATA_CHAN", 2, NULL, self->stsap_sel_data, 0); + insert_param( skb, "RECONNECT_KEY", 1, "LINUX RULES!", 0, 0); + break; + case CMD_FILTER_OPERATION: + handle_filter_request( self, skb); + break; + default: + DEBUG( 0, __FUNCTION__ "(), Unknown command!\n"); + break; + } + + irttp_data_request( self->tsap_ctrl, skb); +} + +/* + * Function irlan_server_register(void) + * + * Register server support so we can accept incomming connections. We + * must register both a TSAP for control and data + * + */ +void irlan_server_register(void) +{ + struct notify_t notify; + struct irlan_cb *self; + struct ias_object *obj; + struct tsap_cb *tsap; + + DEBUG( 4, __FUNCTION__ "()\n"); + + /* + * Open irlan_server instance + */ + self = irlan_server_open(); + if ( !self || self->magic != IRLAN_MAGIC) { + DEBUG( 0, __FUNCTION__"(), Unable to open server!\n"); + return; + } + /* + * First register well known control TSAP + */ + irda_notify_init( ¬ify); + notify.data_indication = irlan_server_control_data_indication; + notify.connect_indication = irlan_server_connect_indication; + notify.disconnect_indication = irlan_server_disconnect_indication; + notify.instance = self; + strncpy( notify.name, "IrLAN srv. ctrl", 16); + + /* FIXME: should not use a static value here! */ + tsap = irttp_open_tsap( TSAP_IRLAN, 1, ¬ify); + if ( tsap == NULL) { + DEBUG( 0, __FUNCTION__ "(), Got no handle!!\n"); + return; + } + self->tsap_ctrl = tsap; + + /* + * Now register data TSAP + */ + irda_notify_init( ¬ify); + notify.data_indication = irlan_eth_rx; + notify.udata_indication = irlan_eth_rx; + notify.connect_indication = irlan_server_connect_indication; + notify.disconnect_indication = irlan_server_disconnect_indication; + notify.instance = self; + strncpy( notify.name, "IrLAN srv. data", 16); + + /* + * Register well known address with IrTTP + */ + tsap = irttp_open_tsap( LSAP_ANY, DEFAULT_INITIAL_CREDIT, ¬ify); + if ( tsap == NULL) { + DEBUG( 0, __FUNCTION__ "(), Got no handle!\n"); + return; + } + self->tsap_data = tsap; + + /* + * This is the data TSAP selector which we will pass to the client + * when the client ask for it. + */ + self->stsap_sel_data = tsap->stsap_sel; + ASSERT( self->stsap_sel_data > 0, return;); + + DEBUG( 0, "irlan_server_register(), Using Source TSAP selector=%02x\n", + self->stsap_sel_data); + + /* + * Register with LM-IAS + */ + obj = irias_new_object( "IrLAN", IAS_IRLAN_ID); + irias_add_integer_attrib( obj, "IrDA:TinyTP:LsapSel", TSAP_IRLAN); + irias_insert_object( obj); + + obj = irias_new_object( "PnP", IAS_PNP_ID); + irias_add_string_attrib( obj, "Name", "Linux"); + irias_add_string_attrib( obj, "DeviceID", "HWP19F0"); + irias_add_integer_attrib( obj, "CompCnt", 2); + irias_add_string_attrib( obj, "Comp#01", "PNP8294"); + irias_add_string_attrib( obj, "Comp#01", "PNP8389"); + irias_add_string_attrib( obj, "Manufacturer", "Linux/IR Project"); + irias_insert_object( obj); +} + +#ifdef MODULE + +MODULE_AUTHOR("Dag Brattli "); +MODULE_DESCRIPTION("The Linux IrDA LAN Server protocol"); + +/* + * Function init_module (void) + * + * Initialize the IrLAN module, this function is called by the + * modprobe(1) program. + */ +int init_module(void) +{ +/* int result; */ + + DEBUG( 4, "--> IrLAN irlan_server: init_module\n"); + + irlan_server_init(); + + DEBUG( 4, "IrLAN irlan_server: init_module -->\n"); + + return 0; +} + +/* + * Function cleanup_module (void) + * + * Remove the IrLAN module, this function is called by the rmmod(1) + * program + */ +void cleanup_module(void) +{ + DEBUG( 4, "--> irlan_server, cleanup_module\n"); + /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ + + /* Free some memory */ + irlan_server_cleanup(); + + DEBUG( 4, "irlan_server, cleanup_module -->\n"); +} + +#endif /* MODULE */ diff --git a/net/irda/irlan/irlan_srv_event.c b/net/irda/irlan/irlan_srv_event.c new file mode 100644 index 000000000000..6ad8d2f46bff --- /dev/null +++ b/net/irda/irlan/irlan_srv_event.c @@ -0,0 +1,268 @@ +/********************************************************************* + * + * Filename: irlan_srv_event.c + * Version: 0.1 + * Description: IrLAN Server FSM (Finite State Machine) + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sun Aug 31 20:14:37 1997 + * Modified at: Wed Dec 9 02:39:05 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include +#include +#include + +#include +#include + +static int irlan_server_state_idle ( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb, + struct irlan_info *info); +static int irlan_server_state_info ( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb, + struct irlan_info *info); +static int irlan_server_state_open ( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb, + struct irlan_info *info); +static int irlan_server_state_data ( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb, + struct irlan_info *info); + +static int (*state[])( struct irlan_cb *self, IRLAN_EVENT event, + struct sk_buff *skb, struct irlan_info *info) = +{ + irlan_server_state_idle, + NULL, /* Query */ + NULL, /* Info */ + irlan_server_state_info, + NULL, /* Media */ + irlan_server_state_open, + NULL, /* Wait */ + NULL, /* Arb */ + irlan_server_state_data, + NULL, /* Close */ + NULL, /* Sync */ +}; + +void irlan_do_server_event( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb, + struct irlan_info *info) +{ + (*state[ self->state]) ( self, event, skb, info); +} + +/* + * Function irlan_server_state_idle (event, skb, info) + * + * IDLE, We are waiting for an indication that there is a provider + * available. + */ +static int irlan_server_state_idle( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb, + struct irlan_info *info) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return -1;); + + switch( event) { + case IRLAN_CONNECT_INDICATION: + ASSERT( info != NULL, return 0;); + irlan_server_connect_response( self, info->tsap); + irlan_next_state( self, IRLAN_INFO); + break; + default: + DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", + event); + break; + } + if ( skb) { + dev_kfree_skb( skb); + } + return 0; +} + +/* + * Function irlan_server_state_info (self, event, skb, info) + * + * INFO, We have issued a GetInfo command and is awaiting a reply. + */ +static int irlan_server_state_info( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb, + struct irlan_info *info) +{ + int ret; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return -1;); + + switch( event) { + case IRLAN_GET_INFO_CMD: + irlan_server_send_reply( self, CMD_GET_PROVIDER_INFO, + RSP_SUCCESS); + /* Keep state */ + break; + + case IRLAN_GET_MEDIA_CMD: + irlan_server_send_reply( self, CMD_GET_MEDIA_CHAR, + RSP_SUCCESS); + /* Keep state */ + break; + + case IRLAN_OPEN_DATA_CMD: + ret = irlan_parse_open_data_cmd( self, skb); + irlan_server_send_reply( self, CMD_OPEN_DATA_CHANNEL, ret); + + if ( ret == RSP_SUCCESS) + irlan_next_state( self, IRLAN_OPEN); + break; + case IRLAN_LMP_DISCONNECT: + case IRLAN_LAP_DISCONNECT: + irlan_next_state( self, IRLAN_IDLE); + break; + default: + DEBUG( 0, "irlan_server_state_info, Unknown event %d\n", + event); + break; + } + if ( skb) { + dev_kfree_skb( skb); + } + + return 0; +} + +/* + * Function irlan_server_state_open (self, event, skb, info) + * + * OPEN, The client has issued a OpenData command and is awaiting a + * reply + * + */ +static int irlan_server_state_open( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb, + struct irlan_info *info) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return -1;); + + switch( event) { + case IRLAN_FILTER_CONFIG_CMD: + irlan_server_extract_params( self, CMD_FILTER_OPERATION, skb); + irlan_server_send_reply( self, CMD_FILTER_OPERATION, + RSP_SUCCESS); + /* Keep state */ + break; + + case IRLAN_DATA_CONNECT_INDICATION: + DEBUG( 4, "DATA_CONNECT_INDICATION\n"); + irlan_next_state( self, IRLAN_DATA); + irlan_server_connect_response( self, info->tsap); + break; + + case IRLAN_LMP_DISCONNECT: + case IRLAN_LAP_DISCONNECT: + irlan_next_state( self, IRLAN_IDLE); + break; + default: + DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", + event); + break; + } + + if ( skb) { + dev_kfree_skb( skb); + } + + return 0; +} + +/* + * Function irlan_server_state_data (self, event, skb, info) + * + * DATA, The data channel is connected, allowing data transfers between + * the local and remote machines. + * + */ +static int irlan_server_state_data( struct irlan_cb *self, + IRLAN_EVENT event, + struct sk_buff *skb, + struct irlan_info *info) +{ + struct irmanager_event mgr_event; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return -1;); + ASSERT( self->magic == IRLAN_MAGIC, return -1;); + + switch( event) { + case IRLAN_FILTER_CONFIG_CMD: + irlan_server_extract_params( self, CMD_FILTER_OPERATION, skb); + irlan_server_send_reply( self, CMD_FILTER_OPERATION, + RSP_SUCCESS); + + /* Make sure the code below only runs once */ + if ( !self->connected) { + mgr_event.event = EVENT_IRLAN_START; + sprintf( mgr_event.devname, "%s", self->ifname); + irmanager_notify( &mgr_event); + + self->connected = TRUE; + } + break; + + case IRLAN_LMP_DISCONNECT: + case IRLAN_LAP_DISCONNECT: + mgr_event.event = EVENT_IRLAN_STOP; + sprintf( mgr_event.devname, "%s", self->ifname); + irmanager_notify( &mgr_event); + + irlan_next_state( self, IRLAN_IDLE); + break; + default: + DEBUG( 0, "irlan_server_state_data, Unknown event %d\n", + event); + break; + } + if ( skb) { + dev_kfree_skb( skb); + } + + return 0; +} + + + + + + + + + + diff --git a/net/irda/irlap.c b/net/irda/irlap.c new file mode 100644 index 000000000000..100348b5e354 --- /dev/null +++ b/net/irda/irlap.c @@ -0,0 +1,1184 @@ +/********************************************************************* + * + * Filename: irlap.c + * Version: 0.3 + * Description: An IrDA LAP driver for Linux + * Status: Experimental. + * Author: Dag Brattli + * Created at: Mon Aug 4 20:40:53 1997 + * Modified at: Mon Dec 14 11:54:42 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli , + * All Rights Reserved. + * + * This program is free software; you can redistribute iyt 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. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +hashbin_t *irlap = NULL; + +static void __irlap_close( struct irlap_cb *self); + +#ifdef CONFIG_PROC_FS +int irlap_proc_read( char *buf, char **start, off_t offset, int len, + int unused); + +#endif /* CONFIG_PROC_FS */ + +__initfunc(int irlap_init( void)) +{ + /* Allocate master array */ + irlap = hashbin_new( HB_LOCAL); + if ( irlap == NULL) { + printk( KERN_WARNING "IrLAP: Can't allocate irlap hashbin!\n"); + return -ENOMEM; + } + +#ifdef CONFIG_IRDA_COMPRESSION + irlap_compressors = hashbin_new( HB_LOCAL); + if ( irlap_compressors == NULL) { + printk( KERN_WARNING "IrLAP: Can't allocate compressors hashbin!\n"); + return -ENOMEM; + } +#endif + + return 0; +} + +void irlap_cleanup(void) +{ + ASSERT( irlap != NULL, return;); + + hashbin_delete( irlap, (FREE_FUNC) __irlap_close); + +#ifdef CONFIG_IRDA_COMPRESSION + hashbin_delete( irlap_compressors, (FREE_FUNC) kfree); +#endif +} + +/* + * Function irlap_open (driver) + * + * Initialize IrLAP layer + * + */ +struct irlap_cb *irlap_open( struct irda_device *irdev) +{ + struct irlap_cb *self; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( irdev != NULL, return NULL;); + ASSERT( irdev->magic == IRDA_DEVICE_MAGIC, return NULL;); + + /* Initialize the irlap structure. */ + self = kmalloc( sizeof( struct irlap_cb), GFP_KERNEL); + if ( self == NULL) + return NULL; + + memset( self, 0, sizeof(struct irlap_cb)); + self->magic = LAP_MAGIC; + + /* Make a binding between the layers */ + self->irdev = irdev; + self->netdev = &irdev->netdev; + + irlap_next_state( self, LAP_OFFLINE); + + /* Initialize transmitt queue */ + skb_queue_head_init( &self->tx_list); + skb_queue_head_init( &self->wx_list); + + /* My unique IrLAP device address! :-) */ + self->saddr = jiffies; + + /* Generate random connection address for this session */ + self->caddr = jiffies & 0xfe; + + init_timer( &self->slot_timer); + init_timer( &self->query_timer); + init_timer( &self->discovery_timer); + init_timer( &self->final_timer); + init_timer( &self->poll_timer); + init_timer( &self->wd_timer); + init_timer( &self->backoff_timer); + + irlap_apply_default_connection_parameters( self); + + irlap_next_state( self, LAP_NDM); + + hashbin_insert( irlap, (QUEUE *) self, self->saddr, NULL); + + irlmp_register_irlap( self, self->saddr, &self->notify); + + DEBUG( 4, "irlap_open -->\n"); + + return self; +} + +/* + * Function __irlap_close (self) + * + * Remove IrLAP and all allocated memory. Stop any pending timers. + * + */ +static void __irlap_close( struct irlap_cb *self) +{ + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + /* Stop timers */ + del_timer( &self->slot_timer); + del_timer( &self->query_timer); + del_timer( &self->discovery_timer); + del_timer( &self->final_timer); + del_timer( &self->poll_timer); + del_timer( &self->wd_timer); + del_timer( &self->backoff_timer); + + irlap_flush_all_queues( self); + + self->irdev = NULL; + self->magic = ~LAP_MAGIC; + + kfree( self); +} + +/* + * Function irlap_close () + * + * + * + */ +void irlap_close( struct irlap_cb *self) +{ + struct irlap_cb *lap; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + irlap_disconnect_indication( self, LAP_DISC_INDICATION); + + irlmp_unregister_irlap( self->saddr); + self->notify.instance = NULL; + + /* Be sure that we manage to remove ourself from the hash */ + lap = hashbin_remove( irlap, self->saddr, NULL); + if ( !lap) { + DEBUG( 0, __FUNCTION__ "(), Didn't find myself!\n"); + return; + } + __irlap_close( lap); +} + +/* + * Function irlap_connect_indication () + * + * Another device is attempting to make a connection + * + */ +void irlap_connect_indication( struct irlap_cb *self, struct sk_buff *skb) +{ + DEBUG( 4, "irlap_connect_indication()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + irlap_init_qos_capabilities( self, NULL); /* No user QoS! */ + + irlmp_link_connect_indication( self->notify.instance, &self->qos_tx, + skb); +} + +/* + * Function irlap_connect_response (void) + * + * Service user has accepted incomming connection + * + */ +void irlap_connect_response( struct irlap_cb *self, struct sk_buff *skb) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + irlap_do_event( self, CONNECT_RESPONSE, skb, NULL); +} + +/* + * Function irlap_connect_request (daddr, qos, sniff) + * + * Request connection with another device, sniffing is not implemented + * yet. + */ +void irlap_connect_request( struct irlap_cb *self, __u32 daddr, + struct qos_info *qos_user, int sniff) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + self->daddr = daddr; + + /* + * If the service user specifies QoS values for this connection, + * then use them + */ + irlap_init_qos_capabilities( self, qos_user); + + if ( self->state == LAP_NDM) { + irlap_do_event( self, CONNECT_REQUEST, NULL, NULL); + } else { + DEBUG( 0, "irlap_connect_request() Wrong state!\n"); + + irlap_disconnect_indication( self, LAP_MEDIA_BUSY); + } + +} + +/* + * Function irlap_connect_confirm (void) + * + * Connection request is accepted + * + */ +void irlap_connect_confirm( struct irlap_cb *self, struct sk_buff *skb) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + irlmp_link_connect_confirm( self->notify.instance, &self->qos_tx, skb); +} + +/* + * Function irlap_data_indication (skb) + * + * Received data frames from IR-port, so we just pass them up to + * IrLMP for further processing + * + */ +inline void irlap_data_indication( struct irlap_cb *self, struct sk_buff *skb) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + + IS_SKB( skb, return;); + + /* Hide LAP header from IrLMP layer */ + skb_pull( skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER); + +#ifdef CONFIG_IRDA_COMPRESSION + if ( self->qos_tx.compression.value) { + skb = irlap_decompress_frame( self, skb); + if ( !skb) { + DEBUG( 0, __FUNCTION__ "(), Decompress error!\n"); + return; + } + } +#endif + + irlmp_link_data_indication( self->notify.instance, LAP_RELIABLE, skb); +} + +/* + * Function irlap_unit_data_indication (self, skb) + * + * Received some data that was sent unreliable + * + */ +void irlap_unit_data_indication( struct irlap_cb *self, struct sk_buff *skb) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + + IS_SKB( skb, return;); + + /* Hide LAP header from IrLMP layer */ + skb_pull( skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER); + +#ifdef CONFIG_IRDA_COMPRESSION + if ( self->qos_tx.compression.value) { + + skb = irlap_decompress_frame( self, skb); + if ( !skb) { + DEBUG( 0, __FUNCTION__ "(), Decompress error!\n"); + return; + } + } +#endif + + irlmp_link_data_indication( self->notify.instance, LAP_UNRELIABLE, + skb); +} + +/* + * Function irlap_data_request (self, skb) + * + * Queue data for transmission, must wait until XMIT state + * + */ +inline void irlap_data_request( struct irlap_cb *self, struct sk_buff *skb, + int reliable) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + + IS_SKB( skb, return;); + + DEBUG( 4, "irlap_data_request: tx_list=%d\n", + skb_queue_len( &self->tx_list)); + +#ifdef CONFIG_IRDA_COMPRESSION + if ( self->qos_tx.compression.value) { + skb = irlap_compress_frame( self, skb); + if ( !skb) { + DEBUG( 0, __FUNCTION__ "(), Compress error!\n"); + return; + } + } +#endif + + ASSERT( skb_headroom( skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER), + return;); + skb_push( skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER); + + /* + * Must set frame format now so that the rest of the code knows + * if its dealing with an I or an UI frame + */ + if ( reliable) + skb->data[1] = I_FRAME; + else { + DEBUG( 4, __FUNCTION__ "(), queueing unreliable frame\n"); + skb->data[1] = UI_FRAME; + } + + IS_SKB( skb, return;); + + /* + * Send event if this frame only if we are in the right state + * FIXME: udata should be sent first! (skb_queue_head?) + */ + if (( self->state == LAP_XMIT_P) || (self->state == LAP_XMIT_S)) { + /* + * Check if the transmit queue contains some unsent frames, + * and if so, make sure they are sent first + */ + if ( !skb_queue_empty( &self->tx_list)) { + skb_queue_tail( &self->tx_list, skb); + skb = skb_dequeue( &self->tx_list); + + ASSERT( skb != NULL, return;); + IS_SKB( skb, return;); + } + irlap_do_event( self, SEND_I_CMD, skb, NULL); + } else + skb_queue_tail( &self->tx_list, skb); + +} + +/* + * Function irlap_disconnect_request (void) + * + * Request to disconnect connection by service user + */ +void irlap_disconnect_request( struct irlap_cb *self) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + irlap_do_event( self, DISCONNECT_REQUEST, NULL, NULL); +} + +/* + * Function irlap_disconnect_indication (void) + * + * Disconnect request from other device + * + */ +void irlap_disconnect_indication( struct irlap_cb *self, LAP_REASON reason) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + +#ifdef CONFIG_IRDA_COMPRESSION + irda_free_compression( self); +#endif + + /* Flush queues */ + irlap_flush_all_queues( self); + + switch( reason) { + case LAP_RESET_INDICATION: + DEBUG( 0, "Sending reset request!\n"); + irlap_do_event( self, RESET_REQUEST, NULL, NULL); + break; + case LAP_NO_RESPONSE: + case LAP_DISC_INDICATION: + case LAP_FOUND_NONE: + case LAP_MEDIA_BUSY: + irlmp_link_disconnect_indication( self->notify.instance, + self, reason, NULL); + break; + default: + DEBUG( 0, __FUNCTION__ "(), Reason %d not implemented!\n", + reason); + } +} + +/* + * Function irlap_discovery_request (gen_addr_bit) + * + * Start one single discovery operation. + * + */ +void irlap_discovery_request( struct irlap_cb *self, DISCOVERY *discovery) +{ + struct irlap_info info; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + ASSERT( discovery != NULL, return;); + + /* + * Discovery is only possible in NDM mode + */ + if ( self->state == LAP_NDM) { + ASSERT( self->discovery_log == NULL, return;); + self->discovery_log= hashbin_new( HB_LOCAL); + + info.S = 6; /* Number of slots */ + info.s = 0; /* Current slot */ + + self->discovery_cmd = discovery; + info.discovery = discovery; + + irlap_do_event( self, DISCOVERY_REQUEST, NULL, &info); + } else { + DEBUG( 4, __FUNCTION__ + "(), discovery only possible in NDM mode\n"); + irlap_discovery_confirm( self, NULL); + } +} + + +/* + * Function irlap_discovery_confirm (log) + * + * A device has been discovered in front of this station, we + * report directly to LMP. + */ +void irlap_discovery_confirm( struct irlap_cb *self, + hashbin_t *discovery_log) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + ASSERT( self->notify.instance != NULL, return;); + + /* Inform IrLMP */ + irlmp_link_discovery_confirm( self->notify.instance, discovery_log); + + /* + * IrLMP has now the responsibilities for the discovery_log + */ + self->discovery_log = NULL; +} + +/* + * Function irlap_discovery_indication (log) + * + * Somebody is trying to discover us! + * + */ +inline void irlap_discovery_indication( struct irlap_cb *self, + DISCOVERY *discovery) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + ASSERT( discovery != NULL, return;); + + ASSERT( self->notify.instance != NULL, return;); + + irlmp_discovery_indication( self->notify.instance, discovery); +} + +/* + * Function irlap_status_indication (quality_of_link) + * + * + * + */ +void irlap_status_indication( int quality_of_link) +{ + switch( quality_of_link) { + case STATUS_NO_ACTIVITY: + printk( KERN_INFO "IrLAP, no activity on link!\n"); + break; + case STATUS_NOISY: + printk( KERN_INFO "IrLAP, noisy link!\n"); + break; + default: + break; + } + /* TODO: layering violation! */ + irlmp_status_indication( quality_of_link, NO_CHANGE); +} + +/* + * Function irlap_reset_indication (void) + * + * + * + */ +void irlap_reset_indication( struct irlap_cb *self) +{ + DEBUG( 0, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + irlap_do_event( self, RESET_REQUEST, NULL, NULL); +} + +/* + * Function irlap_reset_confirm (void) + * + * + * + */ +void irlap_reset_confirm(void) +{ + DEBUG( 0, __FUNCTION__ "() Not implemented!\n"); +} + +/* + * Function irlap_generate_rand_time_slot (S, s) + * + * Generate a random time slot between s and S-1 where + * S = Number of slots (0 -> S-1) + * s = Current slot + */ +int irlap_generate_rand_time_slot( int S, int s) +{ + int slot; + + ASSERT(( S - s) > 0, return 0;); + + slot = s + jiffies % (S-s); + + DEBUG( 4, "S=%d, s=%d, rnd=%d\n", S, s, slot); + + ASSERT(( slot >= s) || ( slot < S), return 0;); + + return slot; +} + +/* + * Function irlap_update_nr_received (nr) + * + * Remove all acknowledged frames in current window queue. This code is + * not intuitive and you should not try to change it. If you think it + * contains bugs, please mail a patch to the author instead. + */ +void irlap_update_nr_received( struct irlap_cb *self, int nr) +{ + struct sk_buff *skb = NULL; + int count = 0; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + /* + * Remove all the ack-ed frames from the window queue. + */ + + DEBUG( 4, "--> wx_list=%d, va=%d, nr=%d\n", + skb_queue_len( &self->wx_list), self->va, nr); + + /* + * Optimize for the common case. It is most likely that the receiver + * will acknowledge all the frames we have sent! So in that case we + * delete all frames stored in window. + */ + if ( nr == self->vs) { + while (( skb = skb_dequeue( &self->wx_list)) != NULL) { + dev_kfree_skb(skb); + } + /* The last acked frame is the next to send minus one */ + self->va = nr - 1; + } else { + /* Remove all acknowledged frames in current window */ + while (( skb_peek( &self->wx_list) != NULL) && + ((( self->va+1) % 8) != nr)) + { + skb = skb_dequeue( &self->wx_list); + dev_kfree_skb(skb); + + self->va = (self->va + 1) % 8; + count++; + } + + DEBUG( 4, "irlap_update_nr_received(), removed %d\n", count); + DEBUG( 4, "wx_list=%d, va=%d, nr=%d -->\n", + skb_queue_len( &self->wx_list), self->va, nr); + } + + /* Advance window */ + self->window = self->window_size - skb_queue_len( &self->wx_list); +} + +/* + * Function irlap_validate_ns_received (ns) + * + * Validate the next to send (ns) field from received frame. + */ +int irlap_validate_ns_received( struct irlap_cb *self, int ns) +{ + ASSERT( self != NULL, return -ENODEV;); + ASSERT( self->magic == LAP_MAGIC, return -EBADR;); + + /* + * ns as expected? + */ + if ( ns == self->vr) { + DEBUG( 4, "*** irlap_validate_ns_received: expected!\n"); + return NS_EXPECTED; + } + /* + * Stations are allowed to treat invalid NS as unexpected NS + * IrLAP, Recv ... with-invalid-Ns. p. 84 + */ + return NS_UNEXPECTED; + + /* return NR_INVALID; */ +} +/* + * Function irlap_validate_nr_received (nr) + * + * Validate the next to receive (nr) field from received frame. + * + */ +int irlap_validate_nr_received( struct irlap_cb *self, int nr) +{ + ASSERT( self != NULL, return -ENODEV;); + ASSERT( self->magic == LAP_MAGIC, return -EBADR;); + + /* + * nr as expected? + */ + if ( nr == self->vs) { + DEBUG( 4, "*** irlap_validate_nr_received: expected!\n"); + return NR_EXPECTED; + } + + /* + * unexpected nr? (but within current window), first we check if the + * ns numbers of the frames in the current window wrap. + */ + if ( self->va < self->vs) { + if (( nr >= self->va) && ( nr <= self->vs)) { + DEBUG( 4, "*** irlap_validate_nr_received:" + " unexpected nr, no wrap\n"); + return NR_UNEXPECTED; + } + } else { + if (( nr >= self->va) || ( nr <= self->vs)) { + DEBUG( 4, "*** irlap_validate_nr_received:" + " unexpected nr, wrapped\n"); + return NR_UNEXPECTED; + } + } + + /* Invalid nr! */ + DEBUG( 4, "irlap_validate_nr_received: invalid nr!, " + " vs=%d, vr=%d, va=%d, nr=%d\n", + self->vs, self->vr, self->va, nr); + + return NR_INVALID; +} + +/* + * Function irlap_initiate_connection_state () + * + * Initialize the connection state parameters + * + */ +void irlap_initiate_connection_state( struct irlap_cb *self) +{ + DEBUG( 4, "irlap_initiate_connection_state()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + /* + * Next to send and next to receive + */ + self->vs = self->vr = 0; + + /* Last frame which got acked (0 - 1) % 8 */ + self->va = 7; + + self->window = 1; + + self->remote_busy = FALSE; + self->retry_count = 0; +} + +/* + * Function irlap_wait_min_turn_around (self, qos) + * + * Wait negotiated minimum turn around time, this function actually sets + * the number of BOS's that must be sent before the next transmitted + * frame in order to delay for the specified amount of time. This is + * done to avoid using timers, and the forbidden udelay! + */ +void irlap_wait_min_turn_around( struct irlap_cb *self, struct qos_info *qos) +{ + int usecs; + int speed; + int bytes = 0; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + ASSERT( qos != NULL, return;); + + /* + * Get QoS values. + */ + speed = qos->baud_rate.value; + usecs = qos->min_turn_time.value; + + /* No need to calculate XBOFs for speeds over 115200 bps */ + if ( speed > 115200) { + self->mtt_required = usecs; + return; + } + + DEBUG( 4, __FUNCTION__ "(), delay=%d usecs\n", usecs); + + /* + * Send additional BOF's for the next frame for the requested + * min turn time, so now we must calculate how many chars (XBOF's) we + * must send for the requested time period (min turn time) + */ + bytes = speed * usecs / 10000000; + + DEBUG( 4, __FUNCTION__ "(), xbofs delay = %d\n", bytes); + + self->xbofs_delay = bytes; +} + +/* + * Function irlap_flush_all_queues (void) + * + * Flush all queues + * + */ +void irlap_flush_all_queues( struct irlap_cb *self) +{ + struct sk_buff* skb; + + DEBUG( 4, "irlap_flush_all_queues()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + /* + * Free transmission queue + */ + while (( skb = skb_dequeue( &self->tx_list)) != NULL) { + dev_kfree_skb( skb); + } + + /* + * Free sliding window buffered packets + */ + while (( skb = skb_dequeue( &self->wx_list)) != NULL) { + dev_kfree_skb( skb); + } +} + +/* + * Function irlap_setspeed (self, speed) + * + * Change the speed of the IrDA port + * + */ +void irlap_change_speed( struct irlap_cb *self, int speed) +{ + DEBUG( 4, __FUNCTION__ "(), setting speed to %d\n", speed); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + if ( !self->irdev) { + DEBUG( 0, __FUNCTION__ "(), driver missing!\n"); + return; + } + + irda_device_change_speed( self->irdev, speed); + + self->qos_rx.baud_rate.value = speed; + self->qos_tx.baud_rate.value = speed; +} + +#ifdef CONFIG_IRDA_COMPRESSION +void irlap_init_comp_qos_capabilities( struct irlap_cb *self) +{ + struct irda_compressor *comp; + __u8 mask; /* Current bit tested */ + int i; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + /* + * Find out which compressors we support. We do this be checking that + * the corresponding compressor for each bit set in the QoS bits has + * actually been loaded. Ths is sort of hairy code but that is what + * you get when you do a little bit flicking :-) + */ + DEBUG( 4, __FUNCTION__ "(), comp bits 0x%02x\n", + self->qos_rx.compression.bits); + mask = 0x80; /* Start with testing MSB */ + for ( i=0;i<8;i++) { + DEBUG( 4, __FUNCTION__ "(), testing bit %d\n", 8-i); + if ( self->qos_rx.compression.bits & mask) { + DEBUG( 4, __FUNCTION__ "(), bit %d is set by defalt\n", + 8-i); + comp = hashbin_find( irlap_compressors, + compression[ msb_index(mask)], + NULL); + if ( !comp) { + /* Protocol not supported, so clear the bit */ + DEBUG( 4, __FUNCTION__ "(), Compression " + "protocol %d has not been loaded!\n", + compression[msb_index(mask)]); + self->qos_rx.compression.bits &= ~mask; + DEBUG( 4, __FUNCTION__ + "(), comp bits 0x%02x\n", + self->qos_rx.compression.bits); + } + } + /* Try the next bit */ + mask >>= 1; + } +} +#endif + +/* + * Function irlap_init_qos_capabilities (self, qos) + * + * Initialize QoS for this IrLAP session, What we do is to compute the + * intersection of the QoS capabilities for the user, driver and for + * IrLAP itself. Normally, IrLAP will not specify any values, but it can + * be used to restrict certain values. + */ +void irlap_init_qos_capabilities( struct irlap_cb *self, + struct qos_info *qos_user) +{ + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + ASSERT( self->irdev != NULL, return;); + + /* Start out with the maximum QoS support possible */ + irda_init_max_qos_capabilies( &self->qos_rx); + +#ifdef CONFIG_IRDA_COMPRESSION + irlap_init_comp_qos_capabilities( self); +#endif + + /* Apply drivers QoS capabilities */ + irda_qos_compute_intersection( &self->qos_rx, + irda_device_get_qos( self->irdev)); + + /* + * Check for user supplied QoS parameters. The service user is only + * allowed to supply these values. We check each parameter since the + * user may not have set all of them. + */ + if ( qos_user != NULL) { + DEBUG( 0, __FUNCTION__ "(), Found user specified QoS!\n"); + + if ( qos_user->baud_rate.bits) + self->qos_rx.baud_rate.bits &= qos_user->baud_rate.bits; + + if ( qos_user->max_turn_time.bits) + self->qos_rx.max_turn_time.bits &= qos_user->max_turn_time.bits; + if ( qos_user->data_size.bits) + self->qos_rx.data_size.bits &= qos_user->data_size.bits; + + if ( qos_user->link_disc_time.bits) + self->qos_rx.link_disc_time.bits &= qos_user->link_disc_time.bits; +#ifdef CONFIG_IRDA_COMPRESSION + self->qos_rx.compression.bits &= qos_user->compression.bits; +#endif + } + + /* + * Make the intersection between IrLAP and drivers QoS + * capabilities + */ + + /* Use 500ms in IrLAP for now */ + self->qos_rx.max_turn_time.bits &= 0x03; + + /* Set data size */ + /* self->qos_rx.data_size.bits &= 0x03; */ + + irda_qos_bits_to_value( &self->qos_rx); +} + +/* + * Function irlap_apply_default_connection_parameters (void) + * + * Use the default connection and transmission parameters + * + */ +void irlap_apply_default_connection_parameters( struct irlap_cb *self) +{ + DEBUG( 4, "irlap_apply_default_connection_parameters()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + irlap_change_speed( self, 9600); + + /* Default value in NDM */ + self->bofs_count = 11; + + /* Use these until connection has been made */ + self->final_timeout = FINAL_TIMEOUT; + self->poll_timeout = POLL_TIMEOUT; + self->wd_timeout = WD_TIMEOUT; + + self->qos_tx.data_size.value = 64; + self->qos_tx.additional_bofs.value = 11; + + irlap_flush_all_queues( self); +} + +/* + * Function irlap_apply_connection_parameters (qos) + * + * Initialize IrLAP with the negotiated QoS values + * + */ +void irlap_apply_connection_parameters( struct irlap_cb *self, + struct qos_info *qos) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + irlap_change_speed( self, qos->baud_rate.value); + + self->window_size = qos->window_size.value; + self->window = qos->window_size.value; + self->bofs_count = qos->additional_bofs.value; + + /* + * Calculate how many bytes it is possible to transmit before the + * link must be turned around wb = baud * mtt/1000 * 1/2 + */ + self->window_bytes = qos->baud_rate.value + * qos->max_turn_time.value / 10000; + DEBUG( 4, "Setting window_bytes = %d\n", self->window_bytes); + + /* + * Set N1 to 0 if Link Disconnect/Threshold Time = 3 and set it to + * 3 seconds otherwise. See page 71 in IrLAP for more details. + * TODO: these values should be calculated from the final timer + * as well + */ + if ( qos->link_disc_time.value == 3) + self->N1 = 0; + else + /* self->N1 = 6; */ + self->N1 = 3000 / qos->max_turn_time.value; + + DEBUG( 4, "Setting N1 = %d\n", self->N1); + + /* self->N2 = qos->link_disc_time.value * 2; */ + self->N2 = qos->link_disc_time.value * 1000 / qos->max_turn_time.value; + DEBUG( 4, "Setting N2 = %d\n", self->N2); + + /* + * Initialize timeout values, some of the rules are listed on + * page 92 in IrLAP. Divide by 10 since the kernel timers has a + * resolution of 10 ms. + */ + self->poll_timeout = qos->max_turn_time.value / 10; + self->final_timeout = qos->max_turn_time.value / 10; + self->wd_timeout = self->poll_timeout * 2; + + DEBUG( 4, __FUNCTION__ "(), Setting poll timeout = %d\n", + self->poll_timeout); + DEBUG( 4, __FUNCTION__ "(), Setting final timeout = %d\n", + self->final_timeout); + DEBUG( 4, __FUNCTION__ "(), Setting wd timeout = %d\n", + self->wd_timeout); + +#ifdef CONFIG_IRDA_COMPRESSION + if ( qos->compression.value) { + DEBUG( 0, __FUNCTION__ "(), Initializing compression\n"); + irda_set_compression( self, qos->compression.value); + + irlap_compressor_init( self, 0); + } +#endif +} + +#ifdef CONFIG_PROC_FS +/* + * Function irlap_proc_read (buf, start, offset, len, unused) + * + * Give some info to the /proc file system + * + */ +int irlap_proc_read( char *buf, char **start, off_t offset, int len, + int unused) +{ + struct irlap_cb *self; + unsigned long flags; + int i = 0; + + save_flags(flags); + cli(); + + len = 0; + + self = (struct irlap_cb *) hashbin_get_first( irlap); + while ( self != NULL) { + ASSERT( self != NULL, return -ENODEV;); + ASSERT( self->magic == LAP_MAGIC, return -EBADR;); + + len += sprintf( buf+len, "IrLAP[%d] <-> %s ", + i++, self->irdev->name); + len += sprintf( buf+len, "state: %s\n", + irlap_state[ self->state]); + + len += sprintf( buf+len, " caddr: %#02x, ", self->caddr); + len += sprintf( buf+len, "saddr: %#08x, ", self->saddr); + len += sprintf( buf+len, "daddr: %#08x\n", self->daddr); + + len += sprintf( buf+len, " win size: %d, ", + self->window_size); + len += sprintf( buf+len, "win: %d, ", self->window); + len += sprintf( buf+len, "win bytes: %d, ", self->window_bytes); + len += sprintf( buf+len, "bytes left: %d\n", self->bytes_left); + + len += sprintf( buf+len, " tx queue len: %d ", + skb_queue_len( &self->tx_list)); + len += sprintf( buf+len, "win queue len: %d ", + skb_queue_len( &self->wx_list)); + len += sprintf( buf+len, "rbusy: %s\n", self->remote_busy ? + "TRUE" : "FALSE"); + + len += sprintf( buf+len, " retrans: %d ", self->retry_count); + len += sprintf( buf+len, "vs: %d ", self->vs); + len += sprintf( buf+len, "vr: %d ", self->vr); + len += sprintf( buf+len, "va: %d\n", self->va); + + len += sprintf( buf+len, " qos\tbps\tmaxtt\tdsize\twinsize\taddbofs\tmintt\tldisc\tcomp\n"); + + len += sprintf( buf+len, " tx\t%d\t", + self->qos_tx.baud_rate.value); + len += sprintf( buf+len, "%d\t", + self->qos_tx.max_turn_time.value); + len += sprintf( buf+len, "%d\t", + self->qos_tx.data_size.value); + len += sprintf( buf+len, "%d\t", + self->qos_tx.window_size.value); + len += sprintf( buf+len, "%d\t", + self->qos_tx.additional_bofs.value); + len += sprintf( buf+len, "%d\t", + self->qos_tx.min_turn_time.value); + len += sprintf( buf+len, "%d\t", + self->qos_tx.link_disc_time.value); +#ifdef CONFIG_IRDA_COMPRESSION + len += sprintf( buf+len, "%d", + self->qos_tx.compression.value); +#endif + len += sprintf( buf+len, "\n"); + + len += sprintf( buf+len, " rx\t%d\t", + self->qos_rx.baud_rate.value); + len += sprintf( buf+len, "%d\t", + self->qos_rx.max_turn_time.value); + len += sprintf( buf+len, "%d\t", + self->qos_rx.data_size.value); + len += sprintf( buf+len, "%d\t", + self->qos_rx.window_size.value); + len += sprintf( buf+len, "%d\t", + self->qos_rx.additional_bofs.value); + len += sprintf( buf+len, "%d\t", + self->qos_rx.min_turn_time.value); + len += sprintf( buf+len, "%d\t", + self->qos_rx.link_disc_time.value); +#ifdef CONFIG_IRDA_COMPRESSION + len += sprintf( buf+len, "%d", + self->qos_rx.compression.value); +#endif + len += sprintf( buf+len, "\n"); + + self = (struct irlap_cb *) hashbin_get_next( irlap); + } + restore_flags(flags); + + return len; +} + +#endif /* CONFIG_PROC_FS */ + diff --git a/net/irda/irlap_comp.c b/net/irda/irlap_comp.c new file mode 100644 index 000000000000..4a7607d36cab --- /dev/null +++ b/net/irda/irlap_comp.c @@ -0,0 +1,353 @@ +/********************************************************************* + * + * Filename: irlap_comp.c + * Version: + * Description: + * Status: Experimental. + * Author: Dag Brattli + * Created at: Fri Oct 9 09:18:07 1998 + * Modified at: Mon Dec 14 11:55:27 1998 + * Modified by: Dag Brattli + * Sources: ppp.c, isdn_ppp.c + * + * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include + +#include +#include +#include +#include +#include "../../drivers/net/zlib.h" + +hashbin_t *irlap_compressors = NULL; + +/* + * Function irda_register_compressor (cp) + * + * Register new compressor with the IrLAP + * + */ +int irda_register_compressor( struct compressor *cp) +{ + struct irda_compressor *new; + + DEBUG( 4, __FUNCTION__ "()\n"); + + /* Check if this compressor has been registred before */ + if ( hashbin_find ( irlap_compressors, cp->compress_proto, NULL)) { + DEBUG( 0, __FUNCTION__ "(), Compressor already registered\n"); + return 0; + } + + /* Make new IrDA compressor */ + new = (struct irda_compressor *) + kmalloc( sizeof( struct irda_compressor), GFP_KERNEL); + if (new == NULL) + return 1; + + memset( new, 0, sizeof( struct irda_compressor)); + new->cp = cp; + + /* Insert IrDA compressor into hashbin */ + hashbin_insert( irlap_compressors, (QUEUE *) new, cp->compress_proto, + NULL); + + return 0; +} + +/* + * Function irda_unregister_compressor (cp) + * + * Unregister compressor + * + */ +void irda_unregister_compressor ( struct compressor *cp) +{ + struct irda_compressor *node; + + DEBUG( 4, __FUNCTION__ "()\n"); + + node = hashbin_remove( irlap_compressors, cp->compress_proto, NULL); + if ( !node) { + DEBUG( 0, __FUNCTION__ "(), compressor not found!\n"); + return; + } + + kfree( node); +} + +/* + * Function irda_set_compression (self, proto) + * + * The the compression protocol to be used by this session + * + */ +int irda_set_compression( struct irlap_cb *self, int proto) +{ + struct compressor *cp; + struct irda_compressor *comp; + + __u8 options[CILEN_DEFLATE]; + + DEBUG( 0, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return -ENODEV;); + ASSERT( self->magic == LAP_MAGIC, return -EBADR;); + + /* Initialize options */ + options[0] = CI_DEFLATE; + options[1] = CILEN_DEFLATE; + options[2] = DEFLATE_METHOD( DEFLATE_METHOD_VAL); + options[3] = DEFLATE_CHK_SEQUENCE; + + comp = hashbin_find( irlap_compressors, proto, NULL); + if ( !comp) { + DEBUG( 0, __FUNCTION__ "(), Unable to find compressor\n"); + return -1; + } + + cp = comp->cp; + /* + * Compressor part + */ + if ( self->compressor.state != NULL) + (*self->compressor.cp->comp_free)( self->compressor.state); + self->compressor.state = NULL; + + self->compressor.cp = cp; + self->compressor.state = cp->comp_alloc( options, sizeof( options)); + if ( self->compressor.state == NULL) { + DEBUG( 0, __FUNCTION__ "(), Failed!\n"); + return -ENOBUFS; + } + + /* + * Decompress part + */ + + if ( self->decompressor.state != NULL) + irda_decomp_free( self->decompressor.state); + self->decompressor.state = NULL; + + self->decompressor.cp = cp; + self->decompressor.state = cp->decomp_alloc( options, sizeof( options)); + if ( self->decompressor.state == NULL) { + DEBUG( 0, __FUNCTION__ "(), Failed!\n"); + return -ENOBUFS; + } + return 0; +} + +/* + * Function irda_free_compression (self) + * + * + * + */ +void irda_free_compression( struct irlap_cb *self) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + if ( self->compressor.state) { + irda_comp_free( self->compressor.state); + self->compressor.state = NULL; + } + + if ( self->decompressor.state) { + irda_decomp_free( self->decompressor.state); + self->decompressor.state = NULL; + } +} + +/* + * Function irlap_compress_init (self) + * + * + * + */ +void irlap_compressor_init( struct irlap_cb *self, int compress) +{ + int debug = TRUE; + __u8 options[CILEN_DEFLATE]; + + DEBUG( 0, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + /* Initialize options */ + options[0] = CI_DEFLATE; + options[1] = CILEN_DEFLATE; + options[2] = DEFLATE_METHOD_VAL; + options[3] = DEFLATE_CHK_SEQUENCE; + + /* + * We're agreeing to send compressed packets. + */ + if ( self->compressor.state == NULL) { + DEBUG( 0, __FUNCTION__ "(), state == NULL\n"); + return; + } + + if ((*self->compressor.cp->comp_init)( self->compressor.state, + options, sizeof( options), + 0, 0, debug)) + { + DEBUG( 0, __FUNCTION__ "(), Compressor running!\n"); + /* ppp->flags |= SC_COMP_RUN; */ + } + + /* + * Initialize decompressor + */ + if ( self->decompressor.state == NULL) { + DEBUG( 0, __FUNCTION__ "(), state == NULL\n"); + return; + } + + if (( self->decompressor.cp->decomp_init)( self->decompressor.state, + options, sizeof( options), + 0, 0, 0, debug)) + { + DEBUG( 0, __FUNCTION__ "(), Decompressor running!\n"); + + /* ppp->flags |= SC_DECOMP_RUN; */ + /* ppp->flags &= ~(SC_DC_ERROR | SC_DC_FERROR); */ + } +} + +/* + * Function irlap_compress_frame (self, skb) + * + * + * + */ +struct sk_buff *irlap_compress_frame( struct irlap_cb *self, + struct sk_buff *skb) +{ + struct sk_buff *new_skb; + int count; + + ASSERT( skb != NULL, return NULL;); + + DEBUG( 0, __FUNCTION__ "() skb->len=%d, jiffies=%ld\n", (int) skb->len, + jiffies); + + ASSERT( self != NULL, return NULL;); + ASSERT( self->magic == LAP_MAGIC, return NULL;); + + /* Check if compressor got initialized */ + if ( self->compressor.state == NULL) { + /* Tell peer that this frame is not compressed */ + skb_push( skb, LAP_COMP_HEADER); + skb->data[0] = IRDA_NORMAL; + + return skb; + } + + /* FIXME: Find out what is the max overhead (not 10) */ + new_skb = dev_alloc_skb( skb->len+LAP_HEADER+10); + if(!new_skb) + return skb; + + skb_reserve( new_skb, LAP_HEADER); + skb_put( new_skb, skb->len+10); + + count = (self->compressor.cp->compress)( self->compressor.state, + skb->data, new_skb->data, + skb->len, new_skb->len); + if( count <= 0) { + DEBUG( 0, __FUNCTION__ "(), Unable to compress frame!\n"); + dev_kfree_skb( new_skb); + + /* Tell peer that this frame is not compressed */ + skb_push( skb, 1); + skb->data[0] = IRDA_NORMAL; + + return skb; + } + skb_trim( new_skb, count); + + /* Tell peer that this frame is compressed */ + skb_push( new_skb, 1); + new_skb->data[0] = IRDA_COMPRESSED; + + dev_kfree_skb( skb); + + DEBUG( 0, __FUNCTION__ "() new_skb->len=%d\n, jiffies=%ld", + (int) new_skb->len, jiffies); + + return new_skb; +} + +/* + * Function irlap_decompress_frame (self, skb) + * + * + * + */ +struct sk_buff *irlap_decompress_frame( struct irlap_cb *self, + struct sk_buff *skb) +{ + struct sk_buff *new_skb; + int count; + + DEBUG( 4, __FUNCTION__ "() skb->len=%d\n", (int) skb->len); + + ASSERT( self != NULL, return NULL;); + ASSERT( self->magic == LAP_MAGIC, return NULL;); + + ASSERT( self->compressor.state != NULL, return NULL;); + + /* Check if frame is compressed */ + if ( skb->data[0] == IRDA_NORMAL) { + + /* Remove compression header */ + skb_pull( skb, LAP_COMP_HEADER); + + /* + * The frame is not compressed. Pass it to the + * decompression code so it can update its + * dictionary if necessary. + */ + irda_incomp( self->decompressor.state, skb->data, skb->len); + + return skb; + } + + /* Remove compression header */ + skb_pull( skb, LAP_COMP_HEADER); + + new_skb = dev_alloc_skb( 2048); /* FIXME: find the right size */ + if(!new_skb) + return skb; + skb_put( new_skb, 2048); + + count = irda_decompress( self->decompressor.state, skb->data, + skb->len, new_skb->data, new_skb->len); + if ( count <= 0) { + DEBUG( 0, __FUNCTION__ "(), Unable to decompress frame!\n"); + + dev_kfree_skb( new_skb); + return skb; + } + + skb_trim( new_skb, count); + + DEBUG( 0, __FUNCTION__ "() new_skb->len=%d\n", (int) new_skb->len); + + return new_skb; +} + diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c new file mode 100644 index 000000000000..9880bf1c64c1 --- /dev/null +++ b/net/irda/irlap_event.c @@ -0,0 +1,1831 @@ +/********************************************************************* + * + * Filename: irlap_event.c + * Version: 0.1 + * Description: IrLAP state machine implementation + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sat Aug 16 00:59:29 1997 + * Modified at: Mon Dec 14 14:16:00 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli , + * Thomas Davis + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +static int irlap_state_ndm ( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_query ( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_reply ( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_conn ( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_setup ( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_offline( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_xmit_p ( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_pclose ( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_nrm_p ( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_reset_wait(struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_reset ( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_nrm_s ( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_xmit_s ( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); +static int irlap_state_sclose ( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info); + +static char *irlap_event[] = { + "DISCOVERY_REQUEST", + "CONNECT_REQUEST", + "CONNECT_RESPONSE", + "DISCONNECT_REQUEST", + "DATA_REQUEST", + "RESET_REQUEST", + "SEND_I_CMD", + "RECV_DISCOVERY_XID_CMD", + "RECV_DISCOVERY_XID_RSP", + "RECV_SNRM_CMD", + "RECV_TEST_CMD", + "RECV_UA_RSP", + "RECV_DM_RSP", + "RECV_I_CMD", + "RECV_I_RSP", + "RECV_UI_FRAME", + "RECV_FRMR_RSP", + "RECV_RR_CMD", + "RECV_RR_RSP", + "RECV_RNR_FRAME", + "RECV_DISC_FRAME", + "SLOT_TIMER_EXPIRED", + "QUERY_TIMER_EXPIRED", + "FINAL_TIMER_EXPIRED", + "POLL_TIMER_EXPIRED", + "DISCOVERY_TIMER_EXPIRED", + "WD_TIMER_EXPIRED", + "BACKOFF_TIMER_EXPIRED", +}; + +char *irlap_state[] = { + "LAP_NDM", + "LAP_QUERY", + "LAP_REPLY", + "LAP_CONN", + "LAP_SETUP", + "LAP_OFFLINE", + "LAP_XMIT_P", + "LAP_PCLOSE", + "LAP_NRM_P", + "LAP_RESET_WAIT", + "LAP_RESET", + "LAP_NRM_S", + "LAP_XMIT_S", + "LAP_SCLOSE", +}; + +static int (*state[])( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info) = +{ + irlap_state_ndm, + irlap_state_query, + irlap_state_reply, + irlap_state_conn, + irlap_state_setup, + irlap_state_offline, + irlap_state_xmit_p, + irlap_state_pclose, + irlap_state_nrm_p, + irlap_state_reset_wait, + irlap_state_reset, + irlap_state_nrm_s, + irlap_state_xmit_s, + irlap_state_sclose, +}; + +/* + * Function irda_poll_timer_expired (data) + * + * + * + */ +static void irlap_poll_timer_expired( unsigned long data) +{ + struct irlap_cb *self = (struct irlap_cb *) data; + + DEBUG( 4, "Poll timer expired!\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + irlap_do_event( self, POLL_TIMER_EXPIRED, NULL, NULL); +} + +void irlap_start_poll_timer( struct irlap_cb *self, int timeout) +{ + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + +#ifdef CONFIG_IRDA_FAST_RR + if ( skb_queue_len( &self->tx_list) == 0) { + if ( self->fast_RR == TRUE) { + /* + * Assert that the fast poll timer has not reached the + * normal poll timer yet + */ + if ( self->fast_RR_timeout < timeout) { + /* + * FIXME: this should be a more configurable + * function + */ + self->fast_RR_timeout += 15; + + /* Use this fast(er) timeout instead */ + timeout = self->fast_RR_timeout; + } + } else { + self->fast_RR = TRUE; + + /* Start with just 1 ms */ + self->fast_RR_timeout = 1; + timeout = 1; + } + } else + self->fast_RR = FALSE; + + DEBUG( 4, __FUNCTION__ "(), Timeout=%d\n", timeout); +#endif + irda_start_timer( &self->poll_timer, timeout, + (unsigned long) self, irlap_poll_timer_expired); +} + +/* + * Function irlap_do_event (event, skb, info) + * + * Rushes through the state machine without any delay. If state = XMIT + * then send queued data frames. + */ +void irlap_do_event( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info) +{ + int ret; + int iter = 0; + + if ( !self || self->magic != LAP_MAGIC) { + DEBUG( 0, "irlap_do_event: bad pointer *self\n"); + return; + } + + DEBUG( 4, "irlap_do_event: event = %s, state = %s\n", + irlap_event[ event], irlap_state[ self->state]); + + /* + * Do event, this implementation does not deal with pending events. + * This is because I don't see the need for this. DB + */ + ret = (*state[ self->state]) ( self, event, skb, info); + + /* + * Check if we have switched to XMIT state? If so, send queued data + * frames if any, if -1 is returned it means that we are not allowed + * to send any more frames. + */ + while (( self->state == LAP_XMIT_P) || ( self->state == LAP_XMIT_S)) { + if ( skb_queue_len( &self->tx_list) > 0) { + + struct sk_buff *skb = skb_dequeue( &self->tx_list); + ASSERT( skb != NULL, return;); + + DEBUG( 4, "** Sending queued data frames\n"); + ret = (*state[ self->state])( self, SEND_I_CMD, skb, + NULL); + if ( ret == -EPROTO) + return; /* Try again later! */ + } else + return; + + /* Just in case :-) */ + if (iter++ > 100) { + DEBUG( 0, __FUNCTION__ "(), *** breaking!! ***\n"); + return; + } + } +} + +/* + * Function irlap_next_state (self, state) + * + * Switches state and provides debug information + * + */ +void irlap_next_state( struct irlap_cb *self, IRLAP_STATE state) +{ + + if ( !self || self->magic != LAP_MAGIC) { + DEBUG( 4, "irlap_next_state: I have lost myself!\n"); + return; + } + + DEBUG( 4, "next LAP state = %s\n", irlap_state[ state]); + + self->state = state; + + /* + * If we are swithing away from a XMIT state then we are allowed to + * transmit a maximum number of bytes again when we enter the XMIT + * state again. Since its possible to "switch" from XMIT to XMIT and + * we cannot do this when swithing into the XMIT state :-) + */ + if (( state != LAP_XMIT_P) && ( state != LAP_XMIT_S)) + self->bytes_left = self->window_bytes; +} + +/* + * Function irlap_state_ndm (event, skb, frame) + * + * NDM (Normal Disconnected Mode) state + * + */ +static int irlap_state_ndm( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info) +{ + DISCOVERY *discovery_rsp; + int ret = 0; + + DEBUG( 4, "irlap_state_ndm()\n"); + + ASSERT( self != NULL, return -1;); + ASSERT( self->magic == LAP_MAGIC, return -1;); + + switch( event) { + case CONNECT_REQUEST: + ASSERT( self->irdev != NULL, return -1;); + + if ( irda_device_is_media_busy( self->irdev)) { + DEBUG( 0, __FUNCTION__ + "(), CONNECT_REQUEST: media busy!\n"); + + /* Always switch state before calling upper layers */ + irlap_next_state( self, LAP_NDM); + + irlap_disconnect_indication( self, LAP_MEDIA_BUSY); + } else { + irlap_send_snrm_frame( self, &self->qos_rx); + + /* Start Final-bit timer */ + irlap_start_final_timer( self, self->final_timeout); + + self->retry_count = 0; + irlap_next_state( self, LAP_SETUP); + } + break; + + case RECV_SNRM_CMD: + self->daddr = info->daddr; + self->caddr = info->caddr; + + irlap_next_state( self, LAP_CONN); + + irlap_connect_indication( self, skb); + break; + + case DISCOVERY_REQUEST: + ASSERT( info != NULL, return -1;); + + if ( irda_device_is_media_busy( self->irdev)) { + DEBUG(0, "irlap_discovery_request: media busy!\n"); + /* irlap->log.condition = MEDIA_BUSY; */ + + /* Always switch state before calling upper layers */ + irlap_next_state( self, LAP_NDM); + + /* This will make IrLMP try again */ + irlap_discovery_confirm( self, NULL); + return 0; + } + + self->S = info->S; + self->s = info->s; + irlap_send_discovery_xid_frame( self, info->S, info->s, TRUE, + info->discovery); + self->s++; + + irlap_start_slot_timer( self, SLOT_TIMEOUT); + irlap_next_state( self, LAP_QUERY); + break; + + case RECV_DISCOVERY_XID_CMD: + ASSERT( info != NULL, return -1;); + + /* Assert that this is not the final slot */ + if ( info->s <= info->S) { + self->daddr = info->daddr; + self->slot = irlap_generate_rand_time_slot( info->S, + info->s); + DEBUG( 4, "XID_CMD: S=%d, s=%d, slot %d\n", info->S, + info->s, self->slot); + + if ( self->slot == info->s) { + discovery_rsp = irlmp_get_discovery_response(); + + DEBUG( 4, "Sending XID rsp 1\n"); + irlap_send_discovery_xid_frame( self, info->S, + self->slot, + FALSE, + discovery_rsp); + self->frame_sent = TRUE; + } else + self->frame_sent = FALSE; + + irlap_start_query_timer( self, QUERY_TIMEOUT); + irlap_next_state( self, LAP_REPLY); + } + + dev_kfree_skb( skb); + break; + + default: + /* DEBUG( 0, "irlap_state_ndm: Unknown event"); */ + ret = -1; + break; + } + return ret; +} + +/* + * Function irlap_state_query (event, skb, info) + * + * QUERY state + * + */ +static int irlap_state_query( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info) +{ + int ret = 0; + + ASSERT( self != NULL, return -1;); + ASSERT( self->magic == LAP_MAGIC, return -1;); + + switch( event) { + case RECV_DISCOVERY_XID_RSP: + ASSERT( info != NULL, return -1;); + ASSERT( info->discovery != NULL, return -1;); + + DEBUG( 4, "irlap_state_query(), daddr=%08x\n", + info->discovery->daddr); + + hashbin_insert( self->discovery_log, + (QUEUE *) info->discovery, + info->discovery->daddr, NULL); + + dev_kfree_skb( skb); + + /* Keep state */ + irlap_next_state( self, LAP_QUERY); + break; + case SLOT_TIMER_EXPIRED: + if ( self->s < self->S) { + irlap_send_discovery_xid_frame( self, self->S, + self->s, TRUE, + self->discovery_cmd); + self->s++; + irlap_start_slot_timer( self, SLOT_TIMEOUT); + + /* Keep state */ + irlap_next_state( self, LAP_QUERY); + } else { + /* This is the final slot! */ + irlap_send_discovery_xid_frame( self, self->S, 0xff, + TRUE, + self->discovery_cmd); + + /* Always switch state before calling upper layers */ + irlap_next_state( self, LAP_NDM); + + /* + * We are now finished with the discovery procedure, + * so now we must return the results + */ + irlap_discovery_confirm( self, self->discovery_log); + } + break; + default: + DEBUG( 4, "irlap_state_query: Unknown event %d, %s\n", event, + irlap_event[event]); + + if ( skb != NULL) { + dev_kfree_skb( skb); + } + ret = -1; + break; + } + return ret; +} + +/* + * Function irlap_state_reply (self, event, skb, info) + * + * REPLY, we have received a XID discovery frame from a device and we + * are waiting for the right time slot to send a response XID frame + * + */ +static int irlap_state_reply( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info) +{ + DISCOVERY *discovery_rsp; + int ret=0; + + DEBUG( 4, "irlap_state_reply()\n"); + + ASSERT( self != NULL, return -1;); + ASSERT( self->magic == LAP_MAGIC, return -1;); + + switch( event) { + case QUERY_TIMER_EXPIRED: + DEBUG( 0, "irlap_state_reply: QUERY_TIMER_EXPIRED <%ld>\n", + jiffies); + irlap_next_state( self, LAP_NDM); + break; + case RECV_DISCOVERY_XID_CMD: + ASSERT( info != NULL, return -1;); + /* + * Last frame? + */ + if ( info->s == 0xff) { + del_timer( &self->query_timer); + + /* info->log.condition = REMOTE; */ + + /* Always switch state before calling upper layers */ + irlap_next_state( self, LAP_NDM); + + irlap_discovery_indication( self, info->discovery); + } else if (( info->s >= self->slot) && + ( !self->frame_sent)) { + DEBUG( 4, "Sending XID rsp 2, s=%d\n", info->s); + discovery_rsp = irlmp_get_discovery_response(); + + irlap_send_discovery_xid_frame( self, info->S, + self->slot, FALSE, + discovery_rsp); + + self->frame_sent = TRUE; + irlap_next_state( self, LAP_REPLY); + } + dev_kfree_skb( skb); + break; + default: + DEBUG( 0, __FUNCTION__ "(), Unknown event %d, %s\n", event, + irlap_event[event]); + + if ( skb != NULL) + dev_kfree_skb( skb); + + ret = -1; + break; + } + return ret; +} + +/* + * Function irlap_state_conn (event, skb, info) + * + * CONN, we have received a SNRM command and is waiting for the upper + * layer to accept or refuse connection + * + */ +static int irlap_state_conn( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info) +{ + int ret = 0; + + DEBUG( 0, __FUNCTION__ "(), event=%s\n", irlap_event[ event]); + + ASSERT( self != NULL, return -1;); + ASSERT( self->magic == LAP_MAGIC, return -1;); + + switch( event) { + case CONNECT_RESPONSE: + skb_pull( skb, 11); + + ASSERT( self->irdev != NULL, return -1;); + irda_qos_negotiate( &self->qos_rx, &self->qos_tx, skb); + + irlap_initiate_connection_state( self); + + /* + * We are allowed to send two frames! + */ + irlap_send_ua_response_frame( self, &self->qos_rx); + irlap_send_ua_response_frame( self, &self->qos_rx); + + irlap_apply_connection_parameters( self, &self->qos_tx); + + /* + * The WD-timer could be set to the duration of the P-timer + * for this case, but it is recommomended to use twice the + * value (note 3 IrLAP p. 60). + */ + irlap_start_wd_timer( self, self->wd_timeout); + irlap_next_state( self, LAP_NRM_S); + break; + + case RECV_SNRM_CMD: + DEBUG( 3, "irlap_state_conn: event RECV_SNRM_CMD!\n"); +#if 0 + irlap_next_state( self, LAP_NDM); +#endif + break; + + case RECV_DISCOVERY_XID_CMD: + DEBUG( 3, "irlap_state_conn: event RECV_DISCOVER_XID_CMD!\n"); + irlap_next_state( self, LAP_NDM); + break; + + case DISCONNECT_REQUEST: + irlap_send_dm_frame( self); + irlap_next_state( self, LAP_CONN); + break; + + default: + DEBUG( 0, "irlap_state_conn: Unknown event %d, %s\n", event, + irlap_event[event]); + ret = -1; + break; + } + + return ret; +} + +/* + * Function irlap_state_setup (event, skb, frame) + * + * SETUP state, The local layer has transmitted a SNRM command frame to + * a remote peer layer and is awaiting a reply . + * + */ +static int irlap_state_setup( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info) +{ + int ret = 0; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return -1;); + ASSERT( self->magic == LAP_MAGIC, return -1;); + + switch( event) { + case FINAL_TIMER_EXPIRED: + if ( self->retry_count < self->N3) { +/* + * Perform random backoff, Wait a random number of time units, minimum + * duration half the time taken to transmitt a SNRM frame, maximum duration + * 1.5 times the time taken to transmit a SNRM frame. So this time should + * between 15 msecs and 45 msecs. + */ + irlap_start_backoff_timer( self, 2 + (jiffies % 3)); + } else { + /* Always switch state before calling upper layers */ + irlap_next_state( self, LAP_NDM); + + irlap_disconnect_indication( self, LAP_FOUND_NONE); + } + break; + case BACKOFF_TIMER_EXPIRED: + irlap_send_snrm_frame( self, &self->qos_rx); + irlap_start_final_timer( self, self->final_timeout); + self->retry_count++; + break; + + case RECV_SNRM_CMD: + DEBUG( 0, "irlap_state_setup: SNRM battle!\n"); + + ASSERT( skb != NULL, return 0;); + ASSERT( info != NULL, return 0;); + + /* + * The device with the largest device address wins the battle + * (both have sent a SNRM command!) + */ + if ( info->daddr > self->saddr) { + del_timer( &self->final_timer); + irlap_initiate_connection_state( self); + + ASSERT( self->irdev != NULL, return -1;); + irda_qos_negotiate( &self->qos_rx, &self->qos_tx, skb); + + irlap_send_ua_response_frame(self, &self->qos_rx); + irlap_apply_connection_parameters( self, &self->qos_tx); + irlap_connect_confirm( self, skb); + + /* + * The WD-timer could be set to the duration of the + * P-timer for this case, but it is recommomended + * to use twice the value (note 3 IrLAP p. 60). + */ + irlap_start_wd_timer( self, self->wd_timeout); + + irlap_next_state( self, LAP_NRM_S); + } else { + /* We just ignore the other device! */ + irlap_next_state( self, LAP_SETUP); + } + break; + case RECV_UA_RSP: + /* Stop F-timer */ + del_timer( &self->final_timer); + + /* Initiate connection state */ + irlap_initiate_connection_state( self); + + /* Negotiate connection parameters */ + IS_SKB( skb, return -1;); + ASSERT( skb->len > 10, return -1;); + skb_pull( skb, 10); + + ASSERT( self->irdev != NULL, return -1;); + irda_qos_negotiate( &self->qos_rx, &self->qos_tx, skb); + + irlap_apply_connection_parameters( self, &self->qos_tx); + self->retry_count = 0; + irlap_send_rr_frame( self, CMD_FRAME); + + irlap_start_final_timer( self, self->final_timeout/2); + irlap_next_state( self, LAP_NRM_P); + + irlap_connect_confirm( self, skb); + break; + + case RECV_DISC_FRAME: + del_timer( &self->final_timer); + irlap_next_state( self, LAP_NDM); + + irlap_disconnect_indication( self, LAP_DISC_INDICATION); + break; + + /* DM handled in irlap_frame.c, irlap_input() */ + + default: + DEBUG( 4, "irlap_state_setup: Unknown event"); + ret = -1; + break; + } + return ret; +} + +/* + * Function irlap_state_offline (self, event, skb, info) + * + * OFFLINE state, not used for now! + * + */ +static int irlap_state_offline( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info) +{ + DEBUG( 0, __FUNCTION__ "(), Unknown event\n"); + + return -1; +} + +/* + * Function irlap_state_xmit_p (self, event, skb, info) + * + * XMIT, Only the primary station has right to transmit, and we therefor + * do not expect to receive any transmissions from other stations. + * + */ +static int irlap_state_xmit_p( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info) +{ + int ret = 0; + + ASSERT( self != NULL, return -ENODEV;); + ASSERT( self->magic == LAP_MAGIC, return -EBADR;); + + DEBUG( 4, __FUNCTION__ "(), event=%s, vs=%d, vr=%d", + irlap_event[ event], self->vs, self->vr); + + switch( event) { + case SEND_I_CMD: + ASSERT( skb != NULL, return -1;); + DEBUG( 4, "irlap_state_xmit: Window=%d\n", self->window); + + /* + * Only send frame if send-window > 0. + */ + if (( self->window > 0) && ( !self->remote_busy)) { + + /* + * Test if we have transmitted more bytes over the + * link than its possible to do with the current + * speed and turn-around-time. + */ + if (( skb->len+self->bofs_count) > self->bytes_left) { + DEBUG( 4, __FUNCTION__ "(), Not allowed to " + "transmit more bytes!\n"); + skb_queue_head( &self->tx_list, skb); + + /* + * We should switch state to LAP_NRM_P, but + * that is not possible since we must be sure + * that we poll the other side. Since we have + * used up our time, the poll timer should + * trigger anyway now,so we just wait for it + * DB + */ + return -EPROTO; + } + self->bytes_left -= ( skb->len + self->bofs_count); + + /* + * Send data with poll bit cleared only if window > 1 + * and there is more frames after this one to be sent + */ + if (( self->window > 1) && + skb_queue_len( &self->tx_list) > 0) + { + DEBUG( 4, __FUNCTION__ "(), window > 1\n"); + irlap_send_data_primary( self, skb); + irlap_next_state( self, LAP_XMIT_P); + } else { + DEBUG( 4, __FUNCTION__ "(), window <= 1\n"); + irlap_send_data_primary_poll( self, skb); + irlap_next_state( self, LAP_NRM_P); + } +#ifdef CONFIG_IRDA_FAST_RR + /* Peer may want to reply immediately */ + self->fast_RR = FALSE; +#endif + } else { + DEBUG( 0, __FUNCTION__ + "(), Unable to send! remote busy?\n"); + skb_queue_head( &self->tx_list, skb); + + /* + * The next ret is important, because it tells + * irlap_next_state _not_ to deliver more frames + */ + ret = -EPROTO; + } + break; + case DISCONNECT_REQUEST: + del_timer( &self->poll_timer); + irlap_wait_min_turn_around( self, &self->qos_tx); + irlap_send_disc_frame( self); + irlap_flush_all_queues( self); + irlap_start_final_timer( self, self->final_timeout); + self->retry_count = 0; + irlap_next_state( self, LAP_PCLOSE); + break; + case POLL_TIMER_EXPIRED: + irlap_send_rr_frame( self, CMD_FRAME); + irlap_start_final_timer( self, self->final_timeout); + irlap_next_state( self, LAP_NRM_P); + break; + default: + /* DEBUG( 0, "irlap_state_xmit: Unknown event"); */ + ret = -EINVAL; + break; + } + return ret; +} + +/* + * Function irlap_state_pclose (event, skb, info) + * + * PCLOSE state + */ +static int irlap_state_pclose( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info) +{ + int ret = 0; + + DEBUG( 0, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return -1;); + ASSERT( self->magic == LAP_MAGIC, return -1;); + + switch( event) { + case RECV_UA_RSP: + del_timer( &self->final_timer); + + irlap_apply_default_connection_parameters( self); + + /* Always switch state before calling upper layers */ + irlap_next_state( self, LAP_NDM); + + irlap_disconnect_indication( self, LAP_DISC_INDICATION); + + break; + case FINAL_TIMER_EXPIRED: + if ( self->retry_count < self->N3) { + irlap_wait_min_turn_around( self, &self->qos_tx); + irlap_send_disc_frame( self); + irlap_start_final_timer( self, self->final_timeout); + self->retry_count++; + /* Keep state */ + } else { + irlap_apply_default_connection_parameters( self); + + /* + * Always switch state before calling upper layers + */ + irlap_next_state( self, LAP_NDM); + + irlap_disconnect_indication( self, LAP_NO_RESPONSE); + } + break; + default: + DEBUG( 0, "irlap_state_pclose: Unknown event %d\n", event); + ret = -1; + break; + } + return ret; +} + +/* + * Function irlap_state_nrm_p (self, event, skb, info) + * + * NRM_P (Normal Response Mode as Primary), The primary station has given + * permissions to a secondary station to transmit IrLAP resonse frames + * (by sending a frame with the P bit set). The primary station will not + * transmit any frames and is expecting to receive frames only from the + * secondary to which transmission permissions has been given. + */ +static int irlap_state_nrm_p( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info) +{ + int ret = 0; + int ns_status; + int nr_status; + + ASSERT( self != NULL, return -1;); + ASSERT( self->magic == LAP_MAGIC, return -1;); + + switch( event) { + case RECV_RR_RSP: + DEBUG( 4, "irlap_state_nrm_p: RECV_RR_FRAME: " + "Retrans:%d, nr=%d, va=%d, vs=%d, vr=%d\n", + self->retry_count, info->nr, self->va, self->vs, + self->vr); + + ASSERT( info != NULL, return -1;); + + /* + * If you get a RR, the remote isn't busy anymore, + * no matter what the NR + */ + self->remote_busy = FALSE; + + /* + * Nr as expected? + */ + ret = irlap_validate_nr_received( self, info->nr); + if ( ret == NR_EXPECTED) { + /* Stop final timer */ + del_timer( &self->final_timer); + + /* Update Nr received */ + irlap_update_nr_received( self, info->nr); + + /* + * Got expected NR, so reset the retry_count. This + * is not done by the IrLAP standard , which is + * strange! DB. + */ + self->retry_count = 0; + irlap_wait_min_turn_around( self, &self->qos_tx); + + /* Start poll timer */ + irlap_start_poll_timer( self, self->poll_timeout); + + irlap_next_state( self, LAP_XMIT_P); + } else if ( ret == NR_UNEXPECTED) { + ASSERT( info != NULL, return -1;); + /* + * Unexpected nr! + */ + + /* Update Nr received */ + irlap_update_nr_received( self, info->nr); + + DEBUG( 4, "RECV_RR_FRAME: Retrans:%d, nr=%d, va=%d, " + "vs=%d, vr=%d\n", + self->retry_count, info->nr, self->va, + self->vs, self->vr); + + /* Resend rejected frames */ + irlap_resend_rejected_frames( self, CMD_FRAME); + + /* + * Start only if not running, DB + * TODO: Should this one be here? + */ + /* if ( !self->final_timer.prev) */ +/* irda_start_timer( FINAL_TIMER, self->final_timeout); */ + + /* Keep state */ + irlap_next_state( self, LAP_NRM_P); + } else if ( ret == NR_INVALID) { + DEBUG( 0, "irlap_state_nrm_p: received RR with " + "invalid nr !\n"); + del_timer( &self->final_timer); + + irlap_next_state( self, LAP_RESET_WAIT); + + irlap_disconnect_indication( self, + LAP_RESET_INDICATION); + self->xmitflag = TRUE; + } + if (skb) + dev_kfree_skb( skb); + break; + case RECV_RNR_FRAME: + DEBUG( 4, "irlap_state_nrm_p: RECV_RNR_FRAME: Retrans:%d, " + "nr=%d, va=%d, vs=%d, vr=%d\n", + self->retry_count, info->nr, self->va, self->vs, + self->vr); + + ASSERT( info != NULL, return -1;); + + /* Stop final timer */ + del_timer( &self->final_timer); + self->remote_busy = TRUE; + + /* Update Nr received */ + irlap_update_nr_received( self, info->nr); + + /* Start poll timer */ + irlap_start_poll_timer( self, self->poll_timeout); + + irlap_next_state( self, LAP_XMIT_P); + + dev_kfree_skb( skb); + break; + case RECV_I_RSP: + /* FIXME: must check for remote_busy below */ +#ifdef CONFIG_IRDA_FAST_RR + /* + * Reset the fast_RR so we can use the fast RR code with + * full speed the next time since peer may have more frames + * to transmitt + */ + self->fast_RR = FALSE; +#endif + + ASSERT( info != NULL, return -1;); + + ns_status = irlap_validate_ns_received( self, info->ns); + nr_status = irlap_validate_nr_received( self, info->nr); + + /* + * Check for expected I(nformation) frame + */ + if ((ns_status == NS_EXPECTED) && (nr_status == NR_EXPECTED)) { + /* + * poll bit cleared? + */ + if ( !info->pf) { + self->vr = (self->vr + 1) % 8; + + /* Update Nr received */ + irlap_update_nr_received( self, info->nr); + + self->ack_required = TRUE; + + /* Keep state, do not move this line */ + irlap_next_state( self, LAP_NRM_P); + + irlap_data_indication( self, skb); + } else { + del_timer( &self->final_timer); + + self->vr = (self->vr + 1) % 8; + + /* Update Nr received */ + irlap_update_nr_received( self, info->nr); + + /* + * Got expected NR, so reset the + * retry_count. This is not done by IrLAP, + * which is strange! + */ + self->retry_count = 0; + self->ack_required = TRUE; + + /* This is the last frame */ + irlap_start_poll_timer( self, self->poll_timeout); + irlap_wait_min_turn_around( self, &self->qos_tx); + /* Do not move this line */ + irlap_next_state( self, LAP_XMIT_P); + + irlap_data_indication( self, skb); + } + break; + + } + /* + * Unexpected next to send (Ns) + */ + if (( ns_status == NS_UNEXPECTED) && + ( nr_status == NR_EXPECTED)) + { + if ( !info->pf) { + irlap_update_nr_received( self, info->nr); + + /* + * Wait until the last frame before doing + * anything + */ + + /* Keep state */ + irlap_next_state( self, LAP_NRM_P); + } else { + DEBUG( 4, "*** irlap_state_nrm_p:" + " missing or duplicate frame!\n"); + + /* Update Nr received */ + irlap_update_nr_received( self, info->nr); + + irlap_wait_min_turn_around( self, &self->qos_tx); + irlap_send_rr_frame( self, CMD_FRAME); + + self->ack_required = FALSE; + + irlap_start_final_timer( self, self->final_timeout); + irlap_next_state( self, LAP_NRM_P); + } + dev_kfree_skb( skb); + break; + } + /* + * Unexpected next to receive (Nr) + */ + if (( ns_status == NS_EXPECTED) && + ( nr_status == NR_UNEXPECTED)) + { + if ( info->pf) { + self->vr = (self->vr + 1) % 8; + + /* Update Nr received */ + irlap_update_nr_received( self, info->nr); + + /* Resend rejected frames */ + irlap_resend_rejected_frames( self, CMD_FRAME); + + self->ack_required = FALSE; + irlap_start_final_timer( self, self->final_timeout); + + /* Keep state, do not move this line */ + irlap_next_state( self, LAP_NRM_P); + + irlap_data_indication( self, skb); + } else { + /* + * Do not resend frames until the last + * frame has arrived from the other + * device. This is not documented in + * IrLAP!! + */ + self->vr = (self->vr + 1) % 8; + + /* Update Nr received */ + irlap_update_nr_received( self, info->nr); + + self->ack_required = FALSE; + + /* Keep state, do not move this line!*/ + irlap_next_state( self, LAP_NRM_P); + + irlap_data_indication( self, skb); + } + break; + } + /* + * Unexpected next to send (Ns) and next to receive (Nr) + * Not documented by IrLAP! + */ + if (( ns_status == NS_UNEXPECTED) && + ( nr_status == NR_UNEXPECTED)) + { + DEBUG( 4, "IrLAP: unexpected nr and ns!\n"); + if ( info->pf) { + /* Resend rejected frames */ + irlap_resend_rejected_frames( self, CMD_FRAME); + + /* Give peer some time to retransmit! */ + irlap_start_final_timer( self, self->final_timeout); + + /* Keep state, do not move this line */ + irlap_next_state( self, LAP_NRM_P); + } else { + /* Update Nr received */ + /* irlap_update_nr_received( info->nr); */ + + self->ack_required = FALSE; + } + break; + } + + /* + * Invalid NR or NS + */ + if (( nr_status == NR_INVALID) || ( ns_status == NS_INVALID)) { + if ( info->pf) { + del_timer( &self->final_timer); + + irlap_next_state( self, LAP_RESET_WAIT); + + irlap_disconnect_indication( self, LAP_RESET_INDICATION); + self->xmitflag = TRUE; + } else { + del_timer( &self->final_timer); + + irlap_disconnect_indication( self, LAP_RESET_INDICATION); + + self->xmitflag = FALSE; + } + break; + } + DEBUG( 0, "irlap_state_nrm_p: Not implemented!\n"); + DEBUG( 0, "event=%s, ns_status=%d, nr_status=%d\n", + irlap_event[ event], ns_status, nr_status); + break; + case RECV_UI_FRAME: + /* poll bit cleared? */ + if ( !info->pf) { + irlap_unit_data_indication( self, skb); + irlap_next_state( self, LAP_NRM_P); + } else { + del_timer( &self->final_timer); + irlap_unit_data_indication( self, skb); + irlap_start_poll_timer( self, self->poll_timeout); + } + break; + case RECV_FRMR_RSP: + del_timer( &self->final_timer); + self->xmitflag = TRUE; + irlap_next_state( self, LAP_RESET_WAIT); + irlap_reset_indication( self); + break; + case FINAL_TIMER_EXPIRED: + /* + * We are allowed to wait for additional 300 ms if + * final timer expires when we are in the middle + * of receiving a frame (page 45, IrLAP). Check that + * we only do this once for each frame. + */ + if ( irda_device_is_receiving( self->irdev) && + !self->add_wait) { + DEBUG( 4, "FINAL_TIMER_EXPIRED when receiving a " + "frame! Waiting a little bit more!\n"); + irlap_start_final_timer( self, 30); + + /* + * Don't allow this to happen one more time in a row, + * or else we can get a pretty tight loop here if + * if we only receive half a frame. DB. + */ + self->add_wait = TRUE; + break; + } + self->add_wait = FALSE; + + if (( self->retry_count < self->N2) && + ( self->retry_count != self->N1)) { + + irlap_wait_min_turn_around( self, &self->qos_tx); + irlap_send_rr_frame( self, CMD_FRAME); + + irlap_start_final_timer( self, self->final_timeout); + self->retry_count++; + + DEBUG( 4, "irlap_state_nrm_p: FINAL_TIMER_EXPIRED:" + " retry_count=%d\n", self->retry_count); + /* Keep state */ + } else if ( self->retry_count == self->N1) { + irlap_status_indication( STATUS_NO_ACTIVITY); + irlap_wait_min_turn_around( self, &self->qos_tx); + irlap_send_rr_frame( self, CMD_FRAME); + + irlap_start_final_timer( self, self->final_timeout); + self->retry_count++; + + DEBUG( 4, "retry count = N1; retry_count=%d\n", + self->retry_count); + /* Keep state */ + } else if ( self->retry_count >= self->N2) { + irlap_apply_default_connection_parameters( self); + + /* Always switch state before calling upper layers */ + irlap_next_state( self, LAP_NDM); + irlap_disconnect_indication( self, LAP_NO_RESPONSE); + } + break; + case RECV_DISC_FRAME: /* FIXME: Check how this is in the standard! */ + DEBUG( 0, __FUNCTION__ "(), RECV_DISC_FRAME()\n"); + + /* Always switch state before calling upper layers */ + irlap_next_state( self, LAP_NDM); + + irlap_wait_min_turn_around( self, &self->qos_tx); + irlap_send_ua_response_frame( self, NULL); + + del_timer( &self->final_timer); + /* del_timer( &self->poll_timer); */ + + irlap_flush_all_queues( self); + irlap_apply_default_connection_parameters( self); + + irlap_disconnect_indication( self, LAP_DISC_INDICATION); + if (skb) + dev_kfree_skb( skb); + + break; + default: + /* DEBUG( 0, "irlap_state_nrm_p: Unknown event"); */ + ret = -1; + break; + } + return ret; +} + +/* + * Function irlap_state_reset_wait (event, skb, info) + * + * We have informed the service user of a reset condition, and is + * awaiting reset of disconnect request. + * + */ +int irlap_state_reset_wait( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info) +{ + int ret = 0; + + DEBUG( 3, __FUNCTION__ "(), event = %s\n", irlap_event[event]); + + ASSERT( self != NULL, return -1;); + ASSERT( self->magic == LAP_MAGIC, return -1;); + + switch( event) { + case RESET_REQUEST: + if ( self->xmitflag) { + irlap_wait_min_turn_around( self, &self->qos_tx); + irlap_send_snrm_frame( self, NULL); + irlap_start_final_timer( self, self->final_timeout); + irlap_next_state( self, LAP_RESET); + } else { + irlap_start_final_timer( self, self->final_timeout); + irlap_next_state( self, LAP_RESET); + } + break; + case DISCONNECT_REQUEST: + irlap_wait_min_turn_around( self, &self->qos_tx); + irlap_send_disc_frame( self); + irlap_flush_all_queues( self); + irlap_start_final_timer( self, self->final_timeout); + self->retry_count = 0; + irlap_next_state( self, LAP_PCLOSE); + break; + default: + DEBUG( 0, "irlap_state_reset_wait: Unknown event %s\n", + irlap_event[event]); + ret = -1; + break; + } + return ret; +} + +/* + * Function irlap_state_reset (self, event, skb, info) + * + * We have sent a SNRM reset command to the peer layer, and is awaiting + * reply. + * + */ +int irlap_state_reset( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info) +{ + int ret = 0; + + DEBUG( 3, __FUNCTION__ "(), event = %s\n", irlap_event[event]); + + ASSERT( self != NULL, return -1;); + ASSERT( self->magic == LAP_MAGIC, return -1;); + + switch( event) { + case RECV_DISC_FRAME: + del_timer( &self->final_timer); + + irlap_apply_default_connection_parameters( self); + + /* Always switch state before calling upper layers */ + irlap_next_state( self, LAP_NDM); + + irlap_disconnect_indication( self, LAP_NO_RESPONSE); + break; + case RECV_UA_RSP: + del_timer( &self->final_timer); + + /* Initiate connection state */ + irlap_initiate_connection_state( self); + + irlap_reset_confirm(); + + self->remote_busy = FALSE; + irlap_start_poll_timer( self, self->poll_timeout); + irlap_next_state( self, LAP_XMIT_P); + break; + case FINAL_TIMER_EXPIRED: + if ( self->retry_count < 3) { + irlap_wait_min_turn_around( self, &self->qos_tx); + + ASSERT( self->irdev != NULL, return -1;); + irlap_send_snrm_frame(self, + irda_device_get_qos( self->irdev)); + + self->retry_count++; /* Experimental!! */ + + irlap_start_final_timer( self, self->final_timeout); + irlap_next_state( self, LAP_RESET); + } else if ( self->retry_count >= self->N3) { + irlap_apply_default_connection_parameters( self); + + /* Always switch state before calling upper layers */ + irlap_next_state( self, LAP_NDM); + + irlap_disconnect_indication( self, LAP_NO_RESPONSE); + } + break; + + case RECV_SNRM_CMD: + DEBUG(3, "lap_reset: RECV_SNRM_CMD\n"); + irlap_initiate_connection_state( self); + irlap_wait_min_turn_around( self, &self->qos_tx); + irlap_send_ua_response_frame( self, &self->qos_rx); + irlap_reset_confirm(); + irlap_start_wd_timer( self, self->wd_timeout); + irlap_next_state( self, LAP_NDM); + break; + + default: + DEBUG( 0, "irlap_state_reset: Unknown event %s\n", + irlap_event[ event]); + ret = -1; + break; + } + return ret; +} + +/* + * Function irlap_state_xmit_s (event, skb, info) + * + * XMIT_S, The secondary station has been given the right to transmit, + * and we therefor do not expect to receive any transmissions from other + * stations. + */ +static int irlap_state_xmit_s( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info) +{ + int ret = 0; + + DEBUG( 4, __FUNCTION__ "(), event=%s\n", irlap_event[ event]); + + ASSERT( self != NULL, return -ENODEV;); + ASSERT( self->magic == LAP_MAGIC, return -EBADR;); + + switch( event) { + case SEND_I_CMD: + ASSERT( skb != NULL, return -1;); + DEBUG( 4, "irlap_state_xmit: Window=%d\n", self->window); + + /* + * Send frame only if send window > 1 + */ + if (( self->window > 0) && ( !self->remote_busy)) { + /* + * Test if we have transmitted more bytes over the + * link than its possible to do with the current + * speed and turn-around-time. + */ + if (( skb->len+self->bofs_count) > self->bytes_left) { + DEBUG( 4, "IrDA: Not allowed to transmit more bytes!\n"); + skb_queue_head( &self->tx_list, skb); + /* + * Switch to NRM_S, this is only possible + * when we are in secondary mode, since we + * must be sure that we don't miss any RR + * frames + */ + irlap_next_state( self, LAP_NRM_S); + + return -EPROTO; /* Try again later */ + } + self->bytes_left -= ( skb->len + self->bofs_count); + + /* + * Send data with final bit cleared only if window > 1 + * and there is more frames to be sent + */ + if (( self->window > 1) && + skb_queue_len( &self->tx_list) > 0) + { + DEBUG( 4, "irlap_state_xmit: window > 1\n"); + irlap_send_data_secondary( self, skb); + irlap_next_state( self, LAP_XMIT_S); + } else { + DEBUG( 4, "irlap_state_xmit: window <= 1\n"); + irlap_send_data_secondary_final( self, skb); + irlap_next_state( self, LAP_NRM_S); + } + } else { + DEBUG( 0, "Unable to send!\n"); + skb_queue_head( &self->tx_list, skb); + ret = -EPROTO; + } + break; + default: + DEBUG( 0, __FUNCTION__ "(), Unknown event %s\n", + irlap_event[ event]); + ret = -EINVAL; + break; + } + return ret; +} + +/* + * Function irlap_state_nrm_s (event, skb, info) + * + * NRM_S (Normal Response Mode as Secondary) state, in this state we are + * expecting to receive frames from the primary station + * + */ +static int irlap_state_nrm_s( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info) +{ + int ret = 0; + int ns_status; + int nr_status; + + DEBUG( 4, __FUNCTION__ "(), event=%s\n", irlap_event[ event]); + + ASSERT( self != NULL, return -1;); + ASSERT( self->magic == LAP_MAGIC, return -1;); + + switch( event) { + case RECV_RR_CMD: + self->retry_count = 0; + + /* + * Nr as expected? + */ + nr_status = irlap_validate_nr_received( self, info->nr); + if ( nr_status == NR_EXPECTED) { + if (( skb_queue_len( &self->tx_list) > 0) && + ( self->window > 0)) { + self->remote_busy = FALSE; + + /* Update Nr received */ + irlap_update_nr_received( self, info->nr); + del_timer( &self->wd_timer); + + irlap_wait_min_turn_around( self, &self->qos_tx); + irlap_next_state( self, LAP_XMIT_S); + } else { + self->remote_busy = FALSE; + /* Update Nr received */ + irlap_update_nr_received( self, info->nr); + irlap_wait_min_turn_around( self, &self->qos_tx); + + irlap_send_rr_frame( self, RSP_FRAME); + + irlap_start_wd_timer( self, self->wd_timeout); + irlap_next_state( self, LAP_NRM_S); + } + } else if ( nr_status == NR_UNEXPECTED) { + self->remote_busy = FALSE; + irlap_update_nr_received( self, info->nr); + irlap_resend_rejected_frames( self, RSP_FRAME); + + irlap_start_wd_timer( self, self->wd_timeout); + + /* Keep state */ + irlap_next_state( self, LAP_NRM_S); + } else { + DEBUG( 0, "irlap_state_nrm_s: **** " + "invalid nr not implemented!\n"); + } + if ( skb) + dev_kfree_skb( skb); + + break; + case RECV_I_CMD: + /* FIXME: must check for remote_busy below */ + DEBUG( 4, __FUNCTION__ "(), event=%s nr=%d, vs=%d, ns=%d, " + "vr=%d, pf=%d\n", irlap_event[event], info->nr, + self->vs, info->ns, self->vr, info->pf); + + self->retry_count = 0; + + ns_status = irlap_validate_ns_received( self, info->ns); + nr_status = irlap_validate_nr_received( self, info->nr); + /* + * Check for expected I(nformation) frame + */ + if ((ns_status == NS_EXPECTED) && (nr_status == NR_EXPECTED)) { + /* + * poll bit cleared? + */ + if ( !info->pf) { + self->vr = (self->vr + 1) % 8; + + /* Update Nr received */ + irlap_update_nr_received( self, info->nr); + + self->ack_required = TRUE; + + /* + * Starting WD-timer here is optional, but + * not recommended. Note 6 IrLAP p. 83 + */ + /* irda_start_timer( WD_TIMER, self->wd_timeout); */ + + /* Keep state, do not move this line */ + irlap_next_state( self, LAP_NRM_S); + + irlap_data_indication( self, skb); + break; + } else { + self->vr = (self->vr + 1) % 8; + + /* Update Nr received */ + irlap_update_nr_received( self, info->nr); + + /* + * We should wait before sending RR, and + * also before changing to XMIT_S + * state. (note 1, IrLAP p. 82) + */ + irlap_wait_min_turn_around( self, &self->qos_tx); + /* + * Any pending data requests? + */ + if (( skb_queue_len( &self->tx_list) > 0) && + ( self->window > 0)) + { + self->ack_required = TRUE; + + del_timer( &self->wd_timer); + + irlap_next_state( self, LAP_XMIT_S); + } else { + irlap_send_rr_frame( self, RSP_FRAME); + irlap_start_wd_timer( self, self->wd_timeout); + + /* Keep the state */ + irlap_next_state( self, LAP_NRM_S); + } + irlap_data_indication( self, skb); + + break; + } + } + /* + * Check for Unexpected next to send (Ns) + */ + if (( ns_status == NS_UNEXPECTED) && + ( nr_status == NR_EXPECTED)) + { + /* Unexpected next to send, with final bit cleared */ + if ( !info->pf) { + irlap_update_nr_received( self, info->nr); + + irlap_start_wd_timer( self, self->wd_timeout); + } else { + /* Update Nr received */ + irlap_update_nr_received( self, info->nr); + + irlap_wait_min_turn_around( self, &self->qos_tx); + irlap_send_rr_frame( self, CMD_FRAME); + + irlap_start_wd_timer( self, self->wd_timeout); + } + dev_kfree_skb( skb); + break; + } + + /* + * Unexpected Next to Receive(NR) ? + */ + if (( ns_status == NS_EXPECTED) && + ( nr_status == NR_UNEXPECTED)) + { + if ( info->pf) { + DEBUG( 4, "RECV_I_RSP: frame(s) lost\n"); + + self->vr = (self->vr + 1) % 8; + + /* Update Nr received */ + irlap_update_nr_received( self, info->nr); + + /* Resend rejected frames */ + irlap_resend_rejected_frames( self, RSP_FRAME); + + /* Keep state, do not move this line */ + irlap_next_state( self, LAP_NRM_S); + + irlap_data_indication( self, skb); + irlap_start_wd_timer( self, self->wd_timeout); + + break; + } + /* + * This is not documented in IrLAP!! Unexpected NR + * with poll bit cleared + */ + if ( !info->pf) { + self->vr = (self->vr + 1) % 8; + + /* Update Nr received */ + irlap_update_nr_received( self, info->nr); + + /* Keep state, do not move this line */ + irlap_next_state( self, LAP_NRM_S); + + irlap_data_indication( self, skb); + irlap_start_wd_timer( self, self->wd_timeout); + } + } + + if ( ret == NR_INVALID) { + DEBUG( 0, "NRM_S, NR_INVALID not implemented!\n"); + } + if ( ret == NS_INVALID) { + DEBUG( 0, "NRM_S, NS_INVALID not implemented!\n"); + } + break; + case RECV_UI_FRAME: + /* + * poll bit cleared? + */ + if ( !info->pf) { + irlap_unit_data_indication( self, skb); + irlap_next_state( self, LAP_NRM_S); /* Keep state */ + } else { + /* + * Any pending data requests? + */ + if (( skb_queue_len( &self->tx_list) > 0) && + ( self->window > 0) && !self->remote_busy) + { + irlap_unit_data_indication( self, skb); + + del_timer( &self->wd_timer); + + irlap_next_state( self, LAP_XMIT_S); + } else { + irlap_unit_data_indication( self, skb); + + irlap_wait_min_turn_around( self, &self->qos_tx); + + irlap_send_rr_frame( self, RSP_FRAME); + self->ack_required = FALSE; + + irlap_start_wd_timer( self, self->wd_timeout); + + /* Keep the state */ + irlap_next_state( self, LAP_NRM_S); + } + } + break; + case RECV_SNRM_CMD: +#if 1 + del_timer( &self->wd_timer); + DEBUG( 0, "irlap_state_nrm_s: received SNRM cmd\n"); + irlap_next_state( self, LAP_RESET); +#else + irlap_wait_min_turn_around( &self->qos_session); + irlap_send_ua_response_frame( &self->qos_session); + irda_start_timer( WD_TIMER, self->wd_timeout); + irlap_next_state( self, LAP_SCLOSE) + +#endif + break; + case WD_TIMER_EXPIRED: + DEBUG( 4, "WD_TIMER_EXPIRED: %ld\n", jiffies); + + /* + * Wait until retry_count * n matches negotiated threshold/ + * disconnect time (note 2 in IrLAP p. 82) + */ + DEBUG( 0, "retry_count = %d\n", self->retry_count); + + if (( self->retry_count < (self->N2/2)) && + ( self->retry_count != self->N1/2)) { + + irlap_start_wd_timer( self, self->wd_timeout); + self->retry_count++; + } else if ( self->retry_count == (self->N1/2)) { + irlap_status_indication( STATUS_NO_ACTIVITY); + irlap_start_wd_timer( self, self->wd_timeout); + self->retry_count++; + } else if ( self->retry_count >= self->N2/2) { + irlap_apply_default_connection_parameters( self); + + /* Always switch state before calling upper layers */ + irlap_next_state( self, LAP_NDM); + + irlap_disconnect_indication( self, LAP_NO_RESPONSE); + } + break; + + case RECV_DISC_FRAME: + /* Always switch state before calling upper layers */ + irlap_next_state( self, LAP_NDM); + + irlap_wait_min_turn_around( self, &self->qos_tx); + irlap_send_ua_response_frame( self, NULL); + del_timer( &self->wd_timer); + irlap_flush_all_queues( self); + irlap_apply_default_connection_parameters( self); + + irlap_disconnect_indication( self, LAP_DISC_INDICATION); + if (skb) + dev_kfree_skb( skb); + + break; + + case RECV_DISCOVERY_XID_CMD: + DEBUG( 3, "irlap_state_nrm_s: got event RECV_DISCOVER_XID_CMD!\n"); + del_timer( &self->final_timer); + + irlap_apply_default_connection_parameters( self); + + /* Always switch state before calling upper layers */ + irlap_next_state( self, LAP_NDM); + + irlap_disconnect_indication( self, LAP_DISC_INDICATION); + +#if 0 + irlap_wait_min_turn_around( self, &self->qos_session); + irlap_send_rr_frame( RSP_FRAME); + irda_start_timer( WD_TIMER, self->wd_timeout); + irlap_next_state( self, LAP_NRM_S); +#endif + break; + + default: + DEBUG( 0, "irlap_state_nrm_s: Unknown event %d, (%s)\n", + event, irlap_event[event]); + ret = -1; + break; + } + return ret; +} + +/* + * Function irlap_state_sclose (self, event, skb, info) + * + * + * + */ +static int irlap_state_sclose( struct irlap_cb *self, IRLAP_EVENT event, + struct sk_buff *skb, struct irlap_info *info) +{ + DEBUG( 0, __FUNCTION__ "(), Not implemented!\n"); + + return -1; +} diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c new file mode 100644 index 000000000000..07bbbabf16ab --- /dev/null +++ b/net/irda/irlap_frame.c @@ -0,0 +1,1420 @@ +/********************************************************************* + * + * Filename: irlap_frame.c + * Version: 0.3 + * Description: Build and transmit IrLAP frames + * Status: Experimental. + * Author: Dag Brattli + * Created at: Tue Aug 19 10:27:26 1997 + * Modified at: Mon Dec 14 14:24:05 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli , All Rights Resrved. + * + * 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. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +extern __u8 *irlmp_hint_to_service( __u8 *hint); + +/* + * Function irlap_insert_mtt (self, skb) + * + * Insert minimum turnaround time relevant information into the skb. We + * need to do this since it's per packet relevant information. + * + */ +__inline__ void irlap_insert_mtt( struct irlap_cb *self, struct sk_buff *skb) +{ + struct irlap_skb_cb *cb; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + cb = (struct irlap_skb_cb *) skb->cb; + + cb->mtt = self->mtt_required; + + /* Reset */ + self->mtt_required = 0; + + /* + * Delay equals negotiated BOFs count plus the number of BOFs to + * force the negotiated minimum turnaround time + */ + cb->xbofs = self->bofs_count+self->xbofs_delay; + + /* Reset XBOF's delay (used only for getting min turn time) */ + self->xbofs_delay = 0; + + DEBUG( 4, __FUNCTION__ "(), using %d xbofs\n", cb->xbofs); +} + +/* + * Function irlap_send_connect_snrm_cmd (void) + * + * Transmits a connect SNRM command frame + */ +void irlap_send_snrm_frame( struct irlap_cb *self, struct qos_info *qos) +{ + struct sk_buff *skb; + __u8 *frame; + int len; + int n; + + DEBUG( 4, "irlap_send_snrm_cmd()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + n = 0; + + /* Allocate frame */ + skb = dev_alloc_skb( 64); + if (skb == NULL) { + DEBUG( 0,"irlap_send_snrm_cmd: " + "Could not allocate an sk_buff of length %d\n", 64); + return; + } + + skb_put( skb, 2); + frame = skb->data; + + /* Insert address field */ + frame[n] = CMD_FRAME; + frame[n++] |= (qos) ? CBROADCAST : self->caddr; + + /* Insert control field */ + frame[n++] = SNRM_CMD | PF_BIT; + + /* + * If we are establishing a connection then insert QoS paramerters + */ + if (qos) { + skb_put( skb, 9); /* 21 left */ + memcpy( frame+n, &self->saddr, 4); n += 4; + memcpy( frame+n, &self->daddr, 4); n += 4; + + frame[n++] = self->caddr; + + /* skb_put( skb, 21); */ + len = irda_insert_qos_negotiation_params( qos, frame+n); + /* Should not be dangerous to do this afterwards */ + skb_put( skb, len); + } + skb->dev = self->netdev; + skb->h.raw = skb->data; + irlap_insert_mtt( self, skb); + + dev_queue_xmit( skb); + self->stats.tx_packets++; +} + +/* + * Function irlap_recv_snrm_cmd (skb, info) + * + * Received SNRM (Set Normal Response Mode) command frame + * + */ +static void irlap_recv_snrm_cmd( struct irlap_cb *self, struct sk_buff *skb, + struct irlap_info *info) +{ + struct snrm_frame *frame; + + DEBUG( 4, __FUNCTION__ "() <%ld>\n", jiffies); + + ASSERT( skb != NULL, return;); + ASSERT( info != NULL, return;); + + frame = ( struct snrm_frame *) skb->data; + + /* Copy peer device address */ + memcpy( &info->daddr, &frame->saddr, 4); + + /* Copy connection address */ + info->caddr = frame->ncaddr; + + irlap_do_event( self, RECV_SNRM_CMD, skb, info); +} + +/* + * Function irlap_send_ua_response_frame (qos) + * + * Send UA (Unnumbered Acknowledgement) frame + * + */ +void irlap_send_ua_response_frame( struct irlap_cb *self, + struct qos_info *qos) +{ + struct sk_buff *skb; + __u8 *frame; + int n; + int len; + + DEBUG( 4, __FUNCTION__ "() <%ld>\n", jiffies); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + skb = NULL; + n = 0; + + /* Allocate frame */ + skb = dev_alloc_skb( 64); + if (skb == NULL) { + DEBUG( 0, __FUNCTION__ + "Could not allocate an sk_buff of length %d\n", 64); + return; + } + + skb_put( skb, 10); + frame = skb->data; + + /* Build UA response */ + frame[n++] = self->caddr; + frame[n++] = UA_RSP | PF_BIT; + memcpy( frame+n, &self->saddr, 4); n += 4; + memcpy( frame+n, &self->daddr, 4); n += 4; + + /* Should we send QoS negotiation parameters? */ + if ( qos) { + len = irda_insert_qos_negotiation_params( qos, frame+n); + skb_put( skb, len); + } + + skb->dev = self->netdev; + skb->h.raw = skb->data; + irlap_insert_mtt( self, skb); + + dev_queue_xmit( skb); + self->stats.tx_packets++; +} + + +/* + * Function irlap_send_dm_frame (void) + * + * Send disconnected mode (DM) frame + * + */ +void irlap_send_dm_frame( struct irlap_cb *self) +{ + struct sk_buff *skb = NULL; + __u8 *frame; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + skb = dev_alloc_skb( 32); + if (skb == NULL) { + DEBUG( 0,"irlap_send_disc_frame: " + "Could not allocate an sk_buff of length %d\n", 64); + return; + } + + skb_put( skb, 2); + frame = skb->data; + + if ( self->state == LAP_NDM) + frame[0] = CBROADCAST; + else + frame[0] = self->caddr; + + frame[1] = DM_RSP | PF_BIT; + + skb->dev = self->netdev; + skb->h.raw = skb->data; + irlap_insert_mtt( self, skb); + + dev_queue_xmit( skb); + self->stats.tx_packets++; +} + +/* + * Function irlap_send_disc_frame (void) + * + * Send disconnect (DISC) frame + * + */ +void irlap_send_disc_frame( struct irlap_cb *self) +{ + struct sk_buff *skb = NULL; + __u8 *frame; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + skb = dev_alloc_skb( 32); + if (skb == NULL) { + DEBUG( 0,"irlap_send_disc_frame: " + "Could not allocate an sk_buff of length %d\n", 64); + return; + } + + skb_put( skb, 2); + frame = skb->data; + + frame[0] = self->caddr | CMD_FRAME; + frame[1] = DISC_CMD | PF_BIT; + + skb->dev = self->netdev; + skb->h.raw = skb->data; + irlap_insert_mtt( self, skb); + + dev_queue_xmit( skb); + self->stats.tx_packets++; +} + +/* + * Function irlap_send_discovery_xid_frame (S, s, command) + * + * Build and transmit a XID (eXchange station IDentifier) discovery + * frame. + */ +void irlap_send_discovery_xid_frame( struct irlap_cb *self, int S, __u8 s, + __u8 command, DISCOVERY *discovery) +{ + struct sk_buff *skb = NULL; + struct xid_frame *frame; + __u32 bcast = BROADCAST; + + DEBUG( 4, __FUNCTION__ "(), s=%d, S=%d, command=%d\n", s, S, command); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + ASSERT( discovery != NULL, return;); + + skb = dev_alloc_skb( 64); + if (skb == NULL) { + DEBUG( 0,"irlap_send_discovery_xid_frame: " + "Could not allocate an sk_buff of length %d\n", 64); + return; + } + + skb_put( skb, 14); + frame = ( struct xid_frame *) skb->data; + + if ( command) { + frame->caddr = CBROADCAST | CMD_FRAME; + frame->control = XID_CMD | PF_BIT; + } else { + frame->caddr = CBROADCAST; + frame->control = XID_RSP | PF_BIT; + } + frame->ident = XID_FORMAT; + + memcpy( &frame->saddr, &self->saddr, 4); + + if ( command) + memcpy( &frame->daddr, &bcast, 4); + else + memcpy( &frame->daddr, &self->daddr, 4); + + switch( S) { + case 1: + frame->flags = 0x00; + break; + case 6: + frame->flags = 0x01; + break; + case 8: + frame->flags = 0x02; + break; + case 16: + frame->flags = 0x03; + break; + default: + frame->flags = 0x02; + break; + } + + frame->slotnr = s; + frame->version = 0x00; + + /* + * Provide info for final slot only in commands, and for all + * responses. Send the second byte of the hint only if the + * EXTENSION bit is set in the first byte. + */ + if ( !command || ( frame->slotnr == 0xff)) { + int i; + + if( discovery->hint[0] & HINT_EXTENSION) + skb_put( skb, 3+discovery->info_len); + else + skb_put( skb, 2+discovery->info_len); + + i = 0; + frame->discovery_info[i++] = discovery->hint[0]; + if( discovery->hint[0] & HINT_EXTENSION) + frame->discovery_info[i++] = discovery->hint[1]; + + frame->discovery_info[i++] = discovery->charset; + + ASSERT( discovery->info_len < 30, return;); + + memcpy( &frame->discovery_info[i++], discovery->info, + discovery->info_len); + + } + + ASSERT( self->netdev != NULL, return;); + + skb->dev = self->netdev; + skb->h.raw = skb->data; + irlap_insert_mtt( self, skb); + + dev_queue_xmit( skb); + self->stats.tx_packets++; +} + +/* + * Function irlap_recv_discovery_xid_rsp (skb, info) + * + * Received a XID discovery response + * + */ +static void irlap_recv_discovery_xid_rsp( struct irlap_cb *self, + struct sk_buff *skb, + struct irlap_info *info) +{ + struct xid_frame *xid; + DISCOVERY *discovery = NULL; + char *text; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + ASSERT( info != NULL, return;); + + if (( discovery = kmalloc( sizeof( DISCOVERY), GFP_ATOMIC)) == NULL) { + DEBUG( 0, __FUNCTION__ "(), kmalloc failed!\n"); + return; + } + memset( discovery, 0, sizeof( DISCOVERY)); + + xid = (struct xid_frame *) skb->data; + + /* + * Copy peer device address and set the source address + */ + memcpy( &info->daddr, &xid->saddr, 4); + discovery->daddr = info->daddr; + discovery->saddr = self->saddr; + + DEBUG( 4, __FUNCTION__ "(), daddr=%08x\n", discovery->daddr); + + /* Get info returned from peer */ + discovery->hint[0] = xid->discovery_info[0]; + if ( xid->discovery_info[0] & HINT_EXTENSION) { + DEBUG( 4, "EXTENSION\n"); + discovery->hint[1] = xid->discovery_info[1]; + discovery->charset = xid->discovery_info[2]; + text = (char *) &xid->discovery_info[3]; + } else { + discovery->hint[1] = 0; + discovery->charset = xid->discovery_info[1]; + text = (char *) &xid->discovery_info[2]; + } + /* + * Terminate string, should be safe since this is where the + * FCS bytes resides. + */ + skb->data[skb->len] = '\0'; + strcpy( discovery->info, text); + + info->discovery = discovery; + + irlap_do_event( self, RECV_DISCOVERY_XID_RSP, skb, info); +} + +/* + * Function irlap_recv_discovery_xid_cmd (skb, info) + * + * Received a XID discovery command + * + */ +static void irlap_recv_discovery_xid_cmd( struct irlap_cb *self, + struct sk_buff *skb, + struct irlap_info *info) +{ + struct xid_frame *xid; + DISCOVERY *discovery = NULL; + char *text; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + ASSERT( info != NULL, return;); + + xid = (struct xid_frame *) skb->data; + + /* Copy peer device address */ + memcpy( &info->daddr, &xid->saddr, 4); + + switch ( xid->flags & 0x03) { + case 0x00: + info->S = 1; + break; + case 0x01: + info->S = 6; + break; + case 0x02: + info->S = 8; + break; + case 0x03: + info->S = 16; + break; + default: + /* Error!! */ + return; + } + info->s = xid->slotnr; + + /* + * Check if last frame + */ + if ( info->s == 0xff) { + /* + * We now have some discovery info to deliver! + */ + discovery = kmalloc( sizeof( DISCOVERY), GFP_ATOMIC); + if ( !discovery) { + DEBUG( 0, __FUNCTION__ "(), kmalloc failed!\n"); + return; + } + discovery->daddr = info->daddr; + discovery->saddr = self->saddr; + + DEBUG( 4, __FUNCTION__ "(), daddr=%08x\n", + discovery->daddr); + + discovery->hint[0] = xid->discovery_info[0]; + if ( xid->discovery_info[0] & HINT_EXTENSION) { + DEBUG( 4, "EXTENSION\n"); + discovery->hint[1] = xid->discovery_info[1]; + discovery->charset = xid->discovery_info[2]; + text = (char *) &xid->discovery_info[3]; + } else { + discovery->hint[1] = 0; + discovery->charset = xid->discovery_info[1]; + text = (char *) &xid->discovery_info[2]; + } + /* + * Terminate string, should be safe since this is where the + * FCS bytes resides. + */ + skb->data[skb->len] = '\0'; + strcpy( discovery->info, text); + + info->discovery = discovery; + } else + info->discovery = NULL; + + DEBUG( 4, __FUNCTION__"(), s=%d, S=%d <%ld>\n", + info->s, info->S, jiffies); + + irlap_do_event( self, RECV_DISCOVERY_XID_CMD, skb, info); +} + +/* + * Function irlap_send_rr_frame (self, command) + * + * Build and transmit RR (Receive Ready) frame. Notice that it is currently + * only possible to send RR frames with the poll bit set. + */ +void irlap_send_rr_frame( struct irlap_cb *self, int command) +{ + struct sk_buff *skb = NULL; + __u8 *frame; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + +#ifdef CONFIG_IRDA_RECYCLE_RR + if ( self->recycle_rr_skb) { + DEBUG( 4, __FUNCTION__ "(), recycling skb!\n"); + skb = self->recycle_rr_skb; + skb->stamp.tv_sec = 0; + self->recycle_rr_skb = NULL; + } +#endif + if ( !skb) { + skb = dev_alloc_skb( 32); + if (skb == NULL) { + printk( KERN_WARNING "irlap_send_rr_frame: " + "Could not allocate an skb of length %d\n", 32); + return; + } + skb_put( skb, 2); + } + ASSERT( skb->len == 2, return;); + + frame = skb->data; + + frame[0] = self->caddr; + frame[0] |= (command) ? CMD_FRAME : 0; + + frame[1] = RR | PF_BIT | (self->vr << 5); + + DEBUG( 4, __FUNCTION__ "(), vr=%d, %ld\n", self->vr, jiffies); + + skb->dev = self->netdev; + skb->h.raw = skb->data; + irlap_insert_mtt( self, skb); + + dev_queue_xmit( skb); + self->stats.tx_packets++; +} + +/* + * Function irlap_recv_rr_frame (skb, info) + * + * Received RR (Receive Ready) frame from peer station + * + */ +static void irlap_recv_rr_frame( struct irlap_cb *self, struct sk_buff *skb, + struct irlap_info *info, int command) +{ + __u8 *frame; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + + frame = skb->data; + info->nr = frame[1] >> 5; + + DEBUG( 4, __FUNCTION__ "(), nr=%d, %ld\n", info->nr, jiffies); + + /* + * Make sure the state-machine is in the right state for receiving, + * if not, then we just discard the received frame for now! + * TODO: check if we should queue this frame, or make tty tell that + * it is receiving frames until the frame is delivered instead of + * until it is outside a frame. + */ +#if 0 + if (( self->state != LAP_NRM_P) && ( self->state != LAP_NRM_S)) { + DEBUG( 0, __FUNCTION__ "(), Wrong state, dropping frame!\n"); + dev_kfree_skb( skb); + return; + } +#endif + +#ifdef CONFIG_IRDA_RECYCLE_RR + /* Only recycle one RR frame */ + if ( self->recycle_rr_skb == NULL) { + + /* Keep this skb, so it can be reused */ + self->recycle_rr_skb = skb; + + /* + * Set skb to NULL, so that the state machine will not + * deallocate it. + */ + skb = NULL; + } +#endif + /* Check if this is a command or a response frame */ + if ( command) + irlap_do_event( self, RECV_RR_CMD, skb, info); + else + irlap_do_event( self, RECV_RR_RSP, skb, info); +} + +/* + * Function irlap_send_rr_frame () + * + * Build and transmit RR (Receive Ready) frame + */ +void irlap_send_frmr_frame( struct irlap_cb *self, int command) +{ + struct sk_buff *skb = NULL; + __u8 *frame; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + skb = dev_alloc_skb( 32); + if (skb == NULL) { + printk( KERN_WARNING "irlap_send_frmr_frame: " + "Could not allocate an sk_buff of length %d\n", 32); + return; + } + + skb_put( skb, 2); + frame = skb->data; + + frame[0] = self->caddr; + frame[0] |= (command) ? CMD_FRAME : 0; + + frame[1] = (self->vs << 1); + frame[1] |= PF_BIT; + frame[1] |= (self->vr << 5); + + frame[2] = 0; + + DEBUG( 4, __FUNCTION__ "(), vr=%d, %ld\n",self->vr, jiffies); + + skb->dev = self->netdev; + skb->h.raw = skb->data; + irlap_insert_mtt( self, skb); + + dev_queue_xmit( skb); + self->stats.tx_packets++; +} + +/* + * Function irlap_recv_rnr_frame (self, skb, info) + * + * Received RNR (Receive Not Ready) frame from peer station + * + */ +static void irlap_recv_rnr_frame( struct irlap_cb *self, struct sk_buff *skb, + struct irlap_info *info) +{ + __u8 *frame; + + ASSERT( skb != NULL, return;); + ASSERT( info != NULL, return;); + + frame = skb->data; + info->nr = frame[1] >> 5; + + DEBUG( 4, __FUNCTION__ "(), nr=%d, %ld\n", info->nr, jiffies); + + irlap_do_event( self, RECV_RNR_FRAME, skb, info); +} + +/* + * Function irlap_recv_ua_frame (skb, frame) + * + * Received UA (Unnumbered Acknowledgement) frame + * + */ +static void irlap_recv_ua_frame( struct irlap_cb *self, struct sk_buff *skb, + struct irlap_info *info) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( skb != NULL, return;); + ASSERT( info != NULL, return;); + + irlap_do_event( self, RECV_UA_RSP, skb, info); +} + +/* + * Function irlap_send_data_primary(self, skb) + * + * + * + */ +void irlap_send_data_primary( struct irlap_cb *self, struct sk_buff *skb) +{ + struct sk_buff *tx_skb; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + + /* Initialize variables */ + tx_skb = NULL; + + if ( skb->data[1] == I_FRAME) { + + /* + * Insert frame sequence number (Vs) in control field before + * inserting into transmit window queue. + */ + skb->data[1] = I_FRAME | (self->vs << 1); + + /* * Copy buffer */ + tx_skb = skb_clone( skb, GFP_ATOMIC); + /* tx_skb = skb_copy( skb, GFP_ATOMIC); */ + if ( tx_skb == NULL) { + dev_kfree_skb( skb); + return; + } + + /* + * make sure the skb->sk accounting of memory usage is sane + */ + if (skb->sk != NULL) + skb_set_owner_w( tx_skb, skb->sk); + + /* + * Insert frame in store, in case of retransmissions + */ + skb_queue_tail( &self->wx_list, skb); + + self->vs = (self->vs + 1) % 8; + self->ack_required = FALSE; + self->window -= 1; + + irlap_send_i_frame( self, tx_skb, CMD_FRAME); + } else { + DEBUG( 4, __FUNCTION__ "(), sending unreliable frame\n"); + irlap_send_ui_frame( self, skb, CMD_FRAME); + self->window -= 1; + } +} +/* + * Function irlap_send_data_primary_poll ( self, skb) + * + * Send I(nformation) frame as primary with poll bit set + */ +void irlap_send_data_primary_poll( struct irlap_cb *self, struct sk_buff *skb) +{ + struct sk_buff *tx_skb; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + + IS_SKB( skb, return;); + + /* Initialize variables */ + tx_skb = NULL; + + /* Is this reliable or unreliable data? */ + if ( skb->data[1] == I_FRAME) { + + /* + * Insert frame sequence number (Vs) in control field before + * inserting into transmit window queue. + */ + skb->data[1] = I_FRAME | (self->vs << 1); + + /* Copy buffer */ + tx_skb = skb_clone( skb, GFP_ATOMIC); + /* tx_skb = skb_copy( skb, GFP_ATOMIC); */ + if ( tx_skb == NULL) { + dev_kfree_skb( skb); + return; + } + + /* + * make sure the skb->sk accounting of memory usage is sane + */ + if (skb->sk != NULL) + skb_set_owner_w( tx_skb, skb->sk); + + /* + * Insert frame in store, in case of retransmissions + */ + skb_queue_tail( &self->wx_list, skb); + + /* + * Set poll bit if necessary. We do this to the copied + * skb, since retransmitted need to set or clear the poll + * bit depending on when * they are sent. + */ + /* Stop P timer */ + del_timer( &self->poll_timer); + + tx_skb->data[1] |= PF_BIT; + + self->vs = (self->vs + 1) % 8; + self->ack_required = FALSE; + self->window = self->window_size; + + irlap_start_final_timer( self, self->final_timeout); + + irlap_send_i_frame( self, tx_skb, CMD_FRAME); + } else { + DEBUG( 4, __FUNCTION__ "(), sending unreliable frame\n"); + + del_timer( &self->poll_timer); + + if ( self->ack_required) { + irlap_send_ui_frame( self, skb, CMD_FRAME); + irlap_send_rr_frame( self, CMD_FRAME); + self->ack_required = FALSE; + } else { + skb->data[1] |= PF_BIT; + irlap_send_ui_frame( self, skb, CMD_FRAME); + } + self->window = self->window_size; + irlap_start_final_timer( self, self->final_timeout); + } +} + +/* + * Function irlap_send_data_secondary_final (self, skb) + * + * Send I(nformation) frame as secondary with final bit set + * + */ +void irlap_send_data_secondary_final( struct irlap_cb *self, + struct sk_buff *skb) +{ + struct sk_buff *tx_skb = NULL; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + + IS_SKB( skb,return;); + + /* Is this reliable or unreliable data? */ + if ( skb->data[1] == I_FRAME) { + + /* + * Insert frame sequence number (Vs) in control field before + * inserting into transmit window queue. + */ + skb->data[1] = I_FRAME | (self->vs << 1); + + tx_skb = skb_clone( skb, GFP_ATOMIC); + /* tx_skb = skb_copy( skb, GFP_ATOMIC); */ + if ( tx_skb == NULL) { + dev_kfree_skb( skb); + return; + } + + if (skb->sk != NULL) + skb_set_owner_w( tx_skb, skb->sk); + + /* Insert frame in store */ + skb_queue_tail( &self->wx_list, skb); + + tx_skb->data[1] |= PF_BIT; + + self->vs = (self->vs + 1) % 8; + self->window = self->window_size; + self->ack_required = FALSE; + + irlap_start_wd_timer( self, self->wd_timeout); + + irlap_send_i_frame( self, tx_skb, RSP_FRAME); + } else { + if ( self->ack_required) { + irlap_send_ui_frame( self, skb, RSP_FRAME); + irlap_send_rr_frame( self, RSP_FRAME); + self->ack_required = FALSE; + } else { + skb->data[1] |= PF_BIT; + irlap_send_ui_frame( self, skb, RSP_FRAME); + } + self->window = self->window_size; + + irlap_start_wd_timer( self, self->wd_timeout); + } +} + +/* + * Function irlap_send_data_secondary (self, skb) + * + * Send I(nformation) frame as secondary without final bit set + * + */ +void irlap_send_data_secondary( struct irlap_cb *self, struct sk_buff *skb) +{ + struct sk_buff *tx_skb = NULL; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + + IS_SKB( skb, return;); + + /* Is this reliable or unreliable data? */ + if ( skb->data[1] == I_FRAME) { + + /* + * Insert frame sequence number (Vs) in control field before + * inserting into transmit window queue. + */ + skb->data[1] = I_FRAME | (self->vs << 1); + + tx_skb = skb_clone( skb, GFP_ATOMIC); + /* tx_skb = skb_copy( skb, GFP_ATOMIC); */ + if ( tx_skb == NULL) { + dev_kfree_skb( skb); + return; + } + + if (skb->sk != NULL) + skb_set_owner_w( tx_skb, skb->sk); + + /* Insert frame in store */ + skb_queue_tail( &self->wx_list, skb); + + self->vs = (self->vs + 1) % 8; + self->ack_required = FALSE; + self->window -= 1; + + irlap_send_i_frame( self, tx_skb, RSP_FRAME); + } else { + irlap_send_ui_frame( self, skb, RSP_FRAME); + self->window -= 1; + } +} + +/* + * Function irlap_resend_rejected_frames (nr) + * + * Resend frames which has not been acknowledged. TODO: check that the + * traversal of the list is atomic, i.e that no-one tries to insert or + * remove frames from the list while we travers it! + * + * FIXME: It is not safe to traverse a this list without locking it! + */ +void irlap_resend_rejected_frames( struct irlap_cb *self, int command) +{ + struct sk_buff *tx_skb; + struct sk_buff *skb; + int count; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + DEBUG( 4, __FUNCTION__ "(), retry_count=%d\n", + self->retry_count); + + /* Initialize variables */ + skb = tx_skb = NULL; + + /* + * Resend all unacknowledged frames + */ + count = skb_queue_len( &self->wx_list); + skb = skb_peek( &self->wx_list); + while ( skb != NULL) { + irlap_wait_min_turn_around( self, &self->qos_tx); + + tx_skb = skb_clone( skb, GFP_ATOMIC); + /* tx_skb = skb_copy( skb, GFP_ATOMIC); */ + if ( tx_skb == NULL) { + /* Unlink tx_skb from list */ + tx_skb->next = tx_skb->prev = NULL; + tx_skb->list = NULL; + + dev_kfree_skb( skb); + return; + } + /* Unlink tx_skb from list */ + tx_skb->next = tx_skb->prev = NULL; + tx_skb->list = NULL; + + /* + * make sure the skb->sk accounting of memory usage is sane + */ + if ( skb->sk != NULL) + skb_set_owner_w( tx_skb, skb->sk); + + /* Clear old Nr field + poll bit */ + tx_skb->data[1] &= 0x0f; + + /* + * Set poll bit on the last frame retransmitted + */ + if ( count-- == 1) + tx_skb->data[1] |= PF_BIT; /* Set p/f bit */ + else + tx_skb->data[1] &= ~PF_BIT; /* Clear p/f bit */ + + irlap_send_i_frame( self, tx_skb, command); + + /* + * If our skb is the last buffer in the list, then + * we are finished, if not, move to the next sk-buffer + */ + if ( skb == skb_peek_tail( &self->wx_list)) + skb = NULL; + else + skb = skb->next; + } + /* + * We can now fill the window with additinal data frames + */ + return; /* Skip this for now, DB */ + + while ( skb_queue_len( &self->tx_list) > 0) { + + DEBUG( 0, "irlap_resend_rejected_frames: " + "sending additional frames!\n"); + if (( skb_queue_len( &self->tx_list) > 0) && + ( self->window > 0)) { + skb = skb_dequeue( &self->tx_list); + ASSERT( skb != NULL, return;); + + /* + * If send window > 1 then send frame with pf + * bit cleared + */ + if (( self->window > 1) && + skb_queue_len( &self->tx_list) > 0) + { + irlap_send_data_primary( self, skb); + } else { + irlap_send_data_primary_poll( self, skb); + } + } + } +} + +/* + * Function irlap_send_ui_frame (self, skb, command) + * + * Contruct and transmit an Unnumbered Information (UI) frame + * + */ +void irlap_send_ui_frame( struct irlap_cb *self, struct sk_buff *skb, + int command) +{ + __u8 *frame; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + + frame = skb->data; + + /* Insert connection address */ + frame[0] = self->caddr; + frame[0] |= (command) ? CMD_FRAME : 0; + + skb->dev = self->netdev; + skb->h.raw = skb->data; + irlap_insert_mtt( self, skb); + + dev_queue_xmit( skb); + self->stats.tx_packets++; +} + +/* + * Function irlap_send_i_frame (skb) + * + * Contruct and transmit Information (I) frame + */ +void irlap_send_i_frame( struct irlap_cb *self, struct sk_buff *skb, + int command) +{ + __u8 *frame; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + + frame = skb->data; + + /* Insert connection address */ + frame[0] = self->caddr; + frame[0] |= (command) ? CMD_FRAME : 0; + + /* Insert next to receive (Vr) */ + frame[1] |= (self->vr << 5); /* insert nr */ + +#if 0 + { + int vr, vs, pf; + + /* Chech contents of various fields */ + vr = frame[1] >> 5; + vs = (frame[1] >> 1) & 0x07; + pf = (frame[1] >> 4) & 0x01; + + DEBUG( 4, __FUNCTION__ "(), vs=%d, vr=%d, p=%d, %ld\n", + vs, vr, pf, jiffies); + } +#endif + skb->dev = self->netdev; + skb->h.raw = skb->data; + irlap_insert_mtt( self, skb); + + dev_queue_xmit( skb); + self->stats.tx_packets++; +} + +/* + * Function irlap_recv_i_frame (skb, frame) + * + * Receive and parse an I (Information) frame + * + */ +static void irlap_recv_i_frame( struct irlap_cb *self, struct sk_buff *skb, + struct irlap_info *info, int command) +{ + __u8 *frame; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + + frame = skb->data; + + info->nr = frame[1] >> 5; /* Next to receive */ + info->pf = frame[1] & PF_BIT; /* Final bit */ + info->ns = (frame[1] >> 1) & 0x07; /* Next to send */ + + DEBUG( 4, __FUNCTION__"(), ns=%d, nr=%d, pf=%d, %ld\n", + info->ns, info->nr, info->pf>>4, jiffies); + + /* + * Make sure the state-machine is in the right state for receiving, + * if not, then we just discard the received frame for now! + * TODO: check if we should queue this frame, or make tty tell that + * it is receiving frames until the frame is delivered instead of + * until it is outside a frame. + */ + if (( self->state != LAP_NRM_P) && ( self->state != LAP_NRM_S)) { + DEBUG( 0, __FUNCTION__ "(), Wrong state, dropping frame!\n"); + dev_kfree_skb( skb); + return; + } + + /* Check if this is a command or a response frame */ + if ( command) + irlap_do_event( self, RECV_I_CMD, skb, info); + else + irlap_do_event( self, RECV_I_RSP, skb, info); +} + +/* + * Function irlap_recv_ui_frame (self, skb, info) + * + * Receive and parse an Unnumbered Information (UI) frame + * + */ +static void irlap_recv_ui_frame( struct irlap_cb *self, struct sk_buff *skb, + struct irlap_info *info) +{ + __u8 *frame; + + DEBUG( 4, __FUNCTION__ "()\n"); + + frame = skb->data; + + info->pf = frame[1] & PF_BIT; /* Final bit */ + + irlap_do_event( self, RECV_UI_FRAME, skb, info); +} + +/* + * Function irlap_recv_frmr_frame (skb, frame) + * + * Received Frame Reject response. + * + */ +static void irlap_recv_frmr_frame( struct irlap_cb *self, struct sk_buff *skb, + struct irlap_info *info) +{ + __u8 *frame; + int w, x, y, z; + + DEBUG( 0, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + ASSERT( info != NULL, return;); + + frame = skb->data; + + info->nr = frame[2] >> 5; /* Next to receive */ + info->pf = frame[2] & PF_BIT; /* Final bit */ + info->ns = (frame[2] >> 1) & 0x07; /* Next to send */ + + w = frame[3] & 0x01; + x = frame[3] & 0x02; + y = frame[3] & 0x04; + z = frame[3] & 0x08; + + if ( w) { + DEBUG( 0, "Rejected control field is undefined or not " + "implemented.\n"); + } + if ( x) { + DEBUG( 0, "Rejected control field was invalid because it " + "contained a non permitted I field.\n"); + } + if ( y) { + DEBUG( 0, "Received I field exceeded the maximum negotiated " + "for the existing connection or exceeded the maximum " + "this station supports if no connection exists.\n"); + } + if ( z) { + DEBUG( 0, "Rejected control field control field contained an " + "invalid Nr count.\n"); + } + irlap_do_event( self, RECV_FRMR_RSP, skb, info); +} + +/* + * Function irlap_input (skb) + * + * Called when a frame is received. Dispatches the right receive function + * for processing of the frame. + */ +int irlap_input( struct sk_buff *skb, struct device *netdev, + struct packet_type *ptype) +{ + struct irlap_info info; + struct irlap_cb *self; + struct irda_device *idev; + __u8 *frame; + int i, command; + __u8 control; + + idev = ( struct irda_device *) netdev->priv; + + ASSERT( idev != NULL, return -1;); + self = idev->irlap; + + ASSERT( self != NULL, return -1;); + ASSERT( self->magic == LAP_MAGIC, return -1;); + ASSERT(( skb != NULL) && (skb->len > 1), return -1;); + + frame = skb->data; + + command = frame[0] & CMD_FRAME; + info.caddr = frame[0] & CBROADCAST; + + info.pf = frame[1] & PF_BIT; + info.control = frame[1] & ~PF_BIT; /* Mask away poll/final bit */ + + control = info.control; + + /* + * First check if this frame addressed to us + */ + if (( info.caddr != self->caddr) && ( info.caddr != CBROADCAST)) { + + DEBUG( 0, __FUNCTION__ "(), Received frame is not for us!\n"); + for(i=0; i<(skb->len < 15?skb->len:15);i++) { + printk( "%02x ", frame[i]); + } + printk("\n"); + + dev_kfree_skb( skb); + + return 0; + } + /* + * Optimize for the common case and check if the frame is an + * I(nformation) frame. Only I-frames have bit 0 set to 0 + */ + if( ~control & 0x01) { + irlap_recv_i_frame( self, skb, &info, command); + self->stats.rx_packets++; + return 0; + } + /* + * We now check is the frame is an S(upervisory) frame. Only + * S-frames have bit 0 set to 1 and bit 1 set to 0 + */ + if ( ~control & 0x02) { + /* + * Received S(upervisory) frame, check which frame type it is + * only the first nibble is of interest + */ + switch( control & 0x0f) { + case RR: + irlap_recv_rr_frame( self, skb, &info, command); + self->stats.rx_packets++; + break; + case RNR: + DEBUG( 3, "*** RNR frame received! pf = %d ***\n", + info.pf >> 4); + irlap_recv_rnr_frame( self, skb, &info); + self->stats.rx_packets++; + break; + case REJ: + DEBUG( 0, "*** REJ frame received! ***\n"); + break; + case SREJ: + DEBUG( 0, "*** SREJ frame received! ***\n"); + break; + default: + DEBUG( 0, "Unknown S frame %02x received!\n", + info.control); + break; + } + return 0; + } + /* + * This must be a C(ontrol) frame + */ + switch( control) { + case XID_RSP: + DEBUG( 4, "XID rsp frame received!\n"); + irlap_recv_discovery_xid_rsp( self, skb, &info); + break; + case XID_CMD: + DEBUG( 4, "XID cmd frame received!\n"); + irlap_recv_discovery_xid_cmd( self, skb, &info); + break; + case SNRM_CMD: + DEBUG( 4, "SNRM frame received!\n"); + irlap_recv_snrm_cmd( self, skb, &info); + break; + case DM_RSP: + DEBUG( 0, "DM rsp frame received!\n"); + irlap_next_state( self, LAP_NDM); + break; + case DISC_CMD: + DEBUG( 0, "DISC cmd frame received!\n"); + irlap_do_event( self, RECV_DISC_FRAME, skb, &info); + break; + case TEST_CMD: + DEBUG( 0, "Test frame received!\n"); + dev_kfree_skb( skb); + break; + case UA_RSP: + DEBUG( 4, "UA rsp frame received!\n"); + irlap_recv_ua_frame( self, skb, &info); + break; + case FRMR_RSP: + DEBUG( 4, "FRMR_RSP recevied!\n"); + irlap_recv_frmr_frame( self, skb, &info); + break; + case UI_FRAME: + DEBUG( 4, "UI-frame received!\n"); + irlap_recv_ui_frame( self, skb, &info); + break; + default: + DEBUG( 0, "Unknown frame %02x received!\n", info.control); + dev_kfree_skb( skb); + break; + } + self->stats.rx_packets++; + + return 0; +} diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c new file mode 100644 index 000000000000..8e3706600ed6 --- /dev/null +++ b/net/irda/irlmp.c @@ -0,0 +1,1341 @@ +/********************************************************************* + * + * Filename: irlmp.c + * Version: 0.8 + * Description: IrDA Link Management Protocol (LMP) layer + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sun Aug 17 20:54:32 1997 + * Modified at: Mon Dec 14 11:54:08 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli , + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Master structure */ +struct irlmp_cb *irlmp = NULL; + +int sysctl_discovery = 0; +char sysctl_devname[65]; + +__u8 *irlmp_hint_to_service( __u8 *hint); +#ifdef CONFIG_PROC_FS +int irlmp_proc_read( char *buf, char **start, off_t offset, int len, + int unused); +#endif + +/* + * Function irlmp_init (void) + * + * Create (allocate) the main IrLMP structure and the pointer array + * which will contain pointers to each instance of a LSAP. + */ +__initfunc(int irlmp_init(void)) +{ + DEBUG( 4, "--> irlmp_init\n"); + + /* Initialize the irlmp structure. */ + if ( irlmp == NULL) { + irlmp = kmalloc( sizeof(struct irlmp_cb), GFP_KERNEL); + if ( irlmp == NULL) + return -ENOMEM; + } + memset( irlmp, 0, sizeof(struct irlmp_cb)); + + irlmp->magic = LMP_MAGIC; + + irlmp->registry = hashbin_new( HB_LOCAL); + irlmp->links = hashbin_new( HB_LOCAL); + irlmp->unconnected_lsaps = hashbin_new( HB_GLOBAL); + + irlmp->free_lsap_sel = 0x10; /* Servers use 0x00-0x0f */ +#ifdef CONFIG_IRDA_CACHE_LAST_LSAP + irlmp->cache.valid = FALSE; +#endif + strcpy( sysctl_devname, "Linux"); + + /* Do discovery every 3 seconds */ + init_timer( &irlmp->discovery_timer); + irlmp_start_discovery_timer( irlmp, 600); + + return 0; +} + +/* + * Function irlmp_cleanup (void) + * + * Remove IrLMP layer + * + */ +void irlmp_cleanup(void) +{ + /* Check for main structure */ + ASSERT( irlmp != NULL, return;); + ASSERT( irlmp->magic == LMP_MAGIC, return;); + + del_timer( &irlmp->discovery_timer); + + /* FIXME, we need a special function to deallocate LAPs */ + hashbin_delete( irlmp->links, (FREE_FUNC) kfree); + hashbin_delete( irlmp->unconnected_lsaps, (FREE_FUNC) kfree); + hashbin_delete( irlmp->registry, (FREE_FUNC) kfree); + + /* De-allocate main structure */ + kfree( irlmp); + irlmp = NULL; +} + +/* + * Function irlmp_open_lsap (slsap, notify) + * + * Register with IrLMP and create a local LSAP, + * returns handle to LSAP. + */ +struct lsap_cb *irlmp_open_lsap( __u8 slsap_sel, struct notify_t *notify) +{ + struct lsap_cb *self; + + ASSERT( notify != NULL, return NULL;); + ASSERT( irlmp != NULL, return NULL;); + ASSERT( irlmp->magic == LMP_MAGIC, return NULL;); + + DEBUG( 4, "irlmp_open_lsap(), slsap_sel=%02x\n", slsap_sel); + + /* + * Does the client care which Source LSAP selector it gets? + */ + if ( slsap_sel == LSAP_ANY) { + /* + * Find unused LSAP + */ + slsap_sel = irlmp_find_free_slsap(); + if ( slsap_sel == 0) + return NULL; + } else { + /* + * Client wants specific LSAP, so check if it's already + * in use + */ + if ( irlmp_slsap_inuse( slsap_sel)) { + return NULL; + } + if ( slsap_sel > irlmp->free_lsap_sel) + irlmp->free_lsap_sel = slsap_sel+1; + } + + /* + * Allocate new instance of a LSAP connection + */ + self = kmalloc( sizeof(struct lsap_cb), GFP_ATOMIC); + if ( self == NULL) { + printk( KERN_ERR "IrLMP: Can't allocate memory for " + "LSAP control block!\n"); + return NULL; + } + memset( self, 0, sizeof(struct lsap_cb)); + + self->magic = LMP_LSAP_MAGIC; + self->slsap_sel = slsap_sel; + self->dlsap_sel = LSAP_ANY; + + init_timer( &self->watchdog_timer); + + ASSERT( notify->instance != NULL, return NULL;); + self->notify = *notify; + + irlmp_next_lsap_state( self, LSAP_DISCONNECTED); + + /* + * Insert into queue of unconnected LSAPs + */ + hashbin_insert( irlmp->unconnected_lsaps, (QUEUE *) self, + self->slsap_sel, NULL); + + return self; +} + +/* + * Function irlmp_close_lsap (self) + * + * Remove an instance of a LSAP + */ +static void __irlmp_close_lsap( struct lsap_cb *self) +{ + DEBUG( 4, "irlmp_close()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LSAP_MAGIC, return;); + + /* + * Set some of the variables to preset values + */ + self->magic = ~LMP_LSAP_MAGIC; + del_timer( &self->watchdog_timer); /* Important! */ + +#ifdef CONFIG_IRDA_CACHE_LAST_LSAP + ASSERT( irlmp != NULL, return;); + irlmp->cache.valid = FALSE; +#endif + /* + * Deallocate structure + */ + kfree( self); + + DEBUG( 4, "irlmp_close() -->\n"); +} + +/* + * Function irlmp_close_lsap (self) + * + * + * + */ +void irlmp_close_lsap( struct lsap_cb *self) +{ + struct lap_cb *lap; + struct lsap_cb *lsap; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LSAP_MAGIC, return;); + + lap = self->lap; + + /* + * Find out if we should remove this LSAP from a link or from the + * list of unconnected lsaps (not associated with a link) + */ + if ( lap == NULL) { + lsap = hashbin_remove( irlmp->unconnected_lsaps, + self->slsap_sel, NULL); + } else { + ASSERT( lap != NULL, return;); + ASSERT( lap->magic == LMP_LAP_MAGIC, return;); + + lsap = hashbin_remove( lap->lsaps, self->slsap_sel, NULL); + } + if ( lsap == NULL) { + DEBUG( 0, __FUNCTION__ + "(), Looks like somebody has removed me already!\n"); + return; + } + ASSERT( lsap == self, return;); + + __irlmp_close_lsap( self); +} + +/* + * Function irlmp_register_irlap (saddr, notify) + * + * Register IrLAP layer with IrLMP. There is possible to have multiple + * instances of the IrLAP layer, each connected to different IrDA ports + * + */ +void irlmp_register_irlap( struct irlap_cb *irlap, __u32 saddr, + struct notify_t *notify) +{ + struct lap_cb *lap; + + DEBUG( 4, __FUNCTION__ "(), Registered IrLAP, saddr = %08x\n", + saddr); + + ASSERT( irlmp != NULL, return;); + ASSERT( irlmp->magic == LMP_MAGIC, return;); + ASSERT( notify != NULL, return;); + + /* + * Allocate new instance of a LSAP connection + */ + lap = kmalloc( sizeof(struct lap_cb), GFP_KERNEL); + if ( lap == NULL) { + printk( KERN_ERR "IrLMP: Can't allocate memory for " + "LAP control block!\n"); + return; + } + memset( lap, 0, sizeof(struct lap_cb)); + + lap->irlap = irlap; + lap->magic = LMP_LAP_MAGIC; + lap->saddr = saddr; + lap->lsaps = hashbin_new( HB_GLOBAL); + lap->cachelog = hashbin_new( HB_LOCAL); + + irlmp_next_lap_state( lap, LAP_STANDBY); + + /* + * Insert into queue of unconnected LSAPs + */ + hashbin_insert( irlmp->links, (QUEUE *) lap, lap->saddr, NULL); + + /* + * We set only this variable so IrLAP can tell us on which link the + * different events happened on + */ + irda_notify_init( notify); + notify->instance = lap; +} + +/* + * Function irlmp_unregister_irlap (saddr) + * + * IrLAP layer has been removed! + * + */ +void irlmp_unregister_irlap( __u32 saddr) +{ + struct lap_cb *self; + + DEBUG( 4, __FUNCTION__ "()\n"); + + self = hashbin_remove( irlmp->links, saddr, NULL); + if ( self != NULL) { + ASSERT( self->magic == LMP_LAP_MAGIC, return;); + + self->magic = ~LMP_LAP_MAGIC; + kfree( self); + } else { + DEBUG( 0, "irlmp_unregister_irlap(), Didn't find LAP!\n"); + } +} + +void dump_discoveries( hashbin_t *log) +{ + DISCOVERY *d; + + ASSERT( log != NULL, return;); + + d = (DISCOVERY *) hashbin_get_first( log); + while( d != NULL) { + DEBUG( 0, "Discovery:\n"); + DEBUG( 0, " daddr=%08x\n", d->daddr); + DEBUG( 0, " name=%s\n", d->info); + + d = (DISCOVERY *) hashbin_get_next( log); + } +} + +/* + * Function irlmp_connect_request (handle, dlsap, userdata) + * + * Connect with a peer LSAP + * + */ +void irlmp_connect_request( struct lsap_cb *self, __u8 dlsap_sel, __u32 daddr, + struct qos_info *qos, struct sk_buff *userdata) +{ + struct sk_buff *skb = NULL; + struct lap_cb *lap; + struct lsap_cb *lsap; + unsigned long flags; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LSAP_MAGIC, return;); + + DEBUG( 4, "irlmp_connect_request(), " + "slsap_sel=%02x, dlsap_sel=%02x, daddr=%08x\n", + self->slsap_sel, dlsap_sel, daddr); + + if ( self->connected) { + DEBUG( 0, __FUNCTION__ "(), Error: already connected!!\n"); + + return; + } + + /* Any userdata? */ + if ( userdata == NULL) { + skb = dev_alloc_skb( 64); + if (skb == NULL) { + DEBUG( 0, "irlmp_connect_request: " + "Could not allocate an sk_buff of length %d\n", + 64); + return; + } + skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER); + } else + skb = userdata; + + /* Make room for MUX control header ( 3 bytes) */ + ASSERT( skb_headroom( skb) >= LMP_CONTROL_HEADER, return;); + skb_push( skb, LMP_CONTROL_HEADER); + + self->dlsap_sel = dlsap_sel; + self->tmp_skb = skb; + + /* + * Find out which link to connect on, and make sure nothing strange + * happens while we traverse the list + */ + save_flags( flags); + cli(); + + lap = (struct lap_cb *) hashbin_get_first( irlmp->links); + while ( lap != NULL) { + ASSERT( lap->magic == LMP_LAP_MAGIC, return;); + /* dump_discoveries( lap->cachelog); */ + + if ( hashbin_find( lap->cachelog, daddr, NULL)) { + DEBUG( 4, "irlmp_connect_request() found link to connect on!\n"); + self->lap = lap; + break; + } + lap = (struct lap_cb *) hashbin_get_next( irlmp->links); + } + restore_flags(flags); + + /* + * Remove LSAP from list of unconnected LSAPs and insert it into the + * list of connected LSAPs for the particular link */ + lsap = hashbin_remove( irlmp->unconnected_lsaps, self->slsap_sel, + NULL); + + /* Check if we found a link to connect on */ + if ( self->lap == NULL) { + DEBUG( 0, __FUNCTION__ "(), Unable to find a usable link!\n"); + return; + } + + ASSERT( lsap != NULL, return;); + ASSERT( lsap->magic == LMP_LSAP_MAGIC, return;); + ASSERT( lsap->lap != NULL, return;); + ASSERT( lsap->lap->magic == LMP_LAP_MAGIC, return;); + + hashbin_insert( self->lap->lsaps, (QUEUE *) self, self->slsap_sel, + NULL); + + self->connected = TRUE; + + /* + * User supplied qos specifications? + */ + if ( qos) + self->qos = *qos; + + DEBUG( 4, "*** Connecting SLSAP=%02x, DLSAP= %02x\n", + self->slsap_sel, self->dlsap_sel); + + irlmp_do_lsap_event( self, LM_CONNECT_REQUEST, skb); +} + +/* + * Function irlmp_connect_indication (self) + * + * Incomming connection + * + */ +void irlmp_connect_indication( struct lsap_cb *self, struct sk_buff *skb) +{ + int max_seg_size; + + DEBUG( 4, "irlmp_connect_indication()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LSAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + ASSERT( self->lap != NULL, return;); + + self->qos = *self->lap->qos; + + max_seg_size = self->lap->qos->data_size.value; + DEBUG( 4, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size); + + /* Hide LMP_CONTROL_HEADER header from layer above */ + skb_pull( skb, LMP_CONTROL_HEADER); + + if ( self->notify.connect_indication) + self->notify.connect_indication( self->notify.instance, self, + &self->qos, max_seg_size, + skb); +} + +/* + * Function irlmp_connect_response (handle, userdata) + * + * Service user is accepting connection + * + */ +void irlmp_connect_response( struct lsap_cb *self, struct sk_buff *userdata) +{ + DEBUG( 4, "irlmp_connect_response()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LSAP_MAGIC, return;); + ASSERT( userdata != NULL, return;); + + self->connected = TRUE; + + DEBUG( 4, "irlmp_connect_response: slsap_sel=%02x, dlsap_sel=%02x\n", + self->slsap_sel, self->dlsap_sel); + + /* Make room for MUX control header ( 3 bytes) */ + ASSERT( skb_headroom( userdata) >= LMP_CONTROL_HEADER, return;); + skb_push( userdata, LMP_CONTROL_HEADER); + + irlmp_do_lsap_event( self, LM_CONNECT_RESPONSE, userdata); +} + +/* + * Function irlmp_connect_confirm (handle, skb) + * + * LSAP connection confirmed peer device! + */ +void irlmp_connect_confirm( struct lsap_cb *self, struct sk_buff *skb) +{ + int max_seg_size; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( skb != NULL, return;); + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LSAP_MAGIC, return;); + + ASSERT( self->lap != NULL, return;); + self->qos = *self->lap->qos; + + max_seg_size = self->qos.data_size.value; + DEBUG( 4, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size); + + /* Hide LMP_CONTROL_HEADER header from layer above */ + skb_pull( skb, LMP_CONTROL_HEADER); + + if ( self->notify.connect_confirm) { + self->notify.connect_confirm( self->notify.instance, self, + &self->qos, max_seg_size, skb); + } +} + +/* + * Function irlmp_disconnect_request (handle, userdata) + * + * The service user is requesting disconnection, this will not remove the + * LSAP, but only mark it as disconnected + */ +void irlmp_disconnect_request( struct lsap_cb *self, struct sk_buff *userdata) +{ + struct lsap_cb *lsap; + + DEBUG( 4, "irlmp_disconnect_request()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LSAP_MAGIC, return;); + + /* Already disconnected? */ + if ( !self->connected) { + DEBUG( 0, __FUNCTION__ "(), already disconnected!\n"); + return; + } + + ASSERT( userdata != NULL, return;); + ASSERT( self->connected == TRUE, return;); + + skb_push( userdata, LMP_CONTROL_HEADER); + + /* + * Do the event before the other stuff since we must know + * which lap layer that the frame should be transmitted on + */ + irlmp_do_lsap_event( self, LM_DISCONNECT_REQUEST, userdata); + + /* + * Remove LSAP from list of connected LSAPs for the particular link + * and insert it into the list of unconnected LSAPs + */ + ASSERT( self->lap != NULL, return;); + ASSERT( self->lap->magic == LMP_LAP_MAGIC, return;); + ASSERT( self->lap->lsaps != NULL, return;); + + lsap = hashbin_remove( self->lap->lsaps, self->slsap_sel, NULL); + + ASSERT( lsap != NULL, return;); + ASSERT( lsap->magic == LMP_LSAP_MAGIC, return;); + ASSERT( lsap == self, return;); + + hashbin_insert( irlmp->unconnected_lsaps, (QUEUE *) self, + self->slsap_sel, NULL); + + /* Reset some values */ + self->connected = FALSE; + self->dlsap_sel = LSAP_ANY; + self->lap = NULL; +} + +/* + * Function irlmp_disconnect_indication (reason, userdata) + * + * LSAP is being closed! + */ +void irlmp_disconnect_indication( struct lsap_cb *self, LM_REASON reason, + struct sk_buff *userdata) +{ + struct lsap_cb *lsap; + + DEBUG( 4, "irlmp_disconnect_indication()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LSAP_MAGIC, return;); + ASSERT( self->connected == TRUE, return;); + + DEBUG( 4, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", + self->slsap_sel, self->dlsap_sel); + + self->connected = FALSE; + self->dlsap_sel = LSAP_ANY; + + /* + * Remove assosiation betwen this LSAP and the kink it used + */ + ASSERT( self->lap != NULL, return;); + ASSERT( self->lap->lsaps != NULL, return;); + + lsap = hashbin_remove( self->lap->lsaps, self->slsap_sel, NULL); + + ASSERT( lsap != NULL, return;); + ASSERT( lsap == self, return;); + hashbin_insert( irlmp->unconnected_lsaps, (QUEUE *) lsap, + lsap->slsap_sel, NULL); + + self->lap = NULL; + + /* FIXME: the reasons should be extracted somewhere else? */ + if ( userdata) { + DEBUG( 4, "irlmp_disconnect_indication: reason=%02x\n", + userdata->data[3]); + } + + /* + * Inform service user + */ + if ( self->notify.disconnect_indication) { + self->notify.disconnect_indication( self->notify.instance, + self, reason, userdata); + } +} + +/* + * Function irlmp_discovery_request (nslots) + * + * Do a discovery of devices in front of the computer + * + */ +void irlmp_discovery_request( int nslots) +{ + struct lap_cb *lap; + + DEBUG( 4, "irlmp_discovery_request()\n"); + + ASSERT( irlmp != NULL, return;); + + if ( !sysctl_discovery) + return; + + /* + * Construct new discovery info to be used by IrLAP, + * TODO: no need to do this every time! + */ + irlmp->discovery_cmd.hint[0] = irlmp->hint[0]; + irlmp->discovery_cmd.hint[1] = irlmp->hint[1]; + + /* + * Set character set for device name (we use ASCII), and + * copy device name. Remember to make room for a \0 at the + * end + */ + irlmp->discovery_cmd.charset = CS_ASCII; + + strncpy( irlmp->discovery_cmd.info, sysctl_devname, 31); + irlmp->discovery_cmd.info_len = strlen( irlmp->discovery_cmd.info); + + /* + * Try to send discovery packets on all links + */ + lap = ( struct lap_cb *) hashbin_get_first( irlmp->links); + while ( lap != NULL) { + ASSERT( lap->magic == LMP_LAP_MAGIC, return;); + + DEBUG( 4, "irlmp_discovery_request() sending request!\n"); + irlmp_do_lap_event( lap, LM_LAP_DISCOVERY_REQUEST, NULL); + + lap = ( struct lap_cb *) hashbin_get_next( irlmp->links); + } +} + +/* + * Function irlmp_check_services (discovery) + * + * + * + */ +void irlmp_check_services( DISCOVERY *discovery) +{ + struct irlmp_registration *entry; + struct irmanager_event event; + __u8 *service; + int i = 0; + + printk( KERN_INFO "IrDA Discovered: %s\n", discovery->info); + printk( KERN_INFO " Services: "); + + + service = irlmp_hint_to_service( discovery->hint); + if (service != NULL) { + /* + * Check all services on the device + */ + while ( service[i] != S_END) { + DEBUG( 4, "service=%02x\n", service[i]); + entry = hashbin_find( irlmp->registry, + service[i], NULL); + if ( entry && entry->discovery_callback) { + DEBUG( 4, "discovery_callback!\n"); + entry->discovery_callback( discovery); + } else { + /* + * Found no clients for dealing with this + * service, so ask the user space irmanager + * to try to load the right module for us + */ + + event.event = EVENT_DEVICE_DISCOVERED; + event.service = service[i]; + event.daddr = discovery->daddr; + sprintf( event.info, "%s", + discovery->info); + irmanager_notify( &event); + } + i++; /* Next service */ + } + kfree( service); + } +} + +/* + * Function irlmp_discovery_confirm ( self, log) + * + * Some device(s) answered to our discovery request! Check to see which + * device it is, and give indication to the client(s) + * + */ +void irlmp_discovery_confirm( struct lap_cb *self, hashbin_t *log) +{ + DISCOVERY *discovery; + + DEBUG( 4, "irlmp_discovery_confirm()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LAP_MAGIC, return;); + + /* + * If log is missing this means that IrLAP was unable to perform the + * discovery, so restart discovery again with just the half timeout + * of the normal one. + */ + if ( !log) { + irlmp_start_discovery_timer( irlmp, 150); + return; + } + + /* + * Now, check all discovered devices (if any) + */ + discovery = ( DISCOVERY *) hashbin_get_first( log); + while ( discovery != NULL) { + self->daddr = discovery->daddr; + + DEBUG( 4, "discovery->daddr = 0x%08x\n", discovery->daddr); + + irlmp_check_services( discovery); + + discovery = ( DISCOVERY *) hashbin_get_next( log); + } +} + +/* + * Function irlmp_discovery_indication (discovery) + * + * A remote device is discovering us! + * + */ +void irlmp_discovery_indication( struct lap_cb *self, DISCOVERY *discovery) +{ + /* struct irda_event event; */ + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LAP_MAGIC, return;); + ASSERT( discovery != NULL, return;); + + DEBUG( 4, __FUNCTION__ "()\n"); + + DEBUG( 4, "discovery->daddr = 0x%08x\n", discovery->daddr); + self->daddr = discovery->daddr; + + /* + * Create a new discovery log if neccessary + */ + if ( self->cachelog == NULL) + self->cachelog = hashbin_new( HB_LOCAL); + /* + * Insert this discovery device into the discovery_log if its + * not there already + */ + if ( !hashbin_find( self->cachelog, discovery->daddr, NULL)) + hashbin_insert( self->cachelog, (QUEUE *) discovery, + discovery->daddr, NULL); + + irlmp_check_services( discovery); +} + +/* + * Function irlmp_get_discovery_response () + * + * Used by IrLAP to get the disocvery info it needs when answering + * discovery requests by other devices. + */ +DISCOVERY *irlmp_get_discovery_response() +{ + DEBUG( 4, "irlmp_get_discovery_response()\n"); + + ASSERT( irlmp != NULL, return NULL;); + + irlmp->discovery_rsp.hint[0] = irlmp->hint[0]; + irlmp->discovery_rsp.hint[1] = irlmp->hint[1]; + + /* + * Set character set for device name (we use ASCII), and + * copy device name. Remember to make room for a \0 at the + * end + */ + irlmp->discovery_rsp.charset = CS_ASCII; + + strncpy( irlmp->discovery_rsp.info, sysctl_devname, 31); + irlmp->discovery_rsp.info_len = strlen( irlmp->discovery_rsp.info) + 2; + + return &irlmp->discovery_rsp; +} + +/* + * Function irlmp_data_request (self, skb) + * + * Send some data to peer device + * + */ +void irlmp_data_request( struct lsap_cb *self, struct sk_buff *skb) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( skb != NULL, return;); + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LSAP_MAGIC, return;); + + /* Make room for MUX header */ + ASSERT( skb_headroom( skb) >= LMP_HEADER, return;); + skb_push( skb, LMP_HEADER); + + irlmp_do_lsap_event( self, LM_DATA_REQUEST, skb); +} + +/* + * Function irlmp_data_indication (handle, skb) + * + * Got data from LAP layer so pass it up to upper layer + * + */ +void irlmp_data_indication( struct lsap_cb *self, struct sk_buff *skb) +{ + DEBUG( 4, "irlmp_data_indication()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LSAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + + /* Hide LMP header from layer above */ + skb_pull( skb, LMP_HEADER); + + if ( self->notify.data_indication) + self->notify.data_indication(self->notify.instance, self, skb); +} + +/* + * Function irlmp_udata_request (self, skb) + * + * + * + */ +void irlmp_udata_request( struct lsap_cb *self, struct sk_buff *skb) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( skb != NULL, return;); + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LSAP_MAGIC, return;); + + /* Make room for MUX header */ + ASSERT( skb_headroom( skb) >= LMP_HEADER, return;); + skb_push( skb, LMP_HEADER); + + irlmp_do_lsap_event( self, LM_UDATA_REQUEST, skb); +} + +/* + * Function irlmp_udata_indication (self, skb) + * + * Send unreliable data (but still within the connection) + * + */ +void irlmp_udata_indication( struct lsap_cb *self, struct sk_buff *skb) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LSAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + + /* Hide LMP header from layer above */ + skb_pull( skb, LMP_HEADER); + + if ( self->notify.udata_indication) + self->notify.udata_indication( self->notify.instance, self, + skb); +} + +/* + * Function irlmp_connection_less_data_request (skb) + * + * Send out of connection UI frames + * + */ +void irlmp_connectionless_data_request( struct sk_buff *skb) +{ + DEBUG( 0, __FUNCTION__ "()\n"); +} + +/* + * Function irlmp_connection_less_data_indication (skb) + * + * + * + */ +void irlmp_connectionless_data_indication( struct sk_buff *skb) +{ + DEBUG( 0, __FUNCTION__ "()\n"); +} + +void irlmp_status_request(void) +{ + DEBUG( 0, "irlmp_status_request(), Not implemented\n"); +} + +void irlmp_status_indication( LINK_STATUS link, LOCK_STATUS lock) +{ + DEBUG( 4, "irlmp_status_indication(), Not implemented\n"); +} + +/* + * Function irlmp_hint_to_service (hint) + * + * Returns a list of all servics contained in the given hint bits. This + * funtion assumes that the hint bits have the size of two bytes only + */ +__u8 *irlmp_hint_to_service( __u8 *hint) +{ + __u8 *service; + int i = 0; + + /* Allocate array to store services in */ + service = kmalloc( 16, GFP_ATOMIC); + if ( !service) { + DEBUG( 0, "irlmp_hint_to_service: Unable to kmalloc!\n"); + return NULL; + } + + if ( !hint[0]) { + printk( "\n"); + return NULL; + } + if ( hint[0] & HINT_PNP) + printk( "PnP Compatible "); + if ( hint[0] & HINT_PDA) + printk( "PDA/Palmtop "); + if ( hint[0] & HINT_COMPUTER) + printk( "Computer "); + if ( hint[0] & HINT_PRINTER) { + printk( "Printer\n"); + service[i++] = S_PRINTER; + } + if ( hint[0] & HINT_MODEM) + printk( "Modem "); + if ( hint[0] & HINT_FAX) + printk( "Fax "); + if ( hint[0] & HINT_LAN) { + printk( "LAN Access\n"); + service[i++] = S_LAN; + } + /* + * Test if extension byte exists. This byte will usually be + * there, but this is not really required by the standard. + * (IrLMP p. 29) + */ + if ( hint[0] & HINT_EXTENSION) { + if ( hint[1] & HINT_TELEPHONY) + printk( "Telephony "); + + if ( hint[1] & HINT_FILE_SERVER) + printk( "File Server "); + + if ( hint[1] & HINT_COMM) { + printk( "IrCOMM "); + service[i++] = S_COMM; + } + if ( hint[1] & HINT_OBEX) { + printk( "IrOBEX "); + service[i++] = S_OBEX; + } + } + printk( "\n"); + + service[i] = S_END; + + return service; +} + +/* + * Function irlmp_service_to_hint (service, hint) + * + * + * + */ +void irlmp_service_to_hint( int service, __u8 *hint) +{ + switch (service) { + case S_PNP: + hint[0] |= HINT_PNP; + break; + case S_PDA: + hint[0] |= HINT_PDA; + break; + case S_COMPUTER: + hint[0] |= HINT_COMPUTER; + break; + case S_PRINTER: + hint[0] |= HINT_PRINTER; + break; + case S_MODEM: + hint[0] |= HINT_PRINTER; + break; + case S_LAN: + hint[0] |= HINT_LAN; + break; + case S_COMM: + hint[0] |= HINT_EXTENSION; + hint[1] |= HINT_COMM; + break; + case S_OBEX: + hint[0] |= HINT_EXTENSION; + hint[1] |= HINT_OBEX; + break; + default: + DEBUG( 0, "irlmp_service_to_hint(), Unknown service!\n"); + break; + } +} + +/* + * Function irlmp_register (service, type, callback) + * + * Register a local client or server with IrLMP + * + */ +void irlmp_register_layer( int service, int type, int do_discovery, + DISCOVERY_CALLBACK callback) +{ + struct irlmp_registration *entry; + + sysctl_discovery |= do_discovery; + + if ( type & SERVER) + irlmp_service_to_hint( service, irlmp->hint); + + /* Check if this service has been registred before */ + entry = hashbin_find( irlmp->registry, service, NULL); + if ( entry != NULL) { + /* Update type in entry */ + entry->type |= type; + + /* Update callback only if client, since servers don't + * use callbacks, and we don't want to overwrite a + * previous registred client callback + */ + if ( type & CLIENT) + entry->discovery_callback = callback; + return; + } + + /* Make a new registration */ + entry = kmalloc( sizeof( struct irlmp_registration), GFP_ATOMIC); + if ( !entry) { + DEBUG( 0, "irlmp_register(), Unable to kmalloc!\n"); + return; + } + + entry->service = service; + entry->type = type; + entry->discovery_callback = callback; + + hashbin_insert( irlmp->registry, (QUEUE*) entry, entry->service, NULL); +} + +/* + * Function irlmp_unregister (serivice) + * + * + * + */ +void irlmp_unregister_layer( int service, int type) +{ + struct irlmp_registration *entry; + + DEBUG( 4, __FUNCTION__ "()\n"); + + entry = hashbin_find( irlmp->registry, service, NULL); + if ( entry != NULL) { + DEBUG( 4, "Found entry to change or remove!\n"); + /* Remove this type from the service registration */ + entry->type &= ~type; + } + + if ( !entry) { + DEBUG( 0, "Unable to find entry to unregister!\n"); + return; + } + + /* + * Remove entry if there is no more client and server support + * left in entry + */ + if ( !entry->type) { + DEBUG( 4, __FUNCTION__ "(), removing entry!\n"); + entry = hashbin_remove( irlmp->registry, service, NULL); + if ( entry != NULL) + kfree( entry); + } + + /* Remove old hint bits */ + irlmp->hint[0] = 0; + irlmp->hint[1] = 0; + + /* Refresh current hint bits */ + entry = (struct irlmp_registration *) hashbin_get_first( irlmp->registry); + while( entry != NULL) { + if ( entry->type & SERVER) + irlmp_service_to_hint( entry->service, + irlmp->hint); + entry = (struct irlmp_registration *) + hashbin_get_next( irlmp->registry); + } +} + +/* + * Function irlmp_slsap_inuse (slsap) + * + * Check if the given source LSAP selector is in use + */ +int irlmp_slsap_inuse( __u8 slsap_sel) +{ + struct lsap_cb *self; + struct lap_cb *lap; + + ASSERT( irlmp != NULL, return TRUE;); + ASSERT( irlmp->magic == LMP_MAGIC, return TRUE;); + ASSERT( slsap_sel != LSAP_ANY, return TRUE;); + + DEBUG( 4, "irlmp_slsap_inuse()\n"); + + /* + * Check if slsap is already in use. To do this we have to loop over + * every IrLAP connection and check every LSAP assosiated with each + * the connection. + */ + lap = ( struct lap_cb *) hashbin_get_first( irlmp->links); + while ( lap != NULL) { + ASSERT( lap->magic == LMP_LAP_MAGIC, return TRUE;); + + self = (struct lsap_cb *) hashbin_get_first( lap->lsaps); + while ( self != NULL) { + ASSERT( self->magic == LMP_LSAP_MAGIC, return TRUE;); + + if (( self->slsap_sel == slsap_sel))/* && */ +/* ( self->dlsap_sel == LSAP_ANY)) */ + { + DEBUG( 4, "Source LSAP selector=%02x in use\n", + self->slsap_sel); + return TRUE; + } + self = (struct lsap_cb*) hashbin_get_next( lap->lsaps); + } + lap = (struct lap_cb *) hashbin_get_next( irlmp->links); + } + return FALSE; +} + +/* + * Function irlmp_find_free_slsap () + * + * Find a free source LSAP to use. This function is called if the service + * user has requested a source LSAP equal to LM_ANY + */ +__u8 irlmp_find_free_slsap(void) +{ + __u8 lsap_sel; + + ASSERT( irlmp != NULL, return -1;); + ASSERT( irlmp->magic == LMP_MAGIC, return -1;); + + lsap_sel = irlmp->free_lsap_sel++; + + DEBUG( 4, "irlmp_find_free_slsap(), picked next free lsap_sel=%02x\n", + lsap_sel); + + return lsap_sel; +} + +/* + * Function irlmp_convert_lap_reason (lap_reason) + * + * Converts IrLAP disconnect reason codes to IrLMP disconnect reason + * codes + * + */ +LM_REASON irlmp_convert_lap_reason( LAP_REASON lap_reason) +{ + int reason = LM_LAP_DISCONNECT; + + switch (lap_reason) { + case LAP_DISC_INDICATION: /* Received a disconnect request from peer */ + reason = LM_USER_REQUEST; + break; + case LAP_NO_RESPONSE: /* To many retransmits without response */ + reason = LM_LAP_DISCONNECT; + break; + case LAP_RESET_INDICATION: + reason = LM_LAP_RESET; + break; + case LAP_FOUND_NONE: + case LAP_MEDIA_BUSY: + case LAP_PRIMARY_CONFLICT: + reason = LM_CONNECT_FAILURE; + break; + default: + DEBUG( 0, __FUNCTION__ + "(), Unknow IrLAP disconnect reason %d!\n", lap_reason); + reason = LM_LAP_DISCONNECT; + break; + } + + return reason; +} + +#ifdef CONFIG_PROC_FS +/* + * Function irlmp_proc_read (buf, start, offset, len, unused) + * + * Give some info to the /proc file system + * + */ +int irlmp_proc_read( char *buf, char **start, off_t offset, int len, + int unused) +{ + struct lsap_cb *self; + struct lap_cb *lap; + unsigned long flags; + + ASSERT( irlmp != NULL, return 0;); + + save_flags( flags); + cli(); + + len = 0; + + len += sprintf( buf+len, "Unconnected LSAPs:\n"); + self = (struct lsap_cb *) hashbin_get_first( irlmp->unconnected_lsaps); + while ( self != NULL) { + ASSERT( self->magic == LMP_LSAP_MAGIC, return 0;); + len += sprintf( buf+len, "lsap state: %s, ", + irlsap_state[ self->lsap_state]); + len += sprintf( buf+len, + "slsap_sel: %#02x, dlsap_sel: %#02x, ", + self->slsap_sel, self->dlsap_sel); + len += sprintf( buf+len, "(%s)", self->notify.name); + len += sprintf( buf+len, "\n"); + + self = ( struct lsap_cb *) hashbin_get_next( + irlmp->unconnected_lsaps); + } + + len += sprintf( buf+len, "\nRegistred Link Layers:\n"); + lap = (struct lap_cb *) hashbin_get_first( irlmp->links); + while ( lap != NULL) { + ASSERT( lap->magic == LMP_LAP_MAGIC, return 0;); + + len += sprintf( buf+len, "lap state: %s, ", + irlmp_state[ lap->lap_state]); + + len += sprintf( buf+len, + "saddr: %#08x, daddr: %#08x, ", + lap->saddr, lap->daddr); + len += sprintf( buf+len, "\n"); + + len += sprintf( buf+len, "\nConnected LSAPs:\n"); + self = (struct lsap_cb *) hashbin_get_first( lap->lsaps); + while ( self != NULL) { + ASSERT( self->magic == LMP_LSAP_MAGIC, return 0;); + len += sprintf( buf+len, "lsap state: %s, ", + irlsap_state[ self->lsap_state]); + len += sprintf( buf+len, + "slsap_sel: %#02x, dlsap_sel: %#02x, ", + self->slsap_sel, self->dlsap_sel); + len += sprintf( buf+len, "(%s)", self->notify.name); + len += sprintf( buf+len, "\n"); + + self = ( struct lsap_cb *) hashbin_get_next( + lap->lsaps); + } + + lap = ( struct lap_cb *) hashbin_get_next( + irlmp->links); + } + + restore_flags( flags); + + return len; +} + +#endif /* PROC_FS */ + + + diff --git a/net/irda/irlmp_event.c b/net/irda/irlmp_event.c new file mode 100644 index 000000000000..2ef4fcfd54be --- /dev/null +++ b/net/irda/irlmp_event.c @@ -0,0 +1,693 @@ +/********************************************************************* + * + * Filename: irlmp_event.c + * Version: 0.1 + * Description: An IrDA LMP event driver for Linux + * Status: Experimental. + * Author: Dag Brattli + * Created at: Mon Aug 4 20:40:53 1997 + * Modified at: Wed Dec 9 01:48:48 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli , + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +char *irlmp_state[] = { + "LAP_STANDBY", + "LAP_U_CONNECT", + "LAP_ACTIVE", +}; + +char *irlsap_state[] = { + "LSAP_DISCONNECTED", + "LSAP_CONNECT", + "LSAP_CONNECT_PEND", + "LSAP_DATA_TRANSFER_READY", + "LSAP_SETUP", + "LSAP_SETUP_PEND", +}; + +static char *irlmp_event[] = { + "LM_CONNECT_REQUEST", + "LM_CONNECT_CONFIRM", + "LM_CONNECT_RESPONSE", + "LM_CONNECT_INDICATION", + + "LM_DISCONNECT_INDICATION", + "LM_DISCONNECT_REQUEST", + + "LM_DATA_REQUEST", + "LM_UDATA_REQUEST", + "LM_DATA_INDICATION", + "LM_UDATA_INDICATION", + + "LM_WATCHDOG_TIMEOUT", + + /* IrLAP events */ + "LM_LAP_CONNECT_REQUEST", + "LM_LAP_CONNECT_INDICATION", + "LM_LAP_CONNECT_CONFIRM", + "LM_LAP_DISCONNECT_INDICATION", + "LM_LAP_DISCONNECT_REQUEST", + "LM_LAP_DISCOVERY_REQUEST", + "LM_LAP_DISCOVERY_CONFIRM", +}; + +/* LAP Connection control proto declarations */ +static void irlmp_state_standby ( struct lap_cb *, IRLMP_EVENT, + struct sk_buff *); +static void irlmp_state_u_connect( struct lap_cb *, IRLMP_EVENT, + struct sk_buff *); +static void irlmp_state_active ( struct lap_cb *, IRLMP_EVENT, + struct sk_buff *); + +/* LSAP Connection control proto declarations */ +static void irlmp_state_disconnected( struct lsap_cb *, IRLMP_EVENT, + struct sk_buff *); +static void irlmp_state_connect ( struct lsap_cb *, IRLMP_EVENT, + struct sk_buff *); +static void irlmp_state_connect_pend( struct lsap_cb *, IRLMP_EVENT, + struct sk_buff *); +static void irlmp_state_dtr ( struct lsap_cb *, IRLMP_EVENT, + struct sk_buff *); +static void irlmp_state_setup ( struct lsap_cb *, IRLMP_EVENT, + struct sk_buff *); +static void irlmp_state_setup_pend ( struct lsap_cb *, IRLMP_EVENT, + struct sk_buff *); + +static void (*lap_state[]) ( struct lap_cb *, IRLMP_EVENT, struct sk_buff *) = +{ + irlmp_state_standby, + irlmp_state_u_connect, + irlmp_state_active, +}; + +static void (*lsap_state[])( struct lsap_cb *, IRLMP_EVENT, struct sk_buff *) = +{ + irlmp_state_disconnected, + irlmp_state_connect, + irlmp_state_connect_pend, + irlmp_state_dtr, + irlmp_state_setup, + irlmp_state_setup_pend +}; + +/* Do connection control events */ +void irlmp_do_lsap_event( struct lsap_cb *self, IRLMP_EVENT event, + struct sk_buff *skb) +{ + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LSAP_MAGIC, return;); + + DEBUG( 4, "do_lsap_event: EVENT = %s, STATE = %s\n", + irlmp_event[ event], irlmp_state[ self->lsap_state]); + + (*lsap_state[ self->lsap_state]) ( self, event, skb); +} + +/* + * Function do_lap_event (event, skb, info) + * + * Do IrLAP control events + * + */ +void irlmp_do_lap_event( struct lap_cb *self, IRLMP_EVENT event, + struct sk_buff *skb) +{ + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LAP_MAGIC, return;); + + DEBUG( 4, "do_lap_event: EVENT = %s, STATE = %s\n", + irlmp_event[event], + irlmp_state[self->lap_state]); + + (*lap_state[ self->lap_state]) ( self, event, skb); +} + +void irlmp_discovery_timer_expired( unsigned long data) +{ +/* struct irlmp_cb *self = ( struct irlmp_cb *) data; */ + + DEBUG( 4, "IrLMP, discovery timer expired!\n"); + + irlmp_discovery_request( 8); + + /* + * Restart timer + */ + irlmp_start_discovery_timer( irlmp, 300); +} + +void irlmp_watchdog_timer_expired( unsigned long data) +{ + struct lsap_cb *self = ( struct lsap_cb *) data; + + DEBUG( 0, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LSAP_MAGIC, return;); + + irlmp_do_lsap_event( self, LM_WATCHDOG_TIMEOUT, NULL); +} + +/********************************************************************* + * + * LAP connection control states + * + ********************************************************************/ + +/* + * Function irlmp_state_standby (event, skb, info) + * + * STANDBY, The IrLAP connection does not exist. + * + */ +static void irlmp_state_standby( struct lap_cb *self, IRLMP_EVENT event, + struct sk_buff *skb) +{ + DEBUG( 4, "irlmp_state_standby()\n"); + ASSERT( self->irlap != NULL, return;); + + switch( event) { + case LM_LAP_DISCOVERY_REQUEST: + /* irlmp_next_station_state( LMP_DISCOVER); */ + + irlap_discovery_request( self->irlap, &irlmp->discovery_cmd); + break; + case LM_LAP_DISCOVERY_CONFIRM: + /* irlmp_next_station_state( LMP_READY); */ + irlmp_discovery_confirm( self, self->cachelog); + break; + case LM_LAP_CONNECT_INDICATION: + /* It's important to switch state first, to avoid IrLMP to + * think that the link is free since IrLMP may then start + * discovery before the connection is properly set up. DB. + */ + irlmp_next_lap_state( self, LAP_ACTIVE); + + /* Just accept connection TODO, this should be fixed */ + irlap_connect_response( self->irlap, skb); + break; + case LM_LAP_CONNECT_REQUEST: + DEBUG( 4, "irlmp_state_standby() LS_CONNECT_REQUEST\n"); + + /* FIXME: need to set users requested QoS */ + irlap_connect_request( self->irlap, self->daddr, NULL, 0); + + irlmp_next_lap_state( self, LAP_U_CONNECT); + break; + case LM_LAP_DISCONNECT_INDICATION: + DEBUG( 4, __FUNCTION__ + "(), Error LM_LAP_DISCONNECT_INDICATION\n"); + + irlmp_next_lap_state( self, LAP_STANDBY); + break; + default: + DEBUG( 4, "irlmp_state_standby: Unknown event\n"); + break; + } +} + +/* + * Function irlmp_state_u_connect (event, skb, info) + * + * U_CONNECT, The layer above has tried to open an LSAP connection but + * since the IrLAP connection does not exist, we must first start an + * IrLAP connection. We are now waiting response from IrLAP. + * */ +static void irlmp_state_u_connect( struct lap_cb *self, IRLMP_EVENT event, + struct sk_buff *skb) +{ + struct lsap_cb *lsap; + struct lsap_cb *lsap_current; + + DEBUG( 4, "irlmp_state_u_connect()\n"); + + switch( event) { + case LM_LAP_CONNECT_CONFIRM: + /* For all lsap_ce E Associated do LS_Connect_confirm */ + irlmp_next_lap_state( self, LAP_ACTIVE); + + lsap = ( struct lsap_cb *) hashbin_get_first( self->lsaps); + while ( lsap != NULL) { + irlmp_do_lsap_event( lsap, + LM_LAP_CONNECT_CONFIRM, + skb); + lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps); + } + break; + case LM_LAP_DISCONNECT_INDICATION: + DEBUG( 0, __FUNCTION__ "(), IRLAP_DISCONNECT_INDICATION\n"); + + irlmp_next_lap_state( self, LAP_STANDBY); + + /* Send disconnect event to all LSAPs using this link */ + + lsap = ( struct lsap_cb *) hashbin_get_first( self->lsaps); + while ( lsap != NULL ) { + ASSERT( lsap->magic == LMP_LSAP_MAGIC, return;); + + lsap_current = lsap; + + /* Be sure to stay one item ahead */ + lsap = ( struct lsap_cb *) hashbin_get_next( self->lsaps); + irlmp_do_lsap_event( lsap_current, + LM_LAP_DISCONNECT_INDICATION, + NULL); + } + break; + case LM_LAP_DISCONNECT_REQUEST: + DEBUG( 0, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n"); + /* irlmp_next_lap_state( self, LAP_STANDBY); */ + +/* irlap_disconnect_request( self->irlap); */ + break; + default: + DEBUG( 4, "irlmp_state_u_connect: Unknown event\n"); + break; + } +} + +/* + * Function irlmp_state_active (event, skb, info) + * + * ACTIVE, IrLAP connection is active + * + */ +static void irlmp_state_active( struct lap_cb *self, IRLMP_EVENT event, + struct sk_buff *skb) +{ + struct lsap_cb *lsap; + struct lsap_cb *lsap_current; + + DEBUG( 4, "irlmp_state_active()\n"); + + switch( event) { + case LM_LAP_CONNECT_REQUEST: + DEBUG( 4, "irlmp_state_active(), LS_CONNECT_REQUEST\n"); + + /* + * LAP connection allready active, just bounce back! Since we + * don't know which LSAP that tried to do this, we have to + * notify all LSAPs using this LAP, but that should be safe to + * do anyway. + */ + lsap = ( struct lsap_cb *) hashbin_get_first( self->lsaps); + while ( lsap != NULL) { + irlmp_do_lsap_event( lsap, LM_LAP_CONNECT_CONFIRM, + skb); + lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps); + } + + /* Keep state */ + break; + case LM_LAP_DISCONNECT_REQUEST: + DEBUG( 4, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n"); + + /* + * Need to find out if we should close IrLAP or not + */ + if ( hashbin_get_size( self->lsaps) == 0) { + DEBUG( 0, __FUNCTION__ + "(), no more LSAPs so time to disconnect IrLAP\n"); + irlmp_next_lap_state( self, LAP_STANDBY); + + irlap_disconnect_request( self->irlap); + } + break; + case LM_LAP_DISCONNECT_INDICATION: + DEBUG( 4, __FUNCTION__ "(), IRLAP_DISCONNECT_INDICATION\n"); + + irlmp_next_lap_state( self, LAP_STANDBY); + + /* + * Inform all connected LSAP's using this link + */ + lsap = ( struct lsap_cb *) hashbin_get_first( self->lsaps); + while ( lsap != NULL ) { + ASSERT( lsap->magic == LMP_LSAP_MAGIC, return;); + + lsap_current = lsap; + + /* Be sure to stay one item ahead */ + lsap = ( struct lsap_cb *) hashbin_get_next( self->lsaps); + irlmp_do_lsap_event( lsap_current, + LM_LAP_DISCONNECT_INDICATION, + NULL); + } + break; + default: + DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event); + break; + } +} + +/********************************************************************* + * + * LSAP connection control states + * + ********************************************************************/ + +/* + * Function irlmp_state_disconnected (event, skb, info) + * + * DISCONNECTED + * + */ +static void irlmp_state_disconnected( struct lsap_cb *self, IRLMP_EVENT event, + struct sk_buff *skb) +{ + struct lsap_cb *lsap; + + DEBUG( 4, "irlmp_state_disconnected()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LSAP_MAGIC, return;); + + switch( event) { + case LM_CONNECT_REQUEST: + DEBUG( 4, "irlmp_state_disconnected: LM_CONNECT_REQUEST\n"); + irlmp_next_lsap_state( self, LSAP_SETUP_PEND); + + irlmp_do_lap_event( self->lap, LM_LAP_CONNECT_REQUEST, NULL); + + /* Start watchdog timer ( 5 secs for now) */ + irlmp_start_watchdog_timer( self, 500); + break; + case LM_CONNECT_INDICATION: + irlmp_next_lsap_state( self, LSAP_CONNECT_PEND); + + + /* + * Bind this LSAP to the IrLAP link where the connect was + * received + * FIXME: this should be done in the LAP state machine + */ + lsap = hashbin_remove( irlmp->unconnected_lsaps, + self->slsap_sel, NULL); + + ASSERT( lsap == self, return;); + + ASSERT( self->lap != NULL, return;); + ASSERT( self->lap->lsaps != NULL, return;); + + hashbin_insert( self->lap->lsaps, (QUEUE *) self, + self->slsap_sel, NULL); + + irlmp_do_lap_event( self->lap, LM_LAP_CONNECT_REQUEST, skb); + break; + default: + /* DEBUG( 4, "irlmp_state_disconnected: Unknown event %d\n", + event); */ + break; + } +} + +/* + * Function irlmp_state_connect (self, event, skb) + * + * CONNECT + * + */ +static void irlmp_state_connect( struct lsap_cb *self, IRLMP_EVENT event, + struct sk_buff *skb) +{ + + DEBUG( 4, "irlmp_state_connect()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LSAP_MAGIC, return;); + + switch( event) { + case LM_CONNECT_RESPONSE: + ASSERT( skb != NULL, return;); + + irlmp_send_lcf_pdu( self->lap, self->dlsap_sel, + self->slsap_sel, CONNECT_CNF, skb); + + del_timer( &self->watchdog_timer); + + irlmp_next_lsap_state( self, LSAP_DATA_TRANSFER_READY); + break; + default: + DEBUG( 4, "irlmp_state_connect: Unknown event\n"); + break; + } +} + +/* + * Function irlmp_state_connect_pend (event, skb, info) + * + * CONNECT_PEND + * + */ +static void irlmp_state_connect_pend( struct lsap_cb *self, IRLMP_EVENT event, + struct sk_buff *skb) +{ + DEBUG( 4, "irlmp_state_connect_pend()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LSAP_MAGIC, return;); + + switch( event) { + case LM_CONNECT_REQUEST: + /* Keep state */ + break; + case LM_CONNECT_RESPONSE: + printk( KERN_WARNING + "IrLMP CONNECT-PEND, No indication issued yet\n"); + /* Keep state */ + break; + case LM_DISCONNECT_REQUEST: + printk( KERN_WARNING + "IrLMP CONNECT-PEND, " + "Not yet bound to IrLAP connection\n"); + /* Keep state */ + break; + case LM_LAP_CONNECT_CONFIRM: + DEBUG( 4, "irlmp_state_connect_pend: LS_CONNECT_CONFIRM\n"); + irlmp_next_lsap_state( self, LSAP_CONNECT); + irlmp_connect_indication( self, skb); + break; + + default: + DEBUG( 4, "irlmp_state_connect_pend: Unknown event %d\n", + event); + break; + } +} + +/* + * Function irlmp_state_dtr (self, event, skb) + * + * DATA_TRANSFER_READY + * + */ +static void irlmp_state_dtr( struct lsap_cb *self, IRLMP_EVENT event, + struct sk_buff *skb) +{ + LM_REASON reason; + + DEBUG( 4, "irlmp_state_dtr()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LSAP_MAGIC, return;); + ASSERT( self->lap != NULL, return;); + + switch( event) { + case LM_CONNECT_REQUEST: + printk( KERN_WARNING + "IrLMP DTR: Error, LSAP allready connected\n"); + /* Keep state */ + break; + case LM_CONNECT_RESPONSE: + printk( KERN_WARNING + "IrLMP DTR: Error, LSAP allready connected\n"); + /* Keep state */ + break; + case LM_DISCONNECT_REQUEST: + ASSERT( skb != NULL, return;); + + irlmp_send_lcf_pdu( self->lap, self->dlsap_sel, + self->slsap_sel, DISCONNECT, skb); + irlmp_next_lsap_state( self, LSAP_DISCONNECTED); + + /* Try to close the LAP connection if its still there */ + if ( self->lap) { + DEBUG( 4, __FUNCTION__ "(), trying to close IrLAP\n"); + irlmp_do_lap_event( self->lap, + LM_LAP_DISCONNECT_REQUEST, + NULL); + } + + break; + case LM_DATA_REQUEST: + ASSERT( skb != NULL, return;); + irlmp_send_data_pdu( self->lap, self->dlsap_sel, + self->slsap_sel, FALSE, skb); + /* irlmp_next_lsap_state( DATA_TRANSFER_READY, info->handle);*/ + break; + case LM_UDATA_REQUEST: + ASSERT( skb != NULL, return;); + irlmp_send_data_pdu( self->lap, self->dlsap_sel, + self->slsap_sel, TRUE, skb); + break; + case LM_DATA_INDICATION: + irlmp_data_indication( self, skb); + /* irlmp_next_lsap_state( DATA_TRANSFER_READY, info->handle);*/ + break; + case LM_UDATA_INDICATION: + irlmp_udata_indication( self, skb); + /* irlmp_next_lsap_state( DATA_TRANSFER_READY, info->handle);*/ + break; + case LM_LAP_DISCONNECT_INDICATION: + irlmp_next_lsap_state( self, LSAP_DISCONNECTED); + + reason = irlmp_convert_lap_reason( self->lap->reason); + + irlmp_disconnect_indication( self, reason, NULL); + break; + case LM_DISCONNECT_INDICATION: + irlmp_next_lsap_state( self, LSAP_DISCONNECTED); + + ASSERT( self->lap != NULL, return;); + ASSERT( self->lap->magic == LMP_LAP_MAGIC, return;); + + reason = irlmp_convert_lap_reason( self->lap->reason); + + /* Try to close the LAP connection */ + DEBUG( 4, __FUNCTION__ "(), trying to close IrLAP\n"); + irlmp_do_lap_event( self->lap, LM_LAP_DISCONNECT_REQUEST, + NULL); + + irlmp_disconnect_indication( self, reason, skb); + + break; + default: + DEBUG( 4, "irlmp_state_dtr: Unknown event %d\n", event); + break; + } +} + +/* + * Function irlmp_state_setup (event, skb, info) + * + * SETUP, Station Control has set up the underlying IrLAP connection. + * An LSAP connection request has been transmitted to the peer + * LSAP-Connection Control FSM and we are awaiting reply. + */ +static void irlmp_state_setup( struct lsap_cb *self, IRLMP_EVENT event, + struct sk_buff *skb) +{ + LM_REASON reason; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LSAP_MAGIC, return;); + + DEBUG( 4, "irlmp_state_setup()\n"); + + switch( event) { + case LM_CONNECT_CONFIRM: + ASSERT( skb != NULL, return;); + + irlmp_next_lsap_state( self, LSAP_DATA_TRANSFER_READY); + + del_timer( &self->watchdog_timer); + + irlmp_connect_confirm( self, skb); + break; + case LM_DISCONNECT_INDICATION: + irlmp_next_lsap_state( self, LSAP_DISCONNECTED); + + del_timer( &self->watchdog_timer); + + ASSERT( self->lap != NULL, return;); + ASSERT( self->lap->magic == LMP_LAP_MAGIC, return;); + + reason = irlmp_convert_lap_reason( self->lap->reason); + + irlmp_disconnect_indication( self, reason, skb); + break; + default: + DEBUG( 4, "irlmp_state_setup: Unknown event %d\n", event); + break; + } +} + +/* + * Function irlmp_state_setup_pend (event, skb, info) + * + * SETUP_PEND, An LM_CONNECT_REQUEST has been received from the service + * user to set up an LSAP connection. A request has been sent to the + * LAP FSM to set up the underlying IrLAP connection, and we + * are awaiting confirm. + */ +static void irlmp_state_setup_pend( struct lsap_cb *self, IRLMP_EVENT event, + struct sk_buff *skb) +{ + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( irlmp != NULL, return;); + + switch( event) { + case LM_LAP_CONNECT_CONFIRM: + irlmp_send_lcf_pdu( self->lap, self->dlsap_sel, + self->slsap_sel, CONNECT_CMD, + self->tmp_skb); + irlmp_next_lsap_state( self, LSAP_SETUP); + break; + case LM_DISCONNECT_INDICATION: + del_timer( &self->watchdog_timer); + + irlmp_next_lsap_state( self, LSAP_DISCONNECTED); + break; + case LM_WATCHDOG_TIMEOUT: + DEBUG( 0, "irlmp_state_setup_pend() WATCHDOG_TIMEOUT!\n"); + + /* FIXME: should we do a disconnect_indication? */ + return; + ASSERT( self->lap != NULL, return;); + irlmp_do_lap_event( self->lap, LM_LAP_DISCONNECT_REQUEST, NULL); + irlmp_next_lsap_state( self, LSAP_DISCONNECTED); + break; + default: + DEBUG( 4, "irlmp_state_setup_pend: Unknown event %d\n", event); + break; + } +} + +void irlmp_next_lap_state( struct lap_cb *self, IRLMP_STATE state) +{ + DEBUG( 4, "LMP LAP = %s\n", irlmp_state[state]); + self->lap_state = state; +} + +void irlmp_next_lsap_state( struct lsap_cb *self, LSAP_STATE state) +{ + ASSERT( self != NULL, return;); + + DEBUG( 4, "LMP LSAP = %s\n", irlsap_state[state]); + self->lsap_state = state; +} diff --git a/net/irda/irlmp_frame.c b/net/irda/irlmp_frame.c new file mode 100644 index 000000000000..f735a4a69c24 --- /dev/null +++ b/net/irda/irlmp_frame.c @@ -0,0 +1,373 @@ +/********************************************************************* + * + * Filename: irlmp_frame.c + * Version: 0.1 + * Description: IrLMP frame implementation + * Status: Experimental. + * Author: Dag Brattli + * Created at: Tue Aug 19 02:09:59 1997 + * Modified at: Wed Dec 9 01:25:47 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1997 Dag Brattli , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include + +static struct lsap_cb *irlmp_find_lsap( struct lap_cb *self, __u8 dlsap, + __u8 slsap, int status); + +inline void irlmp_send_data_pdu( struct lap_cb *self, __u8 dlsap, __u8 slsap, + int expedited, struct sk_buff *skb) +{ + __u8 *frame; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + + frame = skb->data; + + frame[0] = dlsap; + frame[1] = slsap; + + if ( expedited) { + DEBUG( 4, __FUNCTION__ "(), sending expedited data\n"); + irlap_data_request( self->irlap, skb, FALSE); + } else { + DEBUG( 4, __FUNCTION__ "(), sending reliable data\n"); + irlap_data_request( self->irlap, skb, TRUE); + } +} + +/* + * Function irlmp_send_lcf_pdu (dlsap, slsap, opcode,skb) + * + * Send Link Control Frame to IrLAP + */ +void irlmp_send_lcf_pdu( struct lap_cb *self, __u8 dlsap, __u8 slsap, + __u8 opcode, struct sk_buff *skb) +{ + __u8 *frame; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + + frame = skb->data; + + frame[0] = dlsap | CONTROL_BIT; + frame[1] = slsap; + + frame[2] = opcode; + + if (opcode == DISCONNECT) + frame[3] = 0x01; /* Service user request */ + else + frame[3] = 0x00; /* rsvd */ + + ASSERT( self->irlap != NULL, return;); + irlap_data_request( self->irlap, skb, TRUE); +} + +/* + * Function irlmp_input (skb) + * + * Used by IrLAP to pass received data frames to IrLMP layer + * + */ +void irlmp_link_data_indication( struct lap_cb *self, int reliable, + struct sk_buff *skb) +{ + __u8 *fp; + __u8 slsap_sel; /* Source (this) LSAP address */ + __u8 dlsap_sel; /* Destination LSAP address */ + struct lsap_cb *lsap; + + + DEBUG( 4, "irlmp_link_data_indication()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + ASSERT( skb->len > 2, return;); + + fp = skb->data; + + /* + * The next statements may be confusing, but we do this so that + * destination LSAP of received frame is source LSAP in our view + */ + slsap_sel = fp[0] & ~CONTROL_BIT; + dlsap_sel = fp[1]; + + DEBUG( 4, "slsap_sel = %02x, dlsap_sel = %02x\n", slsap_sel, + dlsap_sel); + + /* + * Check if this is an incoming connection, since we must deal with + * it in a different way than other established connections. + */ + if (( fp[0] & CONTROL_BIT) && ( fp[2] == CONNECT_CMD)) { + DEBUG( 4,"Incoming connection, source LSAP=%d, dest LSAP=%d\n", + slsap_sel, dlsap_sel); + lsap = irlmp_find_lsap( self, dlsap_sel, slsap_sel, + CONNECT_CMD); + } else + lsap = irlmp_find_lsap( self, dlsap_sel, slsap_sel, 0); + + if ( lsap == NULL) { + DEBUG( 0, "IrLMP, Sorry, no LSAP for received frame!\n"); + DEBUG( 0, __FUNCTION__ + "(), slsap_sel = %02x, dlsap_sel = %02x\n", slsap_sel, + dlsap_sel); + if ( fp[0] & CONTROL_BIT) { + DEBUG( 0, __FUNCTION__ + "(), received control frame %02x\n", fp[2]); + } else { + DEBUG( 0, __FUNCTION__ + "(), received data frame\n"); + } + dev_kfree_skb( skb); + return; + } + + /* + * Check if we received a control frame? + */ + if ( fp[0] & CONTROL_BIT) { + /* DEBUG( 0, "irlmp_input: Got control frame\n"); */ + switch( fp[2]) { + case CONNECT_CMD: + DEBUG( 4, "irlmp_input: CONNECT_CMD\n"); + lsap->lap = self; + irlmp_do_lsap_event( lsap, LM_CONNECT_INDICATION, skb); + break; + case CONNECT_CNF: + irlmp_do_lsap_event( lsap, LM_CONNECT_CONFIRM, skb); + break; + case DISCONNECT: + DEBUG( 4, "irlmp_input: Disconnect indication!\n"); + irlmp_do_lsap_event( lsap, LM_DISCONNECT_INDICATION, + skb); + break; + case ACCESSMODE_CMD: + DEBUG( 0, "Access mode cmd not implemented!\n"); + break; + case ACCESSMODE_CNF: + DEBUG( 0, "Access mode cnf not implemented!\n"); + break; + default: + DEBUG( 0, "irlmp_input: Unknown control frame %02x\n", + fp[2]); + break; + } + } else if ( reliable == LAP_RELIABLE) { + /* Must be pure data */ + irlmp_do_lsap_event( lsap, LM_DATA_INDICATION, skb); + } else if ( reliable == LAP_UNRELIABLE) { + irlmp_do_lsap_event( lsap, LM_UDATA_INDICATION, skb); + } +} + +/* + * Function irlmp_link_disconnect_indication (reason, userdata) + * + * IrLAP has disconnected + * + */ +void irlmp_link_disconnect_indication( struct lap_cb *lap, + struct irlap_cb *irlap, + LAP_REASON reason, + struct sk_buff *userdata) +{ + DEBUG( 4, "irlmp_link_disconnect_indication()\n"); + + ASSERT( lap != NULL, return;); + ASSERT( lap->magic == LMP_LAP_MAGIC, return;); + + lap->reason = reason; + + /* FIXME: must do something with the userdata if any */ + + /* + * Inform station state machine + */ + irlmp_do_lap_event( lap, LM_LAP_DISCONNECT_INDICATION, NULL); +} + +/* + * Function irlmp_link_connect_indication (qos) + * + * Incoming LAP connection! + * + */ +void irlmp_link_connect_indication( struct lap_cb *self, struct qos_info *qos, + struct sk_buff *skb) +{ + DEBUG( 4, "irlmp_link_connect_indication()\n"); + + /* Copy QoS settings for this session */ + self->qos = qos; + + irlmp_do_lap_event( self, LM_LAP_CONNECT_INDICATION, skb); +} + +/* + * Function irlmp_link_connect_confirm (qos) + * + * LAP connection confirmed! + * + */ +void irlmp_link_connect_confirm( struct lap_cb *self, struct qos_info *qos, + struct sk_buff *userdata) +{ + DEBUG( 4, "irlmp_link_connect_confirm()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LAP_MAGIC, return;); + ASSERT( qos != NULL, return;); + + /* Copy QoS settings for this session */ + self->qos = qos; + + irlmp_do_lap_event( self, LM_LAP_CONNECT_CONFIRM, NULL); +} + +/* + * Function irlmp_link_discovery_confirm (self, log) + * + * Called by IrLAP with a list of discoveries after the discovery + * request has been carried out. A NULL log is received if IrLAP + * was unable to carry out the discovery request + * + */ +void irlmp_link_discovery_confirm( struct lap_cb *self, hashbin_t *log) +{ + DEBUG( 4, "irlmp_link_connect_confirm()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LMP_LAP_MAGIC, return;); + + if ( self->cachelog) + hashbin_delete( self->cachelog, (FREE_FUNC) kfree); + + self->cachelog = log; + + irlmp_do_lap_event( self, LM_LAP_DISCOVERY_CONFIRM, NULL); +} + +#ifdef CONFIG_IRDA_CACHE_LAST_LSAP +void irlmp_update_cache( struct lsap_cb *self) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + /* Update cache entry */ + irlmp->cache.dlsap_sel = self->dlsap_sel; + irlmp->cache.slsap_sel = self->slsap_sel; + irlmp->cache.lsap = self; + irlmp->cache.valid = TRUE; +} +#endif + +/* + * Function irlmp_find_handle (dlsap, slsap) + * + * Find handle assosiated with destination and source LSAP + * + */ +static struct lsap_cb *irlmp_find_lsap( struct lap_cb *self, __u8 dlsap_sel, + __u8 slsap_sel, int status) +{ + struct lsap_cb *lsap; + hashbin_t *queue; + + DEBUG( 4, "irlmp_find_lsap: dlsap_sel=0x%02x, slsap_sel=0x%02x\n", + dlsap_sel, slsap_sel); + + ASSERT( self != NULL, return NULL;); + ASSERT( self->magic == LMP_LAP_MAGIC, return NULL;); + + if ( status) + queue = irlmp->unconnected_lsaps; + else + queue = self->lsaps; + + /* + * Optimize for the common case. We assume that the last frame + * received is in the same connection as the last one, so check in + * cache first to avoid the linear search + */ +#ifdef CONFIG_IRDA_CACHE_LAST_LSAP + ASSERT( irlmp != NULL, return NULL;); + + if (( irlmp->cache.valid) && + ( irlmp->cache.slsap_sel == slsap_sel) && + ( irlmp->cache.dlsap_sel == dlsap_sel)) + { + DEBUG( 4, __FUNCTION__ "(), Using cached LSAP\n"); + return ( irlmp->cache.lsap); + } +#endif + lsap = ( struct lsap_cb *) hashbin_get_first( queue); + while ( lsap != NULL) { + /* + * Check if source LSAP (in our view!) match, and if + * dest LSAP is equal to LM_ANY, which is the case + * for incomming connections + */ + DEBUG( 4, "irlmp_find_lsap: " + "LSAP: lsap->dlsap=%d, lsap->slsap=%d\n", + lsap->dlsap_sel, lsap->slsap_sel); + + if (( status == CONNECT_CMD) && + ( lsap->slsap_sel == slsap_sel) && + ( lsap->dlsap_sel == LSAP_ANY)) + { + DEBUG( 4,"Incoming connection: Setting dlsap_sel=%d\n", + dlsap_sel); + lsap->dlsap_sel = dlsap_sel; + +#ifdef CONFIG_IRDA_CACHE_LAST_LSAP + irlmp_update_cache( lsap); +#endif + return lsap; + } + /* + * Check if source LSAP and dest LSAP selectors match. + */ + if (( lsap->slsap_sel == slsap_sel) && + ( lsap->dlsap_sel == dlsap_sel)) + { +#ifdef CONFIG_IRDA_CACHE_LAST_LSAP + irlmp_update_cache( lsap); +#endif + return lsap; + } + lsap = ( struct lsap_cb *) hashbin_get_next( queue); + } + + /* Sorry not found! */ + return NULL; +} diff --git a/net/irda/irmod.c b/net/irda/irmod.c new file mode 100644 index 000000000000..a172e91ca281 --- /dev/null +++ b/net/irda/irmod.c @@ -0,0 +1,397 @@ +/********************************************************************* + * + * Filename: irmod.c + * Version: 0.8 + * Description: IrDA module code and some other stuff + * Status: Experimental. + * Author: Dag Brattli + * Created at: Mon Dec 15 13:55:39 1997 + * Modified at: Mon Dec 14 20:10:28 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1997 Dag Brattli, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct irda irda; /* One global instance */ + +extern void irda_proc_register(void); +extern void irda_proc_unregister(void); +extern int irda_sysctl_register(void); +extern void irda_sysctl_unregister(void); + +extern void irda_proto_init(struct net_proto *pro); +extern void irda_proto_cleanup(void); + +extern int irda_device_init(void); +extern int irobex_init(void); +extern int irlan_init(void); +extern int irlan_client_init(void); +extern int irlan_server_init(void); +extern int ircomm_init(void); +extern int irvtd_init(void); + +static int irda_open( struct inode * inode, struct file *file); +static int irda_ioctl( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +static int irda_close( struct inode *inode, struct file *file); +static ssize_t irda_read( struct file *file, char *buffer, size_t count, + loff_t *noidea); +static ssize_t irda_write( struct file *file, const char *buffer, + size_t count, loff_t *noidea); +static u_int irda_poll( struct file *file, poll_table *wait); + +static struct file_operations irda_fops = { + NULL, /* seek */ + irda_read, /* read */ + irda_write, /* write */ + NULL, /* readdir */ + irda_poll, /* poll */ + irda_ioctl, /* ioctl */ + NULL, /* mmap */ + irda_open, + NULL, + irda_close, + NULL, + NULL, /* fasync */ +}; + +__initfunc(int irda_init(void)) +{ + printk( KERN_INFO "Linux Support for the IrDA (tm) protocols (Dag Brattli)\n"); + + irda_device_init(); + irlap_init(); + irlmp_init(); + iriap_init(); + irttp_init(); + +#ifdef CONFIG_PROC_FS + irda_proc_register(); +#endif +#ifdef CONFIG_SYSCTL + irda_sysctl_register(); +#endif + + irda.dev.minor = MISC_DYNAMIC_MINOR; + irda.dev.name = "irda"; + irda.dev.fops = &irda_fops; + + misc_register( &irda.dev); + + /* + * Initialize modules that got compiled into the kernel + */ +#ifdef CONFIG_IRLAN + irlan_init(); +#endif +#ifdef CONFIG_IRLAN_CLIENT + irlan_client_init(); +#endif +#ifdef CONFIG_IRLAN_SERVER + irlan_server_init(); +#endif +#ifdef CONFIG_IROBEX + irobex_init(); +#endif +#ifdef CONFIG_IRCOMM + ircomm_init(); + irvtd_init(); +#endif + + return 0; +} + +void irda_cleanup(void) +{ + misc_deregister( &irda.dev); + +#ifdef CONFIG_SYSCTL + irda_sysctl_unregister(); +#endif + +#ifdef CONFIG_PROC_FS + irda_proc_unregister(); +#endif + + /* Remove higher layers */ + irttp_cleanup(); + iriap_cleanup(); + + /* Remove lower layers */ + irda_device_cleanup(); + irlap_cleanup(); /* Must be done before irlmp_cleanup()! DB */ + + /* Remove middle layer */ + irlmp_cleanup(); +} + +/* + * Function irda_lock (lock) + * + * Lock variable. Returns false if the lock is already set. + * + */ +inline int irda_lock( int *lock) { + if ( test_and_set_bit( 0, (void *) lock)) { + printk("Trying to lock, already locked variable!\n"); + return FALSE; + } + return TRUE; +} + +/* + * Function irda_unlock (lock) + * + * Unlock variable. Returns false if lock is already unlocked + * + */ +inline int irda_unlock( int *lock) { + if ( !test_and_clear_bit( 0, (void *) lock)) { + printk("Trying to unlock already unlocked variable!\n"); + return FALSE; + } + return TRUE; +} + +/* + * Function irda_notify_init (notify) + * + * Used for initializing the notify structure + * + */ +void irda_notify_init( struct notify_t *notify) +{ + + notify->data_indication = NULL; + notify->udata_indication = NULL; + notify->connect_confirm = NULL; + notify->connect_indication = NULL; + notify->disconnect_indication = NULL; + notify->flow_indication = NULL; + notify->instance = NULL; + strncpy( notify->name, "Unknown", NOTIFY_MAX_NAME); +} + +/* + * Function irda_execute_as_process (self, callback, param) + * + * If a layer needs to have a function executed with a process context, + * then it can register the function here, and the function will then + * be executed as fast as possible. + * + */ +void irda_execute_as_process( void *self, TODO_CALLBACK callback, __u32 param) +{ + struct irda_todo *new; + struct irmanager_event event; + + /* Make new todo event */ + new = (struct irda_todo *) kmalloc( sizeof(struct irda_todo), + GFP_ATOMIC); + if ( new == NULL) { + return; + } + memset( new, 0, sizeof( struct irda_todo)); + + new->self = self; + new->callback = callback; + new->param = param; + + /* Queue todo */ + enqueue_last( &irda.todo_queue, (QUEUE *) new); + + event.event = EVENT_NEED_PROCESS_CONTEXT; + + /* Notify the user space manager */ + irmanager_notify( &event); +} + +/* + * Function irmanger_notify (event) + * + * Send an event to the user space manager + * + */ +void irmanager_notify( struct irmanager_event *event) +{ + struct irda_event *new; + + DEBUG( 4, __FUNCTION__ "()\n"); + + /* Make new IrDA Event */ + new = (struct irda_event *) kmalloc( sizeof(struct irda_event), + GFP_ATOMIC); + if ( new == NULL) { + return; + } + memset( new, 0, sizeof( struct irda_event)); + new->event = *event; + + /* Queue event */ + enqueue_last( &irda.event_queue, (QUEUE *) new); + + /* Wake up irmanager sleeping on read */ + wake_up_interruptible( &irda.wait_queue); +} + +static int irda_open( struct inode * inode, struct file *file) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + MOD_INC_USE_COUNT; + + return 0; +} + +/* + * Function irda_ioctl (inode, filp, cmd, arg) + * + * Ioctl, used by irmanager to ... + * + */ +static int irda_ioctl( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + struct irda_todo *todo; + int err = 0; + int size = _IOC_SIZE(cmd); + + DEBUG( 4, __FUNCTION__ "()\n"); + + if ( _IOC_DIR(cmd) & _IOC_READ) + err = verify_area( VERIFY_WRITE, (void *) arg, size); + else if ( _IOC_DIR(cmd) & _IOC_WRITE) + err = verify_area( VERIFY_READ, (void *) arg, size); + if ( err) + return err; + + switch( cmd) { + case IRMGR_IOCTNPC: + /* Got process context! */ + DEBUG( 4, __FUNCTION__ "(), got process context!\n"); + + while (( todo = (struct irda_todo *) dequeue_first( + &irda.todo_queue)) != NULL) + { + todo->callback( todo->self, todo->param); + + kfree( todo); + } + break; + + default: + return -ENOIOCTLCMD; + } + + return 0; +} + +static int irda_close( struct inode *inode, struct file *file) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + MOD_DEC_USE_COUNT; + + return 0; +} + +static ssize_t irda_read( struct file *file, char *buffer, size_t count, + loff_t *noidea) +{ + struct irda_event *event; + unsigned long flags; + int len; + + DEBUG( 4, __FUNCTION__ "()\n"); + + /* * Go to sleep and wait for event if there is no event to be read! */ + save_flags( flags); + cli(); + if ( !irda.event_queue) + interruptible_sleep_on( &irda.wait_queue); + restore_flags(flags); + + /* + * Ensure proper reaction to signals, and screen out + * blocked signals (page 112. linux device drivers) + */ + if ( signal_pending( current)) + return -ERESTARTSYS; + + event = (struct irda_event *) dequeue_first( &irda.event_queue); + + len = sizeof(struct irmanager_event); + copy_to_user( buffer, &event->event, len); + + /* Finished with event */ + kfree( event); + + return len; +} + +static ssize_t irda_write( struct file *file, const char *buffer, + size_t count, loff_t *noidea) +{ + DEBUG( 0, __FUNCTION__ "()\n"); + + return 0; +} + +static u_int irda_poll( struct file *file, poll_table *wait) +{ + DEBUG( 0, __FUNCTION__ "(), Sorry not implemented yet!\n"); + + return 0; +} + +#ifdef MODULE + +MODULE_AUTHOR("Dag Brattli "); +MODULE_DESCRIPTION("The Linux IrDA protocol subsystem"); + +/* + * Function init_module (void) + * + * Initialize the irda module + * + */ +int init_module(void) +{ + irda_proto_init(NULL); + + return 0; +} + +/* + * Function cleanup_module (void) + * + * Cleanup the irda module + * + */ +void cleanup_module(void) +{ + irda_proto_cleanup(); +} + +#endif diff --git a/net/irda/irobex/Config.in b/net/irda/irobex/Config.in new file mode 100644 index 000000000000..7e6f71b457f9 --- /dev/null +++ b/net/irda/irobex/Config.in @@ -0,0 +1,3 @@ + +dep_tristate 'IrOBEX protocol' CONFIG_IROBEX $CONFIG_IRDA + diff --git a/net/irda/irobex/Makefile b/net/irda/irobex/Makefile new file mode 100644 index 000000000000..1b028937b478 --- /dev/null +++ b/net/irda/irobex/Makefile @@ -0,0 +1,19 @@ +# +# Makefile for the Linux IrDA IrOBEX protocol layer. +# +# 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 definition is now in the main makefile... + +#O_TARGET := +O_OBJS := irobex.o +M_OBJS := irobex.o + +OX_OBJS += + +include $(TOPDIR)/Rules.make + +tar: + tar -cvf /dev/f1 . diff --git a/net/irda/irobex/irobex.c b/net/irda/irobex/irobex.c new file mode 100644 index 000000000000..0e8b596d3fbb --- /dev/null +++ b/net/irda/irobex/irobex.c @@ -0,0 +1,1110 @@ +/********************************************************************* + * + * Filename: irobex.c + * Version: 0.1 + * Description: Kernel side of the IrOBEX layer + * Status: Experimental. + * Author: Dag Brattli + * Created at: Thu Jun 25 21:21:07 1998 + * Modified at: Mon Dec 14 11:56:26 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +/* + * Master structure, only one instance for now!! + */ +struct irobex_cb *irobex; + +static int irobex_dev_open( struct inode * inode, struct file *file); +static int irobex_ioctl( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + +static int irobex_dev_close( struct inode *inode, struct file *file); +static ssize_t irobex_read( struct file *file, char *buffer, size_t count, + loff_t *noidea); +static ssize_t irobex_write( struct file *file, const char *buffer, + size_t count, loff_t *noidea); +static loff_t irobex_seek( struct file *, loff_t, int); +static u_int irobex_poll( struct file *file, poll_table *wait); +static int irobex_fasync( int, struct file *, int); + +static struct file_operations irobex_fops = { + irobex_seek, /* seek */ + irobex_read, + irobex_write, + NULL, /* readdir */ + irobex_poll, /* poll */ + irobex_ioctl, /* ioctl */ + NULL, /* mmap */ + irobex_dev_open, + NULL, + irobex_dev_close, + NULL, + irobex_fasync, +}; + +#ifdef CONFIG_PROC_FS +static int irobex_proc_read( char *buf, char **start, off_t offset, + int len, int unused); + +extern struct proc_dir_entry proc_irda; + +struct proc_dir_entry proc_irobex = { + 0, 6, "irobex", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, NULL, + &irobex_proc_read, +}; +#endif + +/* + * Function irobex_init (dev) + * + * Initializes the irobex control structure, and registers as a misc + * device + * + */ +__initfunc(int irobex_init(void)) +{ + struct irobex_cb *self; + + DEBUG( 4, "--> " __FUNCTION__ "()\n"); + + self = kmalloc(sizeof(struct irobex_cb), GFP_ATOMIC); + if ( self == NULL) + return -ENOMEM; + + memset( self, 0, sizeof(struct irobex_cb)); + sprintf( self->devname, "irobex%d", 1); /* Just one instance for now */ + + self->magic = IROBEX_MAGIC; + self->rx_flow = self->tx_flow = FLOW_START; + + self->dev.minor = MISC_DYNAMIC_MINOR; + self->dev.name = "irobex"; + self->dev.fops = &irobex_fops; + + skb_queue_head_init( &self->rx_queue); + init_timer( &self->watchdog_timer); + + irobex = self; + + misc_register( &self->dev); + + irobex_register_server( self); + +#ifdef CONFIG_PROC_FS + proc_register( &proc_irda, &proc_irobex); +#endif /* CONFIG_PROC_FS */ + + irlmp_register_layer( S_OBEX, CLIENT | SERVER, TRUE, + irobex_discovery_indication); + + DEBUG( 4, "irobex_init -->\n"); + + return 0; +} + +/* + * Function irobex_cleanup (void) + * + * Removes the IrOBEX layer + * + */ +void irobex_cleanup(void) +{ + struct sk_buff *skb; + struct irobex_cb *self; + + DEBUG( 4, "-->" __FUNCTION__ "()\n"); + + self = irobex; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IROBEX_MAGIC, return;); + + /* + * Deregister client and server + */ + irlmp_unregister_layer( S_OBEX, CLIENT | SERVER); + + if ( self->tsap) { + irttp_close_tsap( self->tsap); + self->tsap = NULL; + } + + /* Stop timers */ + del_timer( &self->watchdog_timer); + + /* + * Deallocate buffers + */ + while (( skb = skb_dequeue( &self->rx_queue)) != NULL) { + dev_kfree_skb( skb); + } + +#ifdef CONFIG_PROC_FS + proc_unregister( &proc_irda, proc_irobex.low_ino); +#endif + + misc_deregister( &self->dev); + + kfree( self); + + DEBUG( 4, __FUNCTION__ "() -->\n"); +} + +/* + * Function irobex_read (inode, file, buffer, count) + * + * User process wants to read some data + * + */ +static ssize_t irobex_read( struct file *file, char *buffer, size_t count, + loff_t *noidea) +{ + int len=0; + struct irobex_cb *self; + struct sk_buff *skb = NULL; + int ret; + + self = irobex; + + ASSERT( self != NULL, return -EIO;); + ASSERT( self->magic == IROBEX_MAGIC, return -EIO;); + + DEBUG( 4, __FUNCTION__ ": count=%d, skb_len=%d, conn.=%d, eof=%d\n", + count, skb_queue_len( &self->rx_queue), self->connected, + self->eof); + + /* + * Check if there is no data to return + */ + if ( skb_queue_len( &self->rx_queue) == 0) { + + /* + * Disconnected yet? + */ + if ( !self->connected) { + switch ( self->eof) { + case LM_USER_REQUEST: + self->eof = FALSE; + DEBUG(3, "read_irobex: returning 0\n"); + ret = 0; + break; + case LM_LAP_DISCONNECT: + self->eof = FALSE; + ret = -EIO; + break; + case LM_LAP_RESET: + self->eof = FALSE; + ret = -ECONNRESET; + break; + default: + self->eof = FALSE; + ret = -EIO; + break; + } + return ret; + } + + /* Return if user does not want to block */ + if ( file->f_flags & O_NONBLOCK) + return -EAGAIN; + + /* * Go to sleep and wait for data! */ + interruptible_sleep_on( &self->read_wait); + + /* + * Ensure proper reaction to signals, and screen out + * blocked signals (page 112. linux device drivers) + */ + if ( signal_pending( current)) + return -ERESTARTSYS; + } + + while ( count && skb_queue_len( &self->rx_queue)) { + + skb = skb_dequeue( &self->rx_queue); + + /* + * Check if we have previously stopped IrTTP and we know + * have more free space in our rx_queue. If so tell IrTTP + * to start delivering frames again before our rx_queue gets + * empty + */ + if ( self->rx_flow == FLOW_STOP) { + if ( skb_queue_len( &self->rx_queue) < LOW_THRESHOLD) { + DEBUG( 0, __FUNCTION__ "(), Starting IrTTP\n"); + self->rx_flow = FLOW_START; + irttp_flow_request( self->tsap, FLOW_START); + } + } + + /* + * Is the request from the user less that the amount in the + * current packet? + */ + if ( count < skb->len) { + copy_to_user( buffer+len, skb->data, count); + len += count; + + /* + * Remove copied data from skb and queue + * it for next read + */ + skb_pull( skb, count); + skb_queue_head( &self->rx_queue, skb); + + return len; + } else { + copy_to_user( buffer+len, skb->data, skb->len); + count -= skb->len; + len += skb->len; + + dev_kfree_skb( skb); + } + } + return len; +} + +/* + * Function irobex_write (inode, file, buffer, count) + * + * User process wants to write to device + * + */ +static ssize_t irobex_write( struct file *file, const char *buffer, + size_t count, loff_t *noidea) +{ + struct irobex_cb *self; + struct sk_buff *skb; + int data_len = 0; + int len = 0; + + self = irobex; + + ASSERT( self != NULL, return -EIO;); + ASSERT( self->magic == IROBEX_MAGIC, return -EIO;); + + DEBUG( 4, __FUNCTION__ ": count = %d\n", count); + + /* + * If we are not connected then we just give up! + */ + if ( !self->connected) { + DEBUG( 0, __FUNCTION__ "(): Not connected!\n"); + + return -ENOLINK; + } + + /* Check if IrTTP is wants us to slow down */ + if ( self->tx_flow == FLOW_STOP) { + DEBUG( 0, __FUNCTION__ + "(), IrTTP wants us to slow down, going to sleep\n"); + interruptible_sleep_on( &self->write_wait); + } + + /* Send data to TTP layer possibly as muliple packets */ + while ( count) { + + /* + * Check if request is larger than what fits inside a TTP + * frame + */ + if ( count < (self->irlap_data_size - IROBEX_MAX_HEADER)) + data_len = count; + else + data_len = self->irlap_data_size - IROBEX_MAX_HEADER; + + DEBUG( 4, __FUNCTION__ "(), data_len=%d, header_len = %d\n", + data_len, IROBEX_MAX_HEADER); + + skb = dev_alloc_skb( data_len + IROBEX_MAX_HEADER); + if ( skb == NULL) { + DEBUG( 0, "irobex - couldn't allocate skbuff!\n"); + return 0; + } + + skb_reserve( skb, IROBEX_MAX_HEADER); + skb_put( skb, data_len); + + copy_from_user( skb->data, buffer+len, data_len); + len += data_len; + count -= data_len; + + DEBUG( 4, __FUNCTION__ "(), skb->len=%d\n", (int) skb->len); + ASSERT( skb->len <= (self->irlap_data_size-IROBEX_MAX_HEADER), + return len;); + irttp_data_request( self->tsap, skb); + } + return (len); +} + +/* + * Function irobex_poll (file, wait) + * + * + * + */ +static u_int irobex_poll(struct file *file, poll_table *wait) +{ + DEBUG( 0, __FUNCTION__ "(), Sorry not implemented yet!\n"); + + /* check out /usr/src/pcmcia/modules/ds.c for an example */ + return 0; +} + +/* + * Function irobex_fasync (inode, filp, mode) + * + * Implementation for SIGIO + * + */ +static int irobex_fasync( int fd, struct file *filp, int on) +{ + struct irobex_cb *self; + + DEBUG( 4, __FUNCTION__ "()\n"); + + self = irobex; + + ASSERT( self != NULL, return -1;); + ASSERT( self->magic == IROBEX_MAGIC, return -1;); + + return fasync_helper( fd, filp, on, &self->async); +} + +/* + * Function irobex_seek (inode, file, buffer, count) + * + * Not implemented yet! + * + */ +static loff_t irobex_seek( struct file *file, loff_t off, int whence) +{ + DEBUG( 0, __FUNCTION__ "(), Not implemented yet!\n"); + + return -ESPIPE; +} + +/* + * Function irobex_ioctl (inode, filp, cmd, arg) + * + * Drivers IOCTL handler, used for connecting and disconnecting + * irobex connections + * + */ +static int irobex_ioctl( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + struct irobex_cb *self; + int err = 0; + int size = _IOC_SIZE(cmd); + + DEBUG( 0, __FUNCTION__ "()\n"); + + self = irobex; + + ASSERT( self != NULL, return -ENOTTY;); + ASSERT( self->magic = IROBEX_MAGIC, return -ENOTTY;); + + if ( _IOC_TYPE(cmd) != IROBEX_IOC_MAGIC) + return -EINVAL; + if ( _IOC_NR(cmd) > IROBEX_IOC_MAXNR) + return -EINVAL; + + if ( _IOC_DIR(cmd) & _IOC_READ) + err = verify_area( VERIFY_WRITE, (void *) arg, size); + else if ( _IOC_DIR(cmd) & _IOC_WRITE) + err = verify_area( VERIFY_READ, (void *) arg, size); + if ( err) + return err; + + switch ( cmd) { + case IROBEX_IOCSCONNECT: + DEBUG( 0, __FUNCTION__ "(): IROBEX_IOCSCONNECT!\n"); + + /* Already connected? */ + if ( self->connected) + return 0; + + /* + * Wait until we have discovered a remote IrOBEX device + */ + if (( self->daddr == 0) || + (( jiffies - self->time_discovered) > 500)) { + + if ( self->daddr != 0) { + DEBUG( 0, __FUNCTION__ "(), daddr is old!\n"); + self->daddr = 0; + } + + irlmp_discovery_request( 8); + DEBUG( 0, __FUNCTION__ + "(): Sleep until device discovered\n"); + + /* Timeout after 10 secs. */ + irobex_start_watchdog_timer( self, 1000); + /* + * Wait for discovery to complete + */ + interruptible_sleep_on( &self->discover_wait); + /* del_timer( &self->watchdog_timer); */ + } + + /* Give up if we are unable to discover any remote devices */ + if ( self->daddr == 0) { + DEBUG( 0, __FUNCTION__ + "(), Unable to discover any devices!\n"); + return -ENOTTY; + } + + /* Need to find remote destination TSAP selector? */ + if ( self->dtsap_sel == 0) { + + DEBUG( 0, __FUNCTION__ "() : Quering remote IAS!\n"); + + /* Timeout after 5 secs. */ + irobex_start_watchdog_timer( self, 500); + iriap_getvaluebyclass_request( self->daddr, + "OBEX", + "IrDA:TinyTP:LsapSel", + irobex_get_value_confirm, + self); + + DEBUG( 0, __FUNCTION__ "(): Sleep until IAS answer\n"); + interruptible_sleep_on( &self->ias_wait); + /* del_timer( &self->watchdog_timer); */ + } + + if ( self->dtsap_sel == 0) { + DEBUG( 0, __FUNCTION__ + "(), Unable to query remote LM-IAS!\n"); + return -ENOTTY; + } + + + /* + * Try connect + */ + DEBUG( 0, __FUNCTION__ "(): Connecting ...\n"); + + /* Timeout after 5 secs. */ + irobex_start_watchdog_timer( self, 500); + + irttp_connect_request( self->tsap, self->dtsap_sel, + self->daddr, NULL, SAR_DISABLE, + NULL); + + /* + * Go to sleep and wait for connection! + */ + DEBUG( 0, __FUNCTION__ "(): Waiting for connection!\n"); + interruptible_sleep_on( &self->connect_wait); + + del_timer( &self->watchdog_timer); + + if ( !self->connected) { + DEBUG( 0, __FUNCTION__ + "(), Unable to connect to remote device!\n"); + return -ENOTTY; + } + + break; + case IROBEX_IOCSDISCONNECT: + DEBUG( 0, __FUNCTION__ "(): IROBEX_IOCSDISCONNECT!\n"); + if ( !self->connected) + return 0; + + irttp_disconnect_request( self->tsap, NULL, P_NORMAL); + + /* Reset values for this instance */ + self->connected = FALSE; + self->eof = 0; + self->daddr = 0; + self->dtsap_sel = 0; + self->rx_flow = FLOW_START; + self->tx_flow = FLOW_START; + + wake_up_interruptible( &self->read_wait); + break; + default: + return -EINVAL; + } + return 0; +} + +/* + * Function irobex_dev_open (inode, file) + * + * + * + */ +static int irobex_dev_open( struct inode * inode, struct file *file) +{ + struct irobex_cb *self; + + DEBUG( 4, "open_irobex:\n"); + + self = irobex; + + ASSERT( self != NULL, return -1;); + ASSERT( self->magic == IROBEX_MAGIC, return -1;); + + if ( self->count++) { + DEBUG( 3, "open_irobex: count not zero; actual = %d\n", + self->count); + self->count--; + return -EBUSY; + } + + MOD_INC_USE_COUNT; + + return 0; +} + +static int irobex_dev_close( struct inode *inode, struct file *file) +{ + struct irobex_cb *self; + struct sk_buff *skb; + + DEBUG( 4, "close_irobex()\n"); + + self = irobex; + + ASSERT( self != NULL, return -ENODEV;); + ASSERT( self->magic == IROBEX_MAGIC, return -EBADR;); + + /* Deallocate buffers */ + while (( skb = skb_dequeue( &self->rx_queue)) != NULL) { + DEBUG( 3, "irobex_close: freeing SKB\n"); + dev_kfree_skb( skb); + } + + /* if ( self->tsap) { */ +/* irttp_close_tsap( self->tsap); */ +/* self->tsap = NULL; */ +/* self->connected = FALSE; */ +/* } */ + + /* Remove this filp from the asynchronously notified filp's */ + irobex_fasync( -1, file, 0); + + self->count--; + + MOD_DEC_USE_COUNT; + + return 0; +} + +/* + * Function irobex_discovery_inication (daddr) + * + * Remote device discovered, try query the remote IAS to see which + * device it is, and which services it has. + * + */ +void irobex_discovery_indication( DISCOVERY *discovery) +{ + struct irobex_cb *self; + + DEBUG( 4, __FUNCTION__ "()\n"); + + self = irobex; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IROBEX_MAGIC, return;); + + self->daddr = discovery->daddr; + self->time_discovered = jiffies; + + wake_up_interruptible( &self->discover_wait); +} + +/* + * Function irobex_disconnect_indication (handle, reason, priv) + * + * + * + */ +void irobex_disconnect_indication( void *instance, void *sap, + LM_REASON reason, struct sk_buff *userdata) +{ + struct irobex_cb *self; + + DEBUG( 0, __FUNCTION__ "(), reason=%d\n", reason); + + self = ( struct irobex_cb *) instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IROBEX_MAGIC, return;); + +/* save_flags(flags); */ +/* cli(); */ + + self->connected = FALSE; + self->eof = reason; + self->daddr = 0; + self->dtsap_sel = 0; + self->rx_flow = self->tx_flow = FLOW_START; + +/* restore_flags(flags); */ + + wake_up_interruptible( &self->read_wait); + wake_up_interruptible( &self->connect_wait); + wake_up_interruptible( &self->write_wait); + + DEBUG( 4, "irobex_disconnect_indication: skb_queue_len=%d\n", + skb_queue_len( &irobex->rx_queue)); + + if ( userdata) { + dev_kfree_skb( userdata); + + } +} + +/* + * Function irobex_connect_confirm (instance, sap, qos, userdata) + * + * Connection to peer IrOBEX layer established + * + */ +void irobex_connect_confirm( void *instance, void *sap, struct qos_info *qos, + int max_sdu_size, struct sk_buff *userdata) +{ + struct irobex_cb *self; + + DEBUG( 0, __FUNCTION__ "()\n"); + + self = ( struct irobex_cb *) instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IROBEX_MAGIC, return;); + ASSERT( qos != NULL, return;); + + DEBUG( 0, __FUNCTION__ "(), IrLAP data size=%d\n", + qos->data_size.value); + + self->irlap_data_size = qos->data_size.value; + self->connected = TRUE; + + /* + * Wake up any blocked process wanting to write. Finally this process + * can start writing since the connection is now open :-) + */ + wake_up_interruptible( &self->connect_wait); + + if ( userdata) { + dev_kfree_skb( userdata); + + } +} + +/* + * Function irobex_connect_response (handle) + * + * Accept incomming connection + * + */ +void irobex_connect_response( struct irobex_cb *self) +{ + struct sk_buff *skb; +/* __u8 *frame; */ + + DEBUG( 4, "irobex_connect_response()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IROBEX_MAGIC, return;); + + self->connected = TRUE; + + skb = dev_alloc_skb( 64); + if (skb == NULL) { + DEBUG( 0,"irobex_connect_response: " + "Could not allocate an sk_buff of length %d\n", + 64); + return; + } + + /* Reserve space for MUX_CONTROL and LAP header */ + skb_reserve( skb, TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER); + + irttp_connect_response( self->tsap, SAR_DISABLE, skb); +} + +/* + * Function irobex_connect_indication (handle, skb, priv) + * + * Connection request from a remote device + * + */ +void irobex_connect_indication( void *instance, void *sap, + struct qos_info *qos, int max_sdu_size, + struct sk_buff *userdata) +{ + struct irmanager_event mgr_event; + struct irobex_cb *self; + + DEBUG( 0, "irobex_connect_indication()\n"); + + self = ( struct irobex_cb *) instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IROBEX_MAGIC, return;); + ASSERT( userdata != NULL, return;); + + self->eof = FALSE; + + DEBUG( 0, "irobex_connect_indication, skb_len = %d\n", + (int) userdata->len); + + DEBUG( 0, __FUNCTION__ "(), IrLAP data size=%d\n", + qos->data_size.value); + + ASSERT( qos->data_size.value >= 64, return;); + + self->irlap_data_size = qos->data_size.value; + + irobex_connect_response( self); + + mgr_event.event = EVENT_IROBEX_START; + sprintf( mgr_event.devname, "%s", self->devname); + irmanager_notify( &mgr_event); + + wake_up_interruptible( &self->read_wait); + + if ( userdata) { + dev_kfree_skb( userdata); + } +} + +/* + * Function irobex_data_indication (instance, sap, skb) + * + * This function gets the data that is received on the data channel + * + */ +void irobex_data_indication( void *instance, void *sap, struct sk_buff *skb) +{ + + struct irobex_cb *self; + + self = ( struct irobex_cb *) instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IROBEX_MAGIC, return;); + ASSERT( skb != NULL, return;); + + DEBUG( 4, __FUNCTION__ "(), len=%d\n", (int) skb->len); + + skb_queue_tail( &self->rx_queue, skb); + + /* + * Check if queues are beginning to get filled, and inform + * IrTTP to slow down if that is the case + */ + if ( skb_queue_len( &self->rx_queue) > HIGH_THRESHOLD) { + DEBUG( 0, __FUNCTION__ + "(), rx_queue is full, telling IrTTP to slow down\n"); + self->rx_flow = FLOW_STOP; + irttp_flow_request( self->tsap, FLOW_STOP); + } + + /* + * Wake up process blocked on read or select + */ + wake_up_interruptible( &self->read_wait); + + /* Send signal to asynchronous readers */ + if ( self->async) + kill_fasync( self->async, SIGIO); +} + +/* + * Function irobex_flow_indication (instance, sap, cmd) + * + * + * + */ +void irobex_flow_indication( void *instance, void *sap, LOCAL_FLOW flow) +{ + struct irobex_cb *self; + + DEBUG( 0, __FUNCTION__ "()\n"); + + self = ( struct irobex_cb *) instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IROBEX_MAGIC, return;); + + switch ( flow) { + case FLOW_STOP: + DEBUG( 0, __FUNCTION__ "(), IrTTP wants us to slow down\n"); + self->tx_flow = flow; + break; + case FLOW_START: + self->tx_flow = flow; + DEBUG( 0, __FUNCTION__ "(), IrTTP wants us to start again\n"); + wake_up_interruptible( &self->discover_wait); + break; + default: + DEBUG( 0, __FUNCTION__ "(), Unknown flow command!\n"); + } +} + +/* + * Function irobex_get_value_confirm (obj_id, value) + * + * Got results from previous GetValueByClass request + * + */ +void irobex_get_value_confirm( __u16 obj_id, struct ias_value *value, + void *priv) +{ + struct irobex_cb *self; + + DEBUG( 4, "irobex_get_value_confirm()\n"); + + ASSERT( priv != NULL, return;); + self = ( struct irobex_cb *) priv; + + if ( !self || self->magic != IROBEX_MAGIC) { + DEBUG( 0, "irobex_get_value_confirm: bad magic!\n"); + return; + } + + switch ( value->type) { + case IAS_INTEGER: + DEBUG( 0, "irobex_get_value_confirm() int=%d\n", + value->t.integer); + + if ( value->t.integer != -1) { + self->dtsap_sel = value->t.integer; + + /* + * Got the remote TSAP, so wake up any processes + * blocking on write. We don't do the connect + * ourselves since we must make sure there is a + * process that wants to make a connection, so we + * just let that process do the connect itself + */ + wake_up_interruptible( &self->ias_wait); + } else + self->dtsap_sel = 0; + break; + case IAS_STRING: + DEBUG( 0, "irlan_get_value_confirm(), got string %s\n", + value->t.string); + break; + case IAS_OCT_SEQ: + DEBUG( 0, "irobex_get_value_confirm(), " + "OCT_SEQ not implemented\n"); + break; + case IAS_MISSING: + DEBUG( 0, "irobex_get_value_confirm(), " + "MISSING not implemented\n"); + break; + default: + DEBUG( 0, "irobex_get_value_confirm(), unknown type!\n"); + break; + } +} + +/* + * Function irobex_provider_confirm (dlsap) + * + * IrOBEX provider is discovered. We can now establish connections + * TODO: This function is currently not used! + */ +void irobex_provider_confirm( struct irobex_cb *self, __u8 dlsap) +{ + /* struct irobex_cb *self = irobex; */ + struct notify_t notify; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IROBEX_MAGIC, return;); + + notify.data_indication = irobex_data_indication; + notify.connect_confirm = irobex_connect_confirm; + notify.connect_indication = irobex_connect_indication; + notify.flow_indication = irobex_flow_indication; + notify.disconnect_indication = irobex_disconnect_indication; + notify.instance = self; + + /* Create TSAP's */ + self->tsap = irttp_open_tsap( LSAP_ANY, DEFAULT_INITIAL_CREDIT, + ¬ify); + +/* DEBUG( 0, "OBEX allocated TSAP%d for data\n", self->handle); */ + + /* irlan_do_event( IAS_PROVIDER_AVAIL, NULL, &frame); */ +} + +/* + * Function irobex_register_server(void) + * + * Register server support so we can accept incomming connections. We + * must register both a TSAP for control and data + * + */ +void irobex_register_server( struct irobex_cb *self) +{ + struct notify_t notify; + struct ias_object *obj; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IROBEX_MAGIC, return;); + + irda_notify_init( ¬ify); + + notify.connect_confirm = irobex_connect_confirm; + notify.connect_indication = irobex_connect_indication; + notify.disconnect_indication = irobex_disconnect_indication; + notify.data_indication = irobex_data_indication; + notify.flow_indication = irobex_flow_indication; + notify.instance = self; + strcpy( notify.name, "IrOBEX"); + + self->tsap = irttp_open_tsap( TSAP_IROBEX, DEFAULT_INITIAL_CREDIT, + ¬ify); + if ( self->tsap == NULL) { + DEBUG( 0, "irobex_register_server(), " + "Unable to allocate TSAP!\n"); + return; + } + + /* + * Register with LM-IAS + */ + obj = irias_new_object( "OBEX", 0x42343); + irias_add_integer_attrib( obj, "IrDA:TinyTP:LsapSel", TSAP_IROBEX); + irias_insert_object( obj); + +} + +void irobex_watchdog_timer_expired( unsigned long data) +{ + struct irobex_cb *self = ( struct irobex_cb *) data; + + DEBUG( 0, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IROBEX_MAGIC, return;); + + wake_up_interruptible( &self->discover_wait); + wake_up_interruptible( &self->ias_wait); + wake_up_interruptible( &self->connect_wait); + + /* irlmp_do_lsap_event( self, LM_WATCHDOG_TIMEOUT, NULL); */ +} + +#ifdef CONFIG_PROC_FS +/* + * Function irobex_proc_read (buf, start, offset, len, unused) + * + * Give some info to the /proc file system + */ +static int irobex_proc_read( char *buf, char **start, off_t offset, + int len, int unused) +{ + struct irobex_cb *self; + + self = irobex; + + ASSERT( self != NULL, return -1;); + ASSERT( self->magic == IROBEX_MAGIC, return -1;); + + len = 0; + + len += sprintf( buf+len, "ifname: %s ",self->devname); + len += sprintf( buf+len, "connected: %s ", + self->connected ? "TRUE": "FALSE"); + len += sprintf( buf+len, "EOF: %s\n", self->eof ? "TRUE": "FALSE"); + + return len; +} + +#endif /* CONFIG_PROC_FS */ + +#ifdef MODULE + +MODULE_AUTHOR("Dag Brattli "); +MODULE_DESCRIPTION("The Linux IrOBEX module"); + +/* + * Function init_module (void) + * + * Initialize the IrOBEX module, this function is called by the + * modprobe(1) program. + */ +int init_module(void) +{ + DEBUG( 4, "--> irobex: init_module\n"); + + irobex_init(); + + DEBUG( 4, "irobex: init_module -->\n"); + + return 0; +} + +/* + * Function cleanup_module (void) + * + * Remove the IrOBEX module, this function is called by the rmmod(1) + * program + */ +void cleanup_module(void) +{ + DEBUG( 4, "--> irobex, cleanup_module\n"); + /* + * No need to check MOD_IN_USE, as sys_delete_module() checks. + */ + + /* Free some memory */ + irobex_cleanup(); + + DEBUG( 4, "irobex, cleanup_module -->\n"); +} + +#endif /* MODULE */ + + + + diff --git a/net/irda/irproc.c b/net/irda/irproc.c new file mode 100644 index 000000000000..6f9e5ecf9c09 --- /dev/null +++ b/net/irda/irproc.c @@ -0,0 +1,386 @@ +/********************************************************************* + * + * Filename: irproc.c + * Version: + * Description: Various entries in the /proc file system + * Status: Experimental. + * Author: Thomas Davis, + * Created at: Sat Feb 21 21:33:24 1998 + * Modified at: Wed Dec 9 02:26:45 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998, Thomas Davis, , + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * I, Thomas Davis, provide no warranty for any of this software. + * This material is provided "AS-IS" and at no charge. + * + * Portions lifted from the linux/fs/procfs/ files. + * + ********************************************************************/ + +#include +#include + +#include +#include +#include + +static int proc_irda_21x_lookup(struct inode * dir, struct dentry *dentry); + +static int proc_irda_readdir(struct file *filp, void *dirent, + filldir_t filldir); + +extern int irda_device_proc_read( char *buf, char **start, off_t offset, + int len, int unused); +extern int irlap_proc_read( char *buf, char **start, off_t offset, int len, + int unused); +extern int irlmp_proc_read( char *buf, char **start, off_t offset, int len, + int unused); +extern int irttp_proc_read( char *buf, char **start, off_t offset, int len, + int unused); +extern int irias_proc_read( char *buf, char **start, off_t offset, int len, + int unused); + +static int proc_discovery_read( char *buf, char **start, off_t offset, int len, + int unused); + +/* int proc_irda_readdir(struct inode *inode, struct file *filp, void *dirent, */ +/* filldir_t filldir); */ + +enum irda_directory_inos { + PROC_IRDA_LAP = 1, + PROC_IRDA_LMP, + PROC_IRDA_TTP, + PROC_IRDA_LPT, + PROC_IRDA_COMM, + PROC_IRDA_IRDA_DEVICE, + PROC_IRDA_IRIAS +}; + +static struct file_operations proc_irda_dir_operations = { + NULL, /* lseek - default */ + NULL, /* read - bad */ + NULL, /* write - bad */ + proc_irda_readdir, /* readdir */ + NULL, /* select - default */ + NULL, /* ioctl - default */ + NULL, /* mmap */ + NULL, /* no special open code */ + NULL, /* no special release code */ + NULL /* can't fsync */ +}; + +/* + * proc directories can do almost nothing.. + */ +struct inode_operations proc_irda_dir_inode_operations = { + &proc_irda_dir_operations, /* default net directory file-ops */ + NULL, /* create */ + proc_irda_21x_lookup, + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + NULL, /* readlink */ + NULL, /* follow_link */ + NULL, /* readpage */ + NULL, /* writepage */ + NULL, /* bmap */ + NULL, /* truncate */ + NULL /* permission */ +}; + +struct proc_dir_entry proc_irda = { + 0, 4, "irda", + S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0, + 0, &proc_irda_dir_inode_operations, + NULL, NULL, + NULL, + NULL, NULL +}; + +#if 0 +struct proc_dir_entry proc_lpt = { + 0, 3, "lpt", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, NULL /* ops -- default to array */, + &irlpt_proc_read /* get_info */, +}; +#endif + +struct proc_dir_entry proc_discovery = { + 0, 9, "discovery", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, NULL /* ops -- default to array */, + &proc_discovery_read /* get_info */, +}; + +struct proc_dir_entry proc_irda_device = { + 0, 11, "irda_device", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, NULL, + &irda_device_proc_read, +}; + +struct proc_dir_entry proc_ttp = { + 0, 5, "irttp", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, NULL /* ops -- default to array */, + &irttp_proc_read /* get_info */, +}; + +struct proc_dir_entry proc_lmp = { + 0, 5, "irlmp", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, NULL /* ops -- default to array */, + &irlmp_proc_read /* get_info */, +}; + +struct proc_dir_entry proc_lap = { + 0, 5, "irlap", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, NULL /* ops -- default to array */, + &irlap_proc_read /* get_info */, +}; + +struct proc_dir_entry proc_ias = { + 0, 5, "irias", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, NULL /* ops -- default to array */, + &irias_proc_read /* get_info */, +}; + +/* + * Function proc_delete_dentry (dentry) + * + * Copy of proc/root.c because this function is invisible to the irda + * module + * + */ +static void proc_delete_dentry(struct dentry * dentry) +{ + d_drop(dentry); +} + +static struct dentry_operations proc_dentry_operations = +{ + NULL, /* revalidate */ + NULL, /* d_hash */ + NULL, /* d_compare */ + proc_delete_dentry /* d_delete(struct dentry *) */ +}; + +/* + * Function irda_proc_register (void) + * + * Register irda entry in /proc file system + * + */ +void irda_proc_register(void) { + proc_net_register( &proc_irda); + proc_register( &proc_irda, &proc_lap); + proc_register( &proc_irda, &proc_lmp); + proc_register( &proc_irda, &proc_ttp); + proc_register( &proc_irda, &proc_ias); + proc_register( &proc_irda, &proc_irda_device); + proc_register( &proc_irda, &proc_discovery); +} + +/* + * Function irda_proc_unregister (void) + * + * Unregister irda entry in /proc file system + * + */ +void irda_proc_unregister(void) { + proc_unregister( &proc_irda, proc_discovery.low_ino); + proc_unregister(&proc_irda, proc_irda_device.low_ino); + proc_unregister( &proc_irda, proc_ias.low_ino); + proc_unregister( &proc_irda, proc_ttp.low_ino); + proc_unregister( &proc_irda, proc_lmp.low_ino); + proc_unregister( &proc_irda, proc_lap.low_ino); + proc_unregister( proc_net, proc_irda.low_ino); +} + +/* + * Function proc_irda_21x_lookup (dir, dentry) + * + * This is a copy of proc_lookup from the linux-2.1.x + * + */ +int proc_irda_21x_lookup(struct inode * dir, struct dentry *dentry) +{ + struct inode *inode; + struct proc_dir_entry * de; + int error; + + error = -ENOTDIR; + if (!dir || !S_ISDIR(dir->i_mode)) + goto out; + + error = -ENOENT; + inode = NULL; + de = (struct proc_dir_entry *) dir->u.generic_ip; + if (de) { + for (de = de->subdir; de ; de = de->next) { + if (!de || !de->low_ino) + continue; + if (de->namelen != dentry->d_name.len) + continue; + if (!memcmp(dentry->d_name.name, de->name, de->namelen)) { + int ino = de->low_ino | (dir->i_ino & ~(0xffff)); + error = -EINVAL; + inode = proc_get_inode(dir->i_sb, ino, de); + break; + } + } + } + + if (inode) { + dentry->d_op = &proc_dentry_operations; + d_add(dentry, inode); + error = 0; + } +out: + return error; +} + +/* + * Function proc_irda_readdir (filp, dirent, filldir) + * + * This is a copy from linux/fs/proc because the function is invisible + * to the irda module + * + */ +static int proc_irda_readdir( struct file *filp, void *dirent, + filldir_t filldir) +{ + struct proc_dir_entry * de; + unsigned int ino; + int i; + + struct inode *inode = filp->f_dentry->d_inode; + if (!inode || !S_ISDIR(inode->i_mode)) + return -ENOTDIR; + ino = inode->i_ino; + de = (struct proc_dir_entry *) inode->u.generic_ip; + if (!de) + return -EINVAL; + i = filp->f_pos; + switch (i) { + case 0: + if (filldir(dirent, ".", 1, i, ino) < 0) + return 0; + i++; + filp->f_pos++; + /* fall through */ + case 1: + if (filldir(dirent, "..", 2, i, de->parent->low_ino) < 0) + return 0; + i++; + filp->f_pos++; + /* fall through */ + default: + ino &= ~0xffff; + de = de->subdir; + i -= 2; + for (;;) { + if (!de) + return 1; + if (!i) + break; + de = de->next; + i--; + } + + do { + if (filldir(dirent, de->name, de->namelen, filp->f_pos, + ino | de->low_ino) < 0) + return 0; + filp->f_pos++; + de = de->next; + } while (de); + } + return 1; +} + +/* + * Function proc_discovery_read (buf, start, offset, len, unused) + * + * Print discovery information in /proc file system + * + */ +int proc_discovery_read( char *buf, char **start, off_t offset, int len, + int unused) +{ + DISCOVERY *discovery; + struct lap_cb *lap; + unsigned long flags; + + if ( !irlmp) + return len; + + len = sprintf(buf, "IrLMP: Discovery log:\n\n"); + + + save_flags(flags); + cli(); + + lap = ( struct lap_cb *) hashbin_get_first( irlmp->links); + while( lap != NULL) { + ASSERT( lap->magic == LMP_LAP_MAGIC, return 0;); + + len += sprintf( buf+len, "Link saddr=0x%08x\n", lap->saddr); + discovery = ( DISCOVERY *) hashbin_get_first( lap->cachelog); + while ( discovery != NULL) { + len += sprintf( buf+len, " name: %s,", + discovery->info); + + len += sprintf( buf+len, " hint: "); + if ( discovery->hint[0] & HINT_PNP) + len += sprintf( buf+len, "PnP Compatible "); + if ( discovery->hint[0] & HINT_PDA) + len += sprintf( buf+len, "PDA/Palmtop "); + if ( discovery->hint[0] & HINT_COMPUTER) + len += sprintf( buf+len, "Computer "); + if ( discovery->hint[0] & HINT_PRINTER) + len += sprintf( buf+len, "Printer "); + if ( discovery->hint[0] & HINT_MODEM) + len += sprintf( buf+len, "Modem "); + if ( discovery->hint[0] & HINT_FAX) + len += sprintf( buf+len, "Fax "); + if ( discovery->hint[0] & HINT_LAN) + len += sprintf( buf+len, "LAN Access"); + + if ( discovery->hint[1] & HINT_TELEPHONY) + len += sprintf( buf+len, "Telephony "); + if ( discovery->hint[1] & HINT_FILE_SERVER) + len += sprintf( buf+len, "File Server "); + if ( discovery->hint[1] & HINT_COMM) + len += sprintf( buf+len, "IrCOMM "); + if ( discovery->hint[1] & HINT_OBEX) + len += sprintf( buf+len, "IrOBEX "); + + len += sprintf( buf+len, ", daddr: 0x%08x\n", + discovery->daddr); + + len += sprintf( buf+len, "\n"); + + discovery = ( DISCOVERY *) hashbin_get_next( lap->cachelog); + } + lap = ( struct lap_cb *) hashbin_get_next( irlmp->links); + } + restore_flags(flags); + + return len; +} + diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c new file mode 100644 index 000000000000..7d9f1c161a82 --- /dev/null +++ b/net/irda/irqueue.c @@ -0,0 +1,770 @@ +/********************************************************************* + * + * Filename: irqueue.c + * Version: 0.3 + * Description: General queue implementation + * Status: Experimental. + * Author: Dag Brattli + * Created at: Tue Jun 9 13:29:31 1998 + * Modified at: Mon Dec 14 20:11:07 1998 + * Modified by: Dag Brattli + * + * Copyright (C) 1998, Aage Kvalnes + * Copyright (C) 1998, Dag Brattli, + * All Rights Reserved. + * + * This code is taken from the Vortex Operating System written by Aage + * Kvalnes. Aage has agreed that this code can use the GPL licence, + * although he does not use that licence in his own code. + * + * This copyright does however _not_ include the ELF hash() function + * which I currently don't know which licence or copyright it + * has. Please inform me if you know. + * + * 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. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include +#include + +static QUEUE *dequeue_general( QUEUE **queue, QUEUE* element); +static __u32 hash( char* name); + +/* + * Function hashbin_create ( type, name ) + * + * Create hashbin! + * + */ +hashbin_t *hashbin_new( int type) +{ + hashbin_t* hashbin; + + DEBUG( 4, "hashbin_create()\n"); + + /* + * Allocate new hashbin + */ + hashbin = kmalloc( sizeof(hashbin_t), GFP_ATOMIC); + + /* + * Initialize structure + */ + memset( hashbin, 0, sizeof(hashbin_t)); + hashbin->hb_type = type; + hashbin->magic = HB_MAGIC; + + return hashbin; +} + +/* + * Function hashbin_clear (hashbin, free_func) + * + * Remove all entries from the hashbin, see also the comments in + * hashbin_delete() below + */ +int hashbin_clear( hashbin_t* hashbin, FREE_FUNC free_func) +{ + QUEUE* queue; + int i; + + ASSERT( hashbin != NULL, return -1;); + ASSERT( hashbin->magic == HB_MAGIC, return -1;); + + /* + * Free the entries in the hashbin + */ + for ( i = 0; i < HASHBIN_SIZE; i ++ ) { + queue = dequeue_first( (QUEUE**) &hashbin->hb_queue[ i]); + while( queue ) { + if ( free_func) + (*free_func)( queue ); + queue = dequeue_first( + (QUEUE**) &hashbin->hb_queue[ i]); + } + } + hashbin->hb_size = 0; + + return 0; +} + + +/* + * Function hashbin_delete (hashbin, free_func) + * + * Destroy hashbin, the free_func can be a user supplied special routine + * for deallocating this structure if it's complex. If not the user can + * just supply kfree, which should take care of the job. + */ +int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func) +{ + int i; + QUEUE* queue; + + DEBUG( 4, "hashbin_destroy()\n"); + + /* + * Free the entries in the hashbin, TODO: use hashbin_clear when + * it has been shown to work + */ + for ( i = 0; i < HASHBIN_SIZE; i ++ ) { + queue = dequeue_first( (QUEUE**) &hashbin->hb_queue[ i ] ); + while( queue ) { + if ( free_func) + (*free_func)( queue ); + queue = dequeue_first( + (QUEUE**) &hashbin->hb_queue[ i ]); + } + } + + /* + * Free the hashbin structure + */ + hashbin->magic = ~HB_MAGIC; + kfree( hashbin ); + + return 0; +} + +/* + * Function hashbin_lock (hashbin, hashv, name) + * + * Lock the hashbin + * + */ +void hashbin_lock( hashbin_t* hashbin, __u32 hashv, char* name, + unsigned long flags) +{ + int bin; + + DEBUG( 0, "hashbin_lock\n"); + + ASSERT( hashbin != NULL, return;); + ASSERT( hashbin->magic == HB_MAGIC, return;); + + /* + * Locate hashbin + */ + if ( name ) + hashv = hash( name ); + bin = GET_HASHBIN( hashv); + + /* Synchronize */ + if ( hashbin->hb_type & HB_GLOBAL ) { + + spin_lock_irqsave( &hashbin->hb_mutex[ bin], flags); + } else { + save_flags( flags); + cli(); + } +} + +/* + * Function hashbin_unlock (hashbin, hashv, name) + * + * Unlock the hashbin + * + */ +void hashbin_unlock( hashbin_t* hashbin, __u32 hashv, char* name, + unsigned long flags) +{ + int bin; + + DEBUG( 0, "hashbin_unlock()\n"); + + ASSERT( hashbin != NULL, return;); + ASSERT( hashbin->magic == HB_MAGIC, return;); + + /* + * Locate hashbin + */ + if ( name ) + hashv = hash( name ); + bin = GET_HASHBIN( hashv ); + + /* Release lock */ + if ( hashbin->hb_type & HB_GLOBAL) { + spin_unlock_irq( &hashbin->hb_mutex[ bin]); + } else if ( hashbin->hb_type & HB_LOCAL) { + restore_flags( flags); + } +} + +/* + * Function hashbin_insert (hashbin, entry, name) + * + * Insert an entry into the hashbin + * + */ +void hashbin_insert( hashbin_t* hashbin, QUEUE* entry, __u32 hashv, + char* name) +{ + unsigned long flags = 0; + int bin; + + DEBUG( 4, "hashbin_insert()\n"); + + ASSERT( hashbin != NULL, return;); + ASSERT( hashbin->magic == HB_MAGIC, return;); + + /* + * Locate hashbin + */ + if ( name ) + hashv = hash( name ); + bin = GET_HASHBIN( hashv ); + + /* Synchronize */ + if ( hashbin->hb_type & HB_GLOBAL ) { + spin_lock_irqsave( &hashbin->hb_mutex[ bin ], flags); + + } else if ( hashbin->hb_type & HB_LOCAL ) { + save_flags(flags); + cli(); + } /* Default is no-lock */ + + /* + * Store name and key + */ + entry->q_hash = hashv; + if ( name ) + strncpy( entry->q_name, name, 32); + + /* + * Insert new entry first + * TODO: Perhaps allow sorted lists? + * -> Merge sort if a sorted list should be created + */ + if ( hashbin->hb_type & HB_SORTED) { + } else { + enqueue_first( (QUEUE**) &hashbin->hb_queue[ bin ], + entry); + } + hashbin->hb_size++; + + /* Release lock */ + if ( hashbin->hb_type & HB_GLOBAL) { + + spin_unlock_irq( &hashbin->hb_mutex[ bin]); + + } else if ( hashbin->hb_type & HB_LOCAL) { + restore_flags( flags); + } +} + +/* + * Function hashbin_find (hashbin, hashv, name) + * + * Find item with the given hashv or name + * + */ +void* hashbin_find( hashbin_t* hashbin, __u32 hashv, char* name ) +{ + int bin, found = FALSE; + unsigned long flags = 0; + QUEUE* entry; + + DEBUG( 4, "hashbin_find()\n"); + + ASSERT( hashbin != NULL, return NULL;); + ASSERT( hashbin->magic == HB_MAGIC, return NULL;); + + /* + * Locate hashbin + */ + if ( name ) + hashv = hash( name ); + bin = GET_HASHBIN( hashv ); + + /* Synchronize */ + if ( hashbin->hb_type & HB_GLOBAL ) { + spin_lock_irqsave( &hashbin->hb_mutex[ bin ], flags); + + } else if ( hashbin->hb_type & HB_LOCAL ) { + save_flags(flags); + cli(); + } /* Default is no-lock */ + + /* + * Search for entry + */ + entry = hashbin->hb_queue[ bin]; + if ( entry ) { + do { + /* + * Check for key + */ + if ( entry->q_hash == hashv ) { + /* + * Name compare too? + */ + if ( name ) { + if ( strcmp( entry->q_name, name ) == 0 ) { + found = TRUE; + break; + } + } else { + found = TRUE; + break; + } + } + entry = entry->q_next; + } while ( entry != hashbin->hb_queue[ bin ] ); + } + + /* Release lock */ + if ( hashbin->hb_type & HB_GLOBAL) { + spin_unlock_irq( &hashbin->hb_mutex[ bin]); + + } else if ( hashbin->hb_type & HB_LOCAL) { + restore_flags( flags); + } + + if ( found ) + return entry; + else + return NULL; +} + +void *hashbin_remove_first( hashbin_t *hashbin) +{ + unsigned long flags; + QUEUE *entry = NULL; + + save_flags(flags); + cli(); + + entry = hashbin_get_first( hashbin); + if ( entry != NULL) + hashbin_remove( hashbin, entry->q_hash, NULL); + + restore_flags( flags); + + return entry; +} + + +/* + * Function hashbin_remove (hashbin, name) + * + * Remove entry with the given name + * + */ +void* hashbin_remove( hashbin_t* hashbin, __u32 hashv, char* name) +{ + int bin, found = FALSE; + unsigned long flags = 0; + QUEUE* entry; + + DEBUG( 4, "hashbin_remove()\n"); + + ASSERT( hashbin != NULL, return NULL;); + ASSERT( hashbin->magic == HB_MAGIC, return NULL;); + + /* + * Locate hashbin + */ + if ( name ) + hashv = hash( name ); + bin = GET_HASHBIN( hashv ); + + if ( hashbin->hb_type & HB_GLOBAL ) { + spin_lock_irqsave( &hashbin->hb_mutex[ bin ], flags); + + } else if ( hashbin->hb_type & HB_LOCAL ) { + save_flags(flags); + cli(); + } /* Default is no-lock */ + + /* + * Search for entry + */ + entry = hashbin->hb_queue[ bin ]; + if ( entry ) { + do { + /* + * Check for key + */ + if ( entry->q_hash == hashv ) { + /* + * Name compare too? + */ + if ( name ) { + if ( strcmp( entry->q_name, name) == 0) + { + found = TRUE; + break; + } + } else { + found = TRUE; + break; + } + } + entry = entry->q_next; + } while ( entry != hashbin->hb_queue[ bin ] ); + } + + /* + * If entry was found, dequeue it + */ + if ( found ) { + dequeue_general( (QUEUE**) &hashbin->hb_queue[ bin ], + (QUEUE*) entry ); + hashbin->hb_size--; + + /* + * Check if this item is the currently selected item, and in + * that case we must reset hb_current + */ + if ( entry == hashbin->hb_current) + hashbin->hb_current = NULL; + } + + /* Release lock */ + if ( hashbin->hb_type & HB_GLOBAL) { + spin_unlock_irq( &hashbin->hb_mutex[ bin]); + + } else if ( hashbin->hb_type & HB_LOCAL) { + restore_flags( flags); + } + + + /* Return */ + if ( found ) + return entry; + else + return NULL; + +} + +/* + * Function hashbin_get_first (hashbin) + * + * Get a pointer to first element in hashbin, this function must be + * called before any calls to hashbin_get_next()! + * + */ +QUEUE *hashbin_get_first( hashbin_t* hashbin) +{ + QUEUE *entry; + int i; + + ASSERT( hashbin != NULL, return NULL;); + ASSERT( hashbin->magic == HB_MAGIC, return NULL;); + + if ( hashbin == NULL) + return NULL; + + for ( i = 0; i < HASHBIN_SIZE; i ++ ) { + entry = hashbin->hb_queue[ i]; + if ( entry) { + hashbin->hb_current = entry; + return entry; + } + } + /* + * Did not find any item in hashbin + */ + return NULL; +} + +/* + * Function hashbin_get_next (hashbin) + * + * Get next item in hashbin. A series of hashbin_get_next() calls must + * be started by a call to hashbin_get_first(). The function returns + * NULL when all items have been traversed + * + */ +QUEUE *hashbin_get_next( hashbin_t *hashbin) +{ + QUEUE* entry; + int bin; + int i; + + ASSERT( hashbin != NULL, return NULL;); + ASSERT( hashbin->magic == HB_MAGIC, return NULL;); + + if ( hashbin->hb_current == NULL) { + ASSERT( hashbin->hb_current != NULL, return NULL;); + return NULL; + } + entry = hashbin->hb_current->q_next; + bin = GET_HASHBIN( entry->q_hash); + + /* + * Make sure that we are not back at the beginning of the queue + * again + */ + if ( entry != hashbin->hb_queue[ bin ]) { + hashbin->hb_current = entry; + + return entry; + } + + /* + * Check that this is not the last queue in hashbin + */ + if ( bin >= HASHBIN_SIZE) + return NULL; + + /* + * Move to next queue in hashbin + */ + bin++; + for ( i = bin; i < HASHBIN_SIZE; i++ ) { + entry = hashbin->hb_queue[ i]; + if ( entry) { + hashbin->hb_current = entry; + + return entry; + } + } + return NULL; +} + +/* + * Function enqueue_last (queue, proc) + * + * Insert item into end of queue. + * + */ +static void __enqueue_last( QUEUE **queue, QUEUE* element) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + /* + * Check if queue is empty. + */ + if ( *queue == NULL ) { + /* + * Queue is empty. Insert one element into the queue. + */ + element->q_next = element->q_prev = *queue = element; + + } else { + /* + * Queue is not empty. Insert element into end of queue. + */ + element->q_prev = (*queue)->q_prev; + element->q_prev->q_next = element; + (*queue)->q_prev = element; + element->q_next = *queue; + } +} + +inline void enqueue_last( QUEUE **queue, QUEUE* element) +{ + unsigned long flags; + + save_flags(flags); + cli(); + + __enqueue_last( queue, element); + + restore_flags(flags); +} + +/* + * Function enqueue_first (queue, proc) + * + * Insert item first in queue. + * + */ +void enqueue_first(QUEUE **queue, QUEUE* element) +{ + + DEBUG( 4, "enqueue_first()\n"); + + /* + * Check if queue is empty. + */ + if ( *queue == NULL ) { + /* + * Queue is empty. Insert one element into the queue. + */ + element->q_next = element->q_prev = *queue = element; + + } else { + /* + * Queue is not empty. Insert element into front of queue. + */ + element->q_next = (*queue); + (*queue)->q_prev->q_next = element; + element->q_prev = (*queue)->q_prev; + (*queue)->q_prev = element; + (*queue) = element; + } +} + +/* + * Function enqueue_queue (queue, list) + * + * Insert a queue (list) into the start of the first queue + * + */ +void enqueue_queue( QUEUE** queue, QUEUE** list ) +{ + QUEUE* tmp; + + /* + * Check if queue is empty + */ + if ( *queue ) { + (*list)->q_prev->q_next = (*queue); + (*queue)->q_prev->q_next = (*list); + tmp = (*list)->q_prev; + (*list)->q_prev = (*queue)->q_prev; + (*queue)->q_prev = tmp; + } else { + *queue = (*list); + } + + (*list) = NULL; +} + +/* + * Function enqueue_second (queue, proc) + * + * Insert item behind head of queue. + * + */ +#if 0 +static void enqueue_second(QUEUE **queue, QUEUE* element) +{ + DEBUG( 0, "enqueue_second()\n"); + + /* + * Check if queue is empty. + */ + if ( *queue == NULL ) { + /* + * Queue is empty. Insert one element into the queue. + */ + element->q_next = element->q_prev = *queue = element; + + } else { + /* + * Queue is not empty. Insert element into .. + */ + element->q_prev = (*queue); + (*queue)->q_next->q_prev = element; + element->q_next = (*queue)->q_next; + (*queue)->q_next = element; + } +} +#endif + +/* + * Function dequeue (queue) + * + * Remove first entry in queue + * + */ +QUEUE *dequeue_first(QUEUE **queue) +{ + QUEUE *ret; + + DEBUG( 4, "dequeue_first()\n"); + + /* + * Set return value + */ + ret = *queue; + + if ( *queue == NULL ) { + /* + * Queue was empty. + */ + } else if ( (*queue)->q_next == *queue ) { + /* + * Queue only contained a single element. It will now be + * empty. + */ + *queue = NULL; + } else { + /* + * Queue contained several element. Remove the first one. + */ + (*queue)->q_prev->q_next = (*queue)->q_next; + (*queue)->q_next->q_prev = (*queue)->q_prev; + *queue = (*queue)->q_next; + } + + /* + * Return the removed entry (or NULL of queue was empty). + */ + return ret; +} + +/* + * Function dequeue_general (queue, element) + * + * + */ +static QUEUE *dequeue_general(QUEUE **queue, QUEUE* element) +{ + QUEUE *ret; + + DEBUG( 4, "dequeue_general()\n"); + + /* + * Set return value + */ + ret = *queue; + + if ( *queue == NULL ) { + /* + * Queue was empty. + */ + } if ( (*queue)->q_next == *queue ) { + /* + * Queue only contained a single element. It will now be + * empty. + */ + *queue = NULL; + + } else { + /* + * Remove specific element. + */ + element->q_prev->q_next = element->q_next; + element->q_next->q_prev = element->q_prev; + if ( (*queue) == element) + (*queue) = element->q_next; + } + + /* + * Return the removed entry (or NULL of queue was empty). + */ + return ret; +} + +/* + * Function hash (name) + * + * This function hash the input string 'name' using the ELF hash + * function for strings. + */ +static __u32 hash( char* name) +{ + __u32 h = 0; + __u32 g; + + while(*name) { + h = (h<<4) + *name++; + if ((g = (h & 0xf0000000))) + h ^=g>>24; + h &=~g; + } + return h; +} diff --git a/net/irda/irsysctl.c b/net/irda/irsysctl.c new file mode 100644 index 000000000000..13ef49559eb1 --- /dev/null +++ b/net/irda/irsysctl.c @@ -0,0 +1,88 @@ +/********************************************************************* + * + * Filename: irsysctl.c + * Version: + * Description: + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sun May 24 22:12:06 1998 + * Modified at: Wed Dec 9 01:29:22 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1997 Dag Brattli, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include +#include +#include + +#define NET_IRDA 412 /* Random number */ +enum { DISCOVERY=1, DEVNAME, COMPRESSION }; + +extern int sysctl_discovery; +int sysctl_compression = 0; +extern char sysctl_devname[]; + +/* One file */ +static ctl_table irda_table[] = { + { DISCOVERY, "discovery", &sysctl_discovery, + sizeof(int), 0644, NULL, &proc_dointvec }, + { DEVNAME, "devname", sysctl_devname, + 65, 0644, NULL, &proc_dostring, &sysctl_string}, + { COMPRESSION, "compression", &sysctl_compression, + sizeof(int), 0644, NULL, &proc_dointvec }, + { 0 } +}; + +/* One directory */ +static ctl_table irda_net_table[] = { + { NET_IRDA, "irda", NULL, 0, 0555, irda_table }, + { 0 } +}; + +/* The parent directory */ +static ctl_table irda_root_table[] = { + { CTL_NET, "net", NULL, 0, 0555, irda_net_table }, + { 0 } +}; + +static struct ctl_table_header *irda_table_header; + +/* + * Function irda_sysctl_register (void) + * + * Register our sysctl interface + * + */ +int irda_sysctl_register(void) +{ + irda_table_header = register_sysctl_table( irda_root_table, 0); + if ( !irda_table_header) + return -ENOMEM; + return 0; +} + +/* + * Function irda_sysctl_unregister (void) + * + * Unregister our sysctl interface + * + */ +void irda_sysctl_unregister(void) +{ + unregister_sysctl_table( irda_table_header); +} + + + diff --git a/net/irda/irttp.c b/net/irda/irttp.c new file mode 100644 index 000000000000..debcaae53ddc --- /dev/null +++ b/net/irda/irttp.c @@ -0,0 +1,1442 @@ +/********************************************************************* + * + * Filename: irttp.c + * Version: 0.4 + * Description: Tiny Transport Protocol (TTP) implementation + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sun Aug 31 20:14:31 1997 + * Modified at: Mon Dec 14 11:53:19 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli , + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include +#include +#include + +#include + +#include +#include +#include + +struct irttp_cb *irttp = NULL; + +static void __irttp_close_tsap( struct tsap_cb *self); + +static void irttp_data_indication( void *instance, void *sap, + struct sk_buff *skb); +static void irttp_udata_indication( void *instance, void *sap, + struct sk_buff *skb); +static void irttp_disconnect_indication( void *instance, void *sap, + LM_REASON reason, + struct sk_buff *); +static void irttp_connect_indication( void *instance, void *sap, + struct qos_info *qos, int max_sdu_size, + struct sk_buff *skb); + +static void irttp_run_tx_queue( struct tsap_cb *self); +static void irttp_run_rx_queue( struct tsap_cb *self); + +static void irttp_flush_queues( struct tsap_cb *self); +static void irttp_fragment_skb( struct tsap_cb *self, struct sk_buff *skb); +static struct sk_buff *irttp_reassemble_skb( struct tsap_cb *self); +static void irttp_start_todo_timer( struct tsap_cb *self, int timeout); + +/* + * Function irttp_init (void) + * + * Initialize the IrTTP layer. Called by module initialization code + * + */ +__initfunc(int irttp_init(void)) +{ + DEBUG( 4, "--> irttp_init\n"); + + /* Initialize the irttp structure. */ + if ( irttp == NULL) { + irttp = kmalloc( sizeof(struct irttp_cb), GFP_KERNEL); + if ( irttp == NULL) + return -ENOMEM; + } + memset( irttp, 0, sizeof(struct irttp_cb)); + + irttp->magic = TTP_MAGIC; + + irttp->tsaps = hashbin_new( HB_LOCAL); + if ( !irttp->tsaps) { + printk( KERN_WARNING "IrDA: Can't allocate IrTTP hashbin!\n"); + return -ENOMEM; + } + + return 0; +} + +/* + * Function irttp_cleanup (void) + * + * Called by module destruction/cleanup code + * + */ +void irttp_cleanup(void) +{ + DEBUG( 4, "irttp_cleanup\n"); + + /* Check for main structure */ + ASSERT( irttp != NULL, return;); + ASSERT( irttp->magic == TTP_MAGIC, return;); + + /* + * Delete hashbin and close all TSAP instances in it + */ + hashbin_delete( irttp->tsaps, (FREE_FUNC) __irttp_close_tsap); + + irttp->magic = ~TTP_MAGIC; + + /* De-allocate main structure */ + kfree( irttp); + + irttp = NULL; +} + +/* + * Function irttp_open_tsap (stsap, notify) + * + * Create TSAP connection endpoint, + */ +struct tsap_cb *irttp_open_tsap( __u8 stsap_sel, int credit, + struct notify_t *notify) +{ + struct notify_t ttp_notify; + struct tsap_cb *self; + struct lsap_cb *lsap; + + ASSERT( irttp != NULL, return NULL;); + ASSERT( irttp->magic == TTP_MAGIC, return NULL;); + + self = kmalloc( sizeof(struct tsap_cb), GFP_ATOMIC); + if ( self == NULL) { + printk( KERN_ERR "IrTTP: Can't allocate memory for " + "TSAP control block!\n"); + return NULL; + } + memset( self, 0, sizeof(struct tsap_cb)); + + init_timer( &self->todo_timer); + + /* Initialize callbacks for IrLMP to use */ + + irda_notify_init( &ttp_notify); + ttp_notify.connect_confirm = irttp_connect_confirm; + ttp_notify.connect_indication = irttp_connect_indication; + ttp_notify.disconnect_indication = irttp_disconnect_indication; + ttp_notify.data_indication = irttp_data_indication; + ttp_notify.udata_indication = irttp_udata_indication; + ttp_notify.instance = self; + strncpy( ttp_notify.name, notify->name, NOTIFY_MAX_NAME); + + /* + * Create LSAP at IrLMP layer + */ + lsap = irlmp_open_lsap( stsap_sel, &ttp_notify); + if ( lsap == NULL) { + printk( KERN_ERR "IrTTP, Unable to get LSAP!!\n"); + return NULL; + } + + /* + * If user specified LSAP_ANY as source TSAP selector, then IrLMP + * will replace it with whatever source selector which is free, so + * the stsap_sel we have might not be valid anymore + */ + self->stsap_sel = lsap->slsap_sel; + DEBUG( 4, __FUNCTION__ "(), stsap_sel=%02x\n", self->stsap_sel); + + self->notify = *notify; + self->lsap = lsap; + self->magic = TTP_TSAP_MAGIC; + + skb_queue_head_init( &self->rx_queue); + skb_queue_head_init( &self->tx_queue); + skb_queue_head_init( &self->rx_fragments); + + /* + * Insert ourself into the hashbin + */ + hashbin_insert( irttp->tsaps, (QUEUE *) self, self->stsap_sel, NULL); + + if ( credit > TTP_MAX_QUEUE) + self->initial_credit = TTP_MAX_QUEUE; + else + self->initial_credit = credit; + + return self; +} + +/* + * Function irttp_close (handle) + * + * Remove an instance of a TSAP. This function should only deal with the + * deallocation of the TSAP, and resetting of the TSAPs values; + * + */ +static void __irttp_close_tsap( struct tsap_cb *self) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + /* First make sure we're connected. */ + ASSERT( self != NULL, return;); + ASSERT( self->magic == TTP_TSAP_MAGIC, return;); + + irttp_flush_queues( self); + + del_timer( &self->todo_timer); + + self->connected = FALSE; + self->magic = ~TTP_TSAP_MAGIC; + + /* + * Deallocate structure + */ + kfree( self); + + DEBUG( 4, "irttp_close_tsap() -->\n"); +} + +/* + * Function irttp_close (self) + * + * Remove TSAP from list of all TSAPs and then deallocate all resources + * associated with this TSAP + * + */ +void irttp_close_tsap( struct tsap_cb *self) +{ + struct tsap_cb *tsap; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == TTP_TSAP_MAGIC, return;); + + tsap = hashbin_remove( irttp->tsaps, self->stsap_sel, NULL); + + ASSERT( tsap == self, return;); + + /* Close corresponding LSAP */ + if ( self->lsap) { + irlmp_close_lsap( self->lsap); + self->lsap = NULL; + } + + __irttp_close_tsap( self); +} + +/* + * Function irttp_udata_request (self, skb) + * + * Send unreliable data on this TSAP + * + */ +int irttp_udata_request( struct tsap_cb *self, struct sk_buff *skb) +{ + ASSERT( self != NULL, return -1;); + ASSERT( self->magic == TTP_TSAP_MAGIC, return -1;); + ASSERT( skb != NULL, return -1;); + + DEBUG( 4, __FUNCTION__ "()\n"); + + /* Check that nothing bad happens */ + if (( skb->len == 0) || ( !self->connected)) { + DEBUG( 0, __FUNCTION__ "(), No data, or not connected\n"); + return -1; + } + + if ( skb->len > self->max_seg_size) { + DEBUG( 0, __FUNCTION__ "(), UData is to large for IrLAP!\n"); + return -1; + } + + irlmp_udata_request( self->lsap, skb); + self->stats.tx_packets++; + + return 0; +} + +/* + * Function irttp_data_request (handle, skb) + * + * Queue frame for transmission. If SAR is enabled, fragement the frame + * and queue the fragments for transmission + */ +int irttp_data_request( struct tsap_cb *self, struct sk_buff *skb) +{ + __u8 *frame; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return -1;); + ASSERT( self->magic == TTP_TSAP_MAGIC, return -1;); + ASSERT( skb != NULL, return -1;); + + IS_SKB( skb, return -1;); + + /* Check that nothing bad happens */ + if (( skb->len == 0) || ( !self->connected)) { + DEBUG( 4, __FUNCTION__ "(), No data, or not connected\n"); + return -1; + } + + /* + * Check if SAR is disabled, and the frame is larger than what fits + * inside an IrLAP frame + */ + if (( self->tx_max_sdu_size == 0) && + ( skb->len > self->max_seg_size)) + { + DEBUG( 0, __FUNCTION__ + "(), SAR disabled, and data is to large for IrLAP!\n"); + return -1; + } + + /* + * Check if SAR is enabled, and the frame is larger than the + * TxMaxSduSize + */ + if (( self->tx_max_sdu_size != 0) && + (skb->len > self->tx_max_sdu_size)) + { + DEBUG( 0, __FUNCTION__ "(), SAR enabled, " + "but data is larger than TxMaxSduSize!\n"); + return -1; + } + /* + * Check if transmit queue is full + */ + if ( skb_queue_len( &self->tx_queue) >= TTP_MAX_QUEUE) { + /* + * Give it a chance to empty itself + */ + irttp_run_tx_queue( self); + + return -1; + } + + /* Queue frame, or queue frame segments */ + if (( self->tx_max_sdu_size == 0) || + ( skb->len < self->max_seg_size)) { + /* Queue frame */ + frame = skb_push( skb, TTP_HEADER); + frame[0] = 0x00; /* Clear more bit */ + + DEBUG( 4, __FUNCTION__ "(), queueing original skb\n"); + skb_queue_tail( &self->tx_queue, skb); + } else { + /* + * Fragment the frame, this function will also queue the + * fragments, we don't care about the fact the the transmit + * queue may be overfilled by all the segments for a little + * while + */ + irttp_fragment_skb( self, skb); + } + + /* Check if we can accept more data from client */ + if (( !self->tx_sdu_busy) && + ( skb_queue_len( &self->tx_queue) > HIGH_THRESHOLD)) { + + /* Tx queue filling up, so stop client */ + self->tx_sdu_busy = TRUE; + + if ( self->notify.flow_indication) { + self->notify.flow_indication( self->notify.instance, + self, + FLOW_STOP); + } + } + + /* Try to make some progress */ + irttp_run_tx_queue( self); + + return 0; +} + +/* + * Function irttp_xmit (self) + * + * If possible, transmit a frame queued for transmission. + * + */ +static void irttp_run_tx_queue( struct tsap_cb *self) +{ + struct sk_buff *skb = NULL; + unsigned long flags; + __u8 *frame; + int n; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == TTP_TSAP_MAGIC, return;); + + if ( irda_lock( &self->tx_queue_lock) == FALSE) + return; + + while (( self->send_credit > 0) && !skb_queue_empty( &self->tx_queue)){ + + skb = skb_dequeue( &self->tx_queue); + ASSERT( skb != NULL, return;); + + /* Make room for TTP header */ + ASSERT( skb_headroom( skb) >= TTP_HEADER, return;); + + /* + * Since we can transmit and receive frames concurrently, + * the code below is a critical region and we must assure that + * nobody messes with the credits while we update them. + */ + save_flags( flags); + cli(); + + n = self->avail_credit; + self->avail_credit = 0; + + /* Only space for 127 credits in frame */ + if ( n > 127) { + self->avail_credit = n-127; + n = 127; + } + self->remote_credit += n; + self->send_credit--; + + restore_flags(flags); + + DEBUG( 4, "irttp_xmit: Giving away %d credits\n", n); + + /* + * More bit must be set by the data_request() or fragment() + * functions + */ + frame = skb->data; + + DEBUG( 4, __FUNCTION__ "(), More=%s\n", frame[0] & 0x80 ? + "TRUE" : "FALSE" ); + + frame[0] |= (__u8) (n & 0x7f); + + irlmp_data_request( self->lsap, skb); + self->stats.tx_packets++; + + /* Check if we can accept more frames from client */ + if (( self->tx_sdu_busy) && + ( skb_queue_len( &self->tx_queue) < LOW_THRESHOLD)) { + self->tx_sdu_busy = FALSE; + + if ( self->notify.flow_indication) + self->notify.flow_indication( self->notify.instance, + self, + FLOW_START); + } + } + + /* Reset lock */ + self->tx_queue_lock = 0; + + /* Check if there is any disconnect request pending */ + if ( self->disconnect_pend) { + if ( self->disconnect_skb) { + irttp_disconnect_request( self, self->disconnect_skb, + P_NORMAL); + self->disconnect_skb = NULL; + } else + irttp_disconnect_request( self, NULL, P_NORMAL); + } +} + +/* + * Function irttp_give_credit (self) + * + * Send a dataless flowdata TTP-PDU and give available credit to peer + * TSAP + */ +void irttp_give_credit( struct tsap_cb *self) +{ + struct sk_buff *tx_skb = NULL; + unsigned long flags; + int n; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == TTP_TSAP_MAGIC, return;); + + DEBUG( 4, "irttp_give_credit() send=%d,avail=%d,remote=%d\n", + self->send_credit, self->avail_credit, self->remote_credit); + + /* Give credit to peer */ + tx_skb = dev_alloc_skb( 64); + if ( tx_skb == NULL) { + DEBUG( 0, "irttp_give_credit: " + "Could not allocate an sk_buff of length %d\n", 64); + return; + } + + /* Reserve space for LMP, and LAP header */ + skb_reserve( tx_skb, LMP_HEADER+LAP_HEADER); + + /* + * Since we can transmit and receive frames concurrently, + * the code below is a critical region and we must assure that + * nobody messes with the credits while we update them. + */ + save_flags( flags); + cli(); + + n = self->avail_credit; + self->avail_credit = 0; + + /* Only space for 127 credits in frame */ + if ( n > 127) { + self->avail_credit = n - 127; + n = 127; + } + self->remote_credit += n; + + restore_flags(flags); + + skb_put( tx_skb, 1); + tx_skb->data[0] = (__u8) ( n & 0x7f); + + irlmp_data_request( self->lsap, tx_skb); + self->stats.tx_packets++; +} + +/* + * Function irttp_udata_indication (instance, sap, skb) + * + * + * + */ +void irttp_udata_indication( void *instance, void *sap, struct sk_buff *skb) +{ + struct tsap_cb *self; + + DEBUG( 4, __FUNCTION__ "()\n"); + + self = (struct tsap_cb *) instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == TTP_TSAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + + /* Just pass data to layer above */ + if ( self->notify.udata_indication) { + self->notify.udata_indication( self->notify.instance, self, + skb); + } + self->stats.rx_packets++; +} + +/* + * Function irttp_data_indication (handle, skb) + * + * Receive segment from IrLMP. + * + */ +void irttp_data_indication( void *instance, void *sap, struct sk_buff *skb) +{ + struct tsap_cb *self; + int more; + int n; + __u8 *frame; + + self = (struct tsap_cb *) instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == TTP_TSAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + + frame = skb->data; + + n = frame[0] & 0x7f; /* Extract the credits */ + more = frame[0] & 0x80; + + DEBUG( 4, __FUNCTION__"(), got %d credits, TSAP sel=%02x\n", + n, self->stsap_sel); + + self->stats.rx_packets++; + + /* + * Data or dataless frame? Dataless frames only contain the + * TTP_HEADER + */ + if ( skb->len == 1) { + /* Dataless flowdata TTP-PDU */ + self->send_credit += n; + } else { + /* Deal with inbound credit */ + self->send_credit += n; + self->remote_credit--; + + /* + * We don't remove the TTP header, since we must preserve the + * more bit, so the defragment routing knows what to do + */ + skb_queue_tail( &self->rx_queue, skb); + } + + irttp_run_rx_queue( self); + + /* + * Give avay some credits to peer? + */ + if (( skb_queue_empty( &self->tx_queue)) && + ( self->remote_credit < LOW_THRESHOLD) && + ( self->avail_credit > 0)) + { + /* Schedule to start immediately after this thread */ + irttp_start_todo_timer( self, 0); + } + + /* If peer has given us some credites and we didn't have anyone + * from before, the we need to shedule the tx queue? + */ + if ( self->send_credit == n) + irttp_start_todo_timer( self, 0); +} + +/* + * Function irttp_flow_request (self, command) + * + * This funtion could be used by the upper layers to tell IrTTP to stop + * delivering frames if the receive queues are starting to get full, or + * to tell IrTTP to start delivering frames again. + */ +void irttp_flow_request( struct tsap_cb *self, LOCAL_FLOW flow) +{ + DEBUG( 0, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == TTP_TSAP_MAGIC, return;); + + switch ( flow) { + case FLOW_STOP: + DEBUG( 0, __FUNCTION__ "(), flow stop\n"); + self->rx_sdu_busy = TRUE; + break; + case FLOW_START: + DEBUG( 0, __FUNCTION__ "(), flow start\n"); + self->rx_sdu_busy = FALSE; + + irttp_run_rx_queue( self); + break; + default: + DEBUG( 0, __FUNCTION__ "(), Unknown flow command!\n"); + } +} + +/* + * Function irttp_connect_request (self, dtsap_sel, daddr, qos) + * + * Try to connect to remote destination TSAP selector + * + */ +void irttp_connect_request( struct tsap_cb *self, __u8 dtsap_sel, __u32 daddr, + struct qos_info *qos, int max_sdu_size, + struct sk_buff *userdata) +{ + struct sk_buff *skb; + __u8 *frame; + __u8 n; + + DEBUG( 4, __FUNCTION__ "(), max_sdu_size=%d\n", max_sdu_size); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == TTP_TSAP_MAGIC, return;); + + /* Any userdata supplied? */ + if ( userdata == NULL) { + skb = dev_alloc_skb( 64); + if (skb == NULL) { + DEBUG( 0, __FUNCTION__ "Could not allocate an " + "sk_buff of length %d\n", 64); + return; + } + + /* Reserve space for MUX_CONTROL and LAP header */ + skb_reserve( skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER)); + } else { + skb = userdata; + /* + * Check that the client has reserved enough space for + * headers + */ + ASSERT( skb_headroom( userdata) >= + (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER), return;); + } + + /* Initialize connection parameters */ + self->connected = FALSE; + self->avail_credit = 0; + self->rx_max_sdu_size = max_sdu_size; + self->rx_sdu_size = 0; + self->rx_sdu_busy = FALSE; + self->dtsap_sel = dtsap_sel; + + n = self->initial_credit; + + self->remote_credit = 0; + self->send_credit = 0; + + /* + * Give away max 127 credits for now + */ + if ( n > 127) { + self->avail_credit=n-127; + n = 127; + } + + self->remote_credit = n; + + /* SAR enabled? */ + if ( max_sdu_size > 0) { + ASSERT( skb_headroom( skb) >= + (TTP_HEADER_WITH_SAR+LMP_CONTROL_HEADER+LAP_HEADER), + return;); + + /* Insert SAR parameters */ + frame = skb_push( skb, TTP_HEADER_WITH_SAR); + + frame[0] = TTP_PARAMETERS | n; + frame[1] = 0x04; /* Length */ + frame[2] = 0x01; /* MaxSduSize */ + frame[3] = 0x02; /* Value length */ + *((__u16 *) (frame+4))= htons( max_sdu_size); /* Big endian! */ + } else { + /* Insert plain TTP header */ + frame = skb_push( skb, TTP_HEADER); + + /* Insert initial credit in frame */ + frame[0] = n & 0x7f; + } + + /* Connect with IrLMP. No QoS parameters for now */ + irlmp_connect_request( self->lsap, dtsap_sel, daddr, qos, skb); +} + +/* + * Function irttp_connect_confirm (handle, qos, skb) + * + * Sevice user confirms TSAP connection with peer. + * + */ +void irttp_connect_confirm( void *instance, void *sap, struct qos_info *qos, + int max_seg_size, struct sk_buff *skb) +{ + struct tsap_cb *self; + __u8 *frame; + __u8 n; + int parameters; + + DEBUG( 4, __FUNCTION__ "()\n"); + + self = (struct tsap_cb *) instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == TTP_TSAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + + /* FIXME: just remove this when we know its working */ + ASSERT( max_seg_size == qos->data_size.value, return;); + + self->max_seg_size = max_seg_size-LMP_HEADER-LAP_HEADER; + + /* + * Check if we have got some QoS parameters back! This should be the + * negotiated QoS for the link. + */ + if ( qos) { + DEBUG( 4, "IrTTP, Negotiated BAUD_RATE: %02x\n", + qos->baud_rate.bits); + DEBUG( 4, "IrTTP, Negotiated BAUD_RATE: %d bps.\n", + qos->baud_rate.value); + } + + frame = skb->data; + n = frame[0] & 0x7f; + + DEBUG( 4, __FUNCTION__ "(), Initial send_credit=%d\n", n); + + self->send_credit = n; + self->tx_max_sdu_size = 0; + self->connected = TRUE; + + parameters = frame[0] & 0x80; + if ( parameters) { + DEBUG( 4, __FUNCTION__ "(), Contains parameters!\n"); + + self->tx_max_sdu_size = ntohs(*(__u16 *)(frame+4)); + DEBUG( 4, __FUNCTION__ "(), RxMaxSduSize=%d\n", + self->tx_max_sdu_size); + } + + DEBUG( 4, "irttp_connect_confirm() send=%d,avail=%d,remote=%d\n", + self->send_credit, self->avail_credit, self->remote_credit); + + skb_pull( skb, TTP_HEADER); + + if ( self->notify.connect_confirm) { + self->notify.connect_confirm( self->notify.instance, self, + qos, self->tx_max_sdu_size, + skb); + } +} + +/* + * Function irttp_connect_indication (handle, skb) + * + * Some other device is connecting to this TSAP + * + */ +void irttp_connect_indication( void *instance, void *sap, + struct qos_info *qos, int max_seg_size, + struct sk_buff *skb) +{ + struct tsap_cb *self; + __u8 *frame; + int parameters; + int n; + + self = (struct tsap_cb *) instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == TTP_TSAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + + /* FIXME: just remove this when we know its working */ + ASSERT( max_seg_size == qos->data_size.value, return;); + + self->max_seg_size = max_seg_size-LMP_HEADER-LAP_HEADER; + + DEBUG( 4, "irttp_connect_indication(), TSAP sel=%02x\n", + self->stsap_sel); + + /* FIXME: Need to update dtsap_sel if its equal to LSAP_ANY */ +/* if ( self->dtsap_sel == LSAP_ANY) */ +/* self->dtsap_sel = lsap->dlsap_sel; */ + + frame = skb->data; + n = frame[0] & 0x7f; + + self->send_credit = n; + self->tx_max_sdu_size = 0; + + parameters = frame[0] & 0x80; + if ( parameters) { + DEBUG( 4, __FUNCTION__ "(), Contains parameters!\n"); + + self->tx_max_sdu_size = ntohs(*(__u16 *)(frame+4)); + DEBUG( 4, __FUNCTION__ "(), MaxSduSize=%d\n", + self->tx_max_sdu_size); + } + + DEBUG( 4, "irttp_connect_indication: initial send_credit=%d\n", n); + + skb_pull( skb, 1); + + if ( self->notify.connect_indication) { + self->notify.connect_indication( self->notify.instance, self, + qos, self->rx_max_sdu_size, + skb); + } +} + +/* + * Function irttp_connect_response (handle, userdata) + * + * Service user is accepting the connection, just pass it down to + * IrLMP! + * + */ +void irttp_connect_response( struct tsap_cb *self, int max_sdu_size, + struct sk_buff *userdata) +{ + struct sk_buff *skb; + __u8 *frame; + __u8 n; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == TTP_TSAP_MAGIC, return;); + + DEBUG( 4, __FUNCTION__ "(), Source TSAP selector=%02x\n", + self->stsap_sel); + + /* Any userdata supplied? */ + if ( userdata == NULL) { + skb = dev_alloc_skb( 64); + if (skb == NULL) { + DEBUG( 0, __FUNCTION__ "Could not allocate an " + "sk_buff of length %d\n", 64); + return; + } + + /* Reserve space for MUX_CONTROL and LAP header */ + skb_reserve( skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER)); + } else { + skb = userdata; + /* + * Check that the client has reserved enough space for + * headers + */ + ASSERT( skb_headroom( skb) >= + (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER), return;); + } + + self->avail_credit = 0; + self->remote_credit = 0; + self->rx_max_sdu_size = max_sdu_size; + self->rx_sdu_size = 0; + self->rx_sdu_busy = FALSE; + + n = self->initial_credit; + + /* Frame has only space for max 127 credits (7 bits) */ + if ( n > 127) { + self->avail_credit = n - 127; + n = 127; + } + + self->remote_credit = n; + self->connected = TRUE; + + /* SAR enabled? */ + if ( max_sdu_size > 0) { + ASSERT( skb_headroom( skb) >= + (TTP_HEADER_WITH_SAR+LMP_CONTROL_HEADER+LAP_HEADER), + return;); + + /* Insert TTP header with SAR parameters */ + frame = skb_push( skb, TTP_HEADER_WITH_SAR); + + frame[0] = TTP_PARAMETERS | n; + frame[1] = 0x04; /* Length */ + frame[2] = 0x01; /* MaxSduSize */ + frame[3] = 0x02; /* Value length */ + *((__u16 *) (frame+4))= htons( max_sdu_size); + } else { + /* Insert TTP header */ + frame = skb_push( skb, TTP_HEADER); + + frame[0] = n & 0x7f; + } + + irlmp_connect_response( self->lsap, skb); +} + +/* + * Function irttp_disconnect_request ( self) + * + * Close this connection please! If priority is high, the queued data + * segments, if any, will be deallocated first + * + */ +void irttp_disconnect_request( struct tsap_cb *self, struct sk_buff *userdata, + int priority) +{ + struct sk_buff *skb; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == TTP_TSAP_MAGIC, return;); + + /* Already disconnected? */ + if ( !self->connected) { + DEBUG( 4, __FUNCTION__ "(), already disconnected!\n"); + return; + } + + /* Disconnect already pending? */ + if ( self->disconnect_pend) { + DEBUG( 0, __FUNCTION__ "(), disconnect already pending\n"); + if ( userdata) { + dev_kfree_skb( userdata); + } + + /* Try to make some progress */ + irttp_run_rx_queue( self); + return; + } + + /* + * Check if there is still data segments in the transmit queue + */ + if ( skb_queue_len( &self->tx_queue) > 0) { + if ( priority == P_HIGH) { + DEBUG( 0, __FUNCTION__ "High priority!!()\n" ); + + /* + * No need to send the queued data, if we are + * disconnecting right now since the data will + * not have any usable connection to be sent on + */ + irttp_flush_queues( self); + } else if ( priority == P_NORMAL) { + /* + * Must delay disconnect til after all data segments + * have been sent an the tx_queue is empty + */ + if ( userdata) + self->disconnect_skb = userdata; + else + self->disconnect_skb = NULL; + + self->disconnect_pend = TRUE; + + irttp_run_tx_queue( self); + /* + * irttp_xmit will call us again when the tx_queue + * is empty + */ + return; + } + } + DEBUG( 0, __FUNCTION__ "(), Disconnecting ...\n"); + + self->connected = FALSE; + + if ( !userdata) { + skb = dev_alloc_skb( 64); + if (skb == NULL) { + DEBUG( 0, __FUNCTION__ "(), Could not allocate an " + "sk_buff of length %d\n", 64); + return; + } + + /* + * Reserve space for MUX and LAP header + */ + skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER); + + userdata = skb; + } + irlmp_disconnect_request( self->lsap, userdata); +} + +/* + * Function irttp_disconnect_indication (self, reason) + * + * Disconnect indication, TSAP disconnected by peer? + * + */ +void irttp_disconnect_indication( void *instance, void *sap, LM_REASON reason, + struct sk_buff *userdata) +{ + struct tsap_cb *self; + + DEBUG( 4, "irttp_disconnect_indication()\n"); + + self = ( struct tsap_cb *) instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == TTP_TSAP_MAGIC, return;); + + self->connected = FALSE; + + /* + * Use callback to notify layer above + */ + if ( self->notify.disconnect_indication) + self->notify.disconnect_indication( self->notify.instance, + self, reason, userdata); +} + +/* + * Function irttp_run_rx_queue (self) + * + * Check if we have any frames to be transmitted, or if we have any + * available credit to give away. + */ +void irttp_run_rx_queue( struct tsap_cb *self) +{ + struct sk_buff *skb; + __u8 *frame; + int more = 0; + void *instance; + + ASSERT( self != NULL, return;); + ASSERT( self->magic == TTP_TSAP_MAGIC, return;); + + instance = self->notify.instance; + ASSERT( instance != NULL, return;); + + DEBUG( 4, "irttp_do_events() send=%d,avail=%d,remote=%d\n", + self->send_credit, self->avail_credit, self->remote_credit); + + if ( irda_lock( &self->rx_queue_lock) == FALSE) + return; + + /* + * Process receive queue + */ + while (( !skb_queue_empty( &self->rx_queue)) && !self->rx_sdu_busy) { + + skb = skb_dequeue( &self->rx_queue); + if ( !skb) + break; /* Should not happend, but ... */ + + self->avail_credit++; + + frame = skb->data; + more = frame[0] & 0x80; + DEBUG( 4, __FUNCTION__ "(), More=%s\n", more ? "TRUE" : + "FALSE"); + + /* Remove TTP header */ + skb_pull( skb, TTP_HEADER); + + /* Add the length of the remaining data */ + self->rx_sdu_size += skb->len; + + /* + * If SAR is disabled, or user has requested no reassembly + * of received fragements then we just deliver them + * immediately. This can be requested by clients that + * implements byte streams without any message boundaries + */ + if ((self->no_defrag) || (self->rx_max_sdu_size == 0)) { + self->notify.data_indication( instance, self, skb); + self->rx_sdu_size = 0; + + continue; + } + + /* Check if this is a fragment, and not the last fragment */ + if ( more) { + /* + * Queue the fragment if we still are within the + * limits of the maximum size of the rx_sdu + */ + if ( self->rx_sdu_size <= self->rx_max_sdu_size) { + DEBUG( 4, __FUNCTION__ + "(), queueing fragment\n"); + + skb_queue_tail( &self->rx_fragments, skb); + } else { + DEBUG( 0, __FUNCTION__ "(), Error!\n"); + } + } else { + /* + * This is the last fragment, so time to reassemble! + */ + if ( self->rx_sdu_size <= self->rx_max_sdu_size) { + + /* A little optimizing. Only queue the + * fragment if there is other fragments. Since + * if this is the last and only fragment, + * there is no need to reassemble + */ + if ( !skb_queue_empty( &self->rx_fragments)) { + + DEBUG( 4, __FUNCTION__ + "(), queueing fragment\n"); + skb_queue_tail( &self->rx_fragments, + skb); + + skb = irttp_reassemble_skb( self); + } + self->notify.data_indication( instance, self, + skb); + } else { + DEBUG( 0, __FUNCTION__ + "(), Truncated frame\n"); + self->notify.data_indication( + self->notify.instance, self, skb); + } + self->rx_sdu_size = 0; + } + } + /* Reset lock */ + self->rx_queue_lock = 0; +} + +/* + * Function irttp_flush_queues (self) + * + * Flushes (removes all frames) in transitt-buffer (tx_list) + */ +void irttp_flush_queues( struct tsap_cb *self) +{ + struct sk_buff* skb; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == TTP_TSAP_MAGIC, return;); + + /* Deallocate frames waiting to be sent */ + while (( skb = skb_dequeue( &self->tx_queue)) != NULL) { + dev_kfree_skb( skb); + } + /* Deallocate received frames */ + while (( skb = skb_dequeue( &self->rx_queue)) != NULL) { + dev_kfree_skb( skb); + } + /* Deallocate received fragments */ + while (( skb = skb_dequeue( &self->rx_fragments)) != NULL) { + dev_kfree_skb( skb); + } + +} + +/* + * Function irttp_reasseble (self) + * + * Makes a new (continuous) skb of all the fragments in the fragment + * queue + * + */ +static struct sk_buff *irttp_reassemble_skb( struct tsap_cb *self) +{ + struct sk_buff *skb, *frag; + int n = 0; /* Fragment index */ + int i = 1; /* Fragment nr */ + + ASSERT( self != NULL, return NULL;); + ASSERT( self->magic == TTP_TSAP_MAGIC, return NULL;); + + DEBUG( 4, __FUNCTION__ "(), self->rx_sdu_size=%d\n", + self->rx_sdu_size); + + skb = dev_alloc_skb( self->rx_sdu_size); + if ( !skb) { + DEBUG( 0, __FUNCTION__ "(), unable to allocate skb\n"); + return NULL; + } + + skb_put( skb, self->rx_sdu_size); + + /* + * Copy all fragments to a new buffer + */ + while (( frag = skb_dequeue( &self->rx_fragments)) != NULL) { + DEBUG( 4, __FUNCTION__ "(), copying fragment %d with len=%d\n", + i++, (int) frag->len); + memcpy( skb->data+n, frag->data, frag->len); + n += frag->len; + + dev_kfree_skb( frag); + } + DEBUG( 4, __FUNCTION__ "(), frame len=%d\n", n); + /* Set the new length */ + + DEBUG( 4, __FUNCTION__ "(), rx_sdu_size=%d\n", self->rx_sdu_size); + ASSERT( n <= self->rx_sdu_size, return NULL;); + skb_trim( skb, n); + + self->rx_sdu_size = 0; + + return skb; +} + +/* + * Function irttp_fragment_skb (skb) + * + * Fragments a frame and queues all the fragments for transmission + * + */ +static void irttp_fragment_skb( struct tsap_cb *self, struct sk_buff *skb) +{ + struct sk_buff *frag; + __u8 *frame; + int i = 0; + + DEBUG( 4, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == TTP_TSAP_MAGIC, return;); + ASSERT( skb != NULL, return;); + + /* + * Split frame into a number of segments + */ + while ( skb->len > 0) { + /* + * Instead of making the last segment, we just + * queue what is left of the original skb + */ + if ( skb->len < self->max_seg_size) { + DEBUG( 4, __FUNCTION__ + "(), queuing last segment\n"); + + frame = skb_push( skb, TTP_HEADER); + frame[0] = 0x00; /* Clear more bit */ + skb_queue_tail( &self->tx_queue, skb); + + return; + } + + /* Make new segment */ + frag = dev_alloc_skb( self->max_seg_size+ + TTP_HEADER+LMP_HEADER+ + LAP_HEADER); + if ( frag == NULL) { + DEBUG( 0, __FUNCTION__ + "(), Couldn't allocate skbuff!\n"); + return; + } + + skb_reserve( frag, LMP_HEADER+LAP_HEADER); + + /* + * Copy data from the original skb into this fragment. We + * first insert the TTP header with the more bit set + */ + frame = skb_put( frag, self->max_seg_size+TTP_HEADER); + frame[0] = TTP_MORE; + memcpy( frag->data+1, skb->data, self->max_seg_size); + + /* Hide the copied data from the original skb */ + skb_pull( skb, self->max_seg_size); + + /* Queue segment */ + DEBUG( 4, __FUNCTION__ "(), queuing segment %d with len=%d\n", + i++, (int) frag->len); + + skb_queue_tail( &self->tx_queue, frag); + } +} + +/* + * Function irttp_todo_expired (data) + * + * Todo timer has expired! + * + */ +static void irttp_todo_expired( unsigned long data) +{ + struct tsap_cb *self = ( struct tsap_cb *) data; + + DEBUG( 4, __FUNCTION__ "()\n"); + + /* Check that we still exist */ + if ( !self || self->magic != TTP_TSAP_MAGIC) { + return; + } + + irttp_run_rx_queue( self); + irttp_run_tx_queue( self); + + /* Give avay some credits to peer? */ + if (( skb_queue_empty( &self->tx_queue)) && + ( self->remote_credit < LOW_THRESHOLD) && + ( self->avail_credit > 0)) + { + DEBUG( 4, "irttp_do_events: sending credit!\n"); + irttp_give_credit( self); + } + + /* Rearm! */ + /* irttp_start_todo_timer( self, 50); */ +} + +/* + * Function irttp_start_todo_timer (self, timeout) + * + * Start todo timer. + * + */ +static void irttp_start_todo_timer( struct tsap_cb *self, int timeout) +{ + ASSERT( self != NULL, return;); + ASSERT( self->magic == TTP_TSAP_MAGIC, return;); + + del_timer( &self->todo_timer); + + self->todo_timer.data = (unsigned long) self; + self->todo_timer.function = &irttp_todo_expired; + self->todo_timer.expires = jiffies + timeout; + + add_timer( &self->todo_timer); +} + +#ifdef CONFIG_PROC_FS +/* + * Function irttp_proc_read (buf, start, offset, len, unused) + * + * Give some info to the /proc file system + */ +int irttp_proc_read( char *buf, char **start, off_t offset, int len, + int unused) +{ + struct tsap_cb *self; + unsigned long flags; + int i = 0; + + ASSERT( irttp != NULL, return 0;); + + len = 0; + + save_flags(flags); + cli(); + + self = ( struct tsap_cb *) hashbin_get_first( irttp->tsaps); + while ( self != NULL) { + if ( !self || self->magic != TTP_TSAP_MAGIC) { + DEBUG( 0, "irttp_proc_read: bad ptr self\n"); + return len; + } + + len += sprintf( buf+len, "TSAP %d, ", i++); + len += sprintf( buf+len, "stsap_sel: %02x, ", + self->stsap_sel); + len += sprintf( buf+len, "dtsap_sel: %02x\n", + self->dtsap_sel); + len += sprintf( buf+len, " connected: %s, ", + self->connected? "TRUE":"FALSE"); + len += sprintf( buf+len, "avail credit: %d, ", + self->avail_credit); + len += sprintf( buf+len, "remote credit: %d, ", + self->remote_credit); + len += sprintf( buf+len, "send credit: %d\n", + self->send_credit); + len += sprintf( buf+len, " tx packets: %d, ", + self->stats.tx_packets); + len += sprintf( buf+len, "rx packets: %d, ", + self->stats.rx_packets); + len += sprintf( buf+len, "tx_queue len: %d ", + skb_queue_len( &self->tx_queue)); + len += sprintf( buf+len, "rx_queue len: %d\n", + skb_queue_len( &self->rx_queue)); + len += sprintf( buf+len, " tx_sdu_busy: %s, ", + self->tx_sdu_busy? "TRUE":"FALSE"); + len += sprintf( buf+len, "rx_sdu_busy: %s\n", + self->rx_sdu_busy? "TRUE":"FALSE"); + len += sprintf( buf+len, " max_seg_size: %d, ", + self->max_seg_size); + len += sprintf( buf+len, "tx_max_sdu_size: %d, ", + self->tx_max_sdu_size); + len += sprintf( buf+len, "rx_max_sdu_size: %d\n", + self->rx_max_sdu_size); + + len += sprintf( buf+len, " Used by (%s)\n", + self->notify.name); + + len += sprintf( buf+len, "\n"); + + self = ( struct tsap_cb *) hashbin_get_next( irttp->tsaps); + } + restore_flags(flags); + + return len; +} + +#endif /* PROC_FS */ diff --git a/net/irda/qos.c b/net/irda/qos.c new file mode 100644 index 000000000000..215666aa0768 --- /dev/null +++ b/net/irda/qos.c @@ -0,0 +1,448 @@ +/********************************************************************* + * + * Filename: qos.c + * Version: 0.1 + * Description: IrLAP QoS negotiation + * Status: Experimental. + * Author: Dag Brattli + * Created at: Tue Sep 9 00:00:26 1997 + * Modified at: Sat Dec 12 12:21:42 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include + +#include +#include +#include +#ifdef CONFIG_IRDA_COMPRESSION +#include +#include "../../drivers/net/zlib.h" + +#define CI_BZIP2 27 /* Random pick */ +#endif + +int min_turn_time[] = { 10000, 5000, 1000, 500, 100, 50, 10, 0 }; +int baud_rates[] = { 2400, 9600, 19200, 38400, 57600, 115200, 576000, 1152000, + 4000000 }; +int data_size[] = { 64, 128, 256, 512, 1024, 2048 }; +int add_bofs[] = { 48, 24, 12, 5, 3, 2, 1, 0 }; +int max_turn_time[] = { 500, 250, 100, 50 }; +int link_disc_time[] = { 3, 8, 12, 16, 20, 25, 30, 40 }; + +#ifdef CONFIG_IRDA_COMPRESSION +int compression[] = { CI_BZIP2, CI_DEFLATE, CI_DEFLATE_DRAFT }; +#endif +/* + * Function irda_qos_compute_intersection (qos, new) + * + * Compute the intersection of the old QoS capabilites with new ones + * + */ +void irda_qos_compute_intersection( struct qos_info *qos, struct qos_info *new) +{ + ASSERT( qos != NULL, return;); + ASSERT( new != NULL, return;); + + /* Apply */ + qos->baud_rate.bits &= new->baud_rate.bits; + qos->window_size.bits &= new->window_size.bits; + qos->min_turn_time.bits &= new->min_turn_time.bits; + qos->max_turn_time.bits &= new->max_turn_time.bits; + qos->data_size.bits &= new->data_size.bits; + qos->link_disc_time.bits &= new->link_disc_time.bits; + qos->additional_bofs.bits &= new->additional_bofs.bits; + +#ifdef CONFIG_IRDA_COMPRESSION + qos->compression.bits &= new->compression.bits; +#endif + + irda_qos_bits_to_value( qos); +} + +/* + * Function irda_init_max_qos_capabilies (qos) + * + * The purpose of this function is for layers and drivers to be able to + * set the maximum QoS possible and then "and in" their own limitations + * + */ +void irda_init_max_qos_capabilies( struct qos_info *qos) +{ + /* + * These are the maximum supported values as specified on pages + * 39-43 in IrLAP + */ + + /* LSB is first byte, MSB is second byte */ + qos->baud_rate.bits = 0x01ff; + + qos->window_size.bits = 0x7f; + qos->min_turn_time.bits = 0xff; + qos->max_turn_time.bits = 0x0f; + qos->data_size.bits = 0x3f; + qos->link_disc_time.bits = 0xff; + qos->additional_bofs.bits = 0xff; + +#ifdef CONFIG_IRDA_COMPRESSION + qos->compression.bits = 0x03; +#endif +} + +/* + * Function irlap_negotiate (qos_device, qos_session, skb) + * + * Negotiate QoS values, not really that much negotiation :-) + * We just set the QoS capabilities for the peer station + * + */ +void irda_qos_negotiate( struct qos_info *qos_rx, struct qos_info *qos_tx, + struct sk_buff *skb) +{ + int n=0; +#ifdef CONFIG_IRDA_COMPRESSION + int comp_seen = FALSE; +#endif + __u8 length; + __u8 *frame; + __u8 final_byte; + __u8 code; + __u8 byte; + __u16 final_word; + __u16_host_order word; + + ASSERT( qos_tx != NULL, return;); + ASSERT( qos_rx != NULL, return;); + ASSERT( skb != NULL, return;); + + frame = skb->data; + + while( n < skb->len-2) { + code = frame[n++]; + /* Length */ + length = frame[n++]; + + /* + * Get the value, since baud_rate may need two bytes, we + * Just use word size all the time + */ + switch( length) { + case 1: + byte = frame[n++]; + word.word = byte; /* To make things a little easier */ + break; + case 2: +#ifdef __LITTLE_ENDIAN + word.byte[0] = frame[n++]; + word.byte[1] = frame[n++]; +#else ifdef __BIG_ENDIAN + word.byte[1] = frame[n++]; + word.byte[0] = frame[n++]; +#endif + byte = 0; + break; + default: + DEBUG( 0, __FUNCTION__ "Error\n"); + word.word = byte = 0; + n += length; + + break; + } + + switch( code) { + case PI_BAUD_RATE: + /* + * Stations must agree on baud rate, so calculate + * intersection + */ + DEBUG( 4, "Requested BAUD_RATE: 0x%04x\n", word.word); + final_word = word.word & qos_rx->baud_rate.bits; + DEBUG( 4, "Final BAUD_RATE: 0x%04x\n", final_word); + qos_tx->baud_rate.bits = final_word; + qos_rx->baud_rate.bits = final_word; + break; + case PI_MAX_TURN_TIME: + /* + * Negotiated independently for each station + */ + DEBUG( 4, "MAX_TURN_TIME: %02x\n", byte); + qos_tx->max_turn_time.bits = byte; + break; + case PI_DATA_SIZE: + /* + * Negotiated independently for each station + */ + DEBUG( 4, "DATA_SIZE: %02x\n", byte); + qos_tx->data_size.bits = byte; + break; + case PI_WINDOW_SIZE: + /* + * Negotiated independently for each station + */ + qos_tx->window_size.bits = byte; + break; + case PI_ADD_BOFS: + /* + * Negotiated independently for each station + */ + DEBUG( 4, "ADD_BOFS: %02x\n", byte); + qos_tx->additional_bofs.bits = byte; + break; + case PI_MIN_TURN_TIME: + DEBUG( 4, "MIN_TURN_TIME: %02x\n", byte); + qos_tx->min_turn_time.bits = byte; + break; + case PI_LINK_DISC: + /* + * Stations must agree on link disconnect/threshold + * time. + */ + DEBUG( 4, "LINK_DISC: %02x\n", byte); + + final_byte = byte & qos_rx->link_disc_time.bits; + DEBUG( 4, "Final LINK_DISC: %02x\n", final_byte); + qos_tx->link_disc_time.bits = final_byte; + qos_rx->link_disc_time.bits = final_byte; + break; +#ifdef CONFIG_IRDA_COMPRESSION + case PI_COMPRESSION: + final_byte = byte & qos_rx->compression.bits; + qos_rx->compression.bits = byte; + qos_tx->compression.bits = byte; + comp_seen = TRUE; + break; +#endif + default: + DEBUG( 0, __FUNCTION__ "(), Unknown value\n"); + break; + } + } +#ifdef CONFIG_IRDA_COMPRESSION + if ( !comp_seen) { + DEBUG( 4, __FUNCTION__ "(), Compression not seen!\n"); + qos_tx->compression.bits = 0x00; + qos_rx->compression.bits = 0x00; + } +#endif + /* Convert the negotiated bits to values */ + irda_qos_bits_to_value( qos_tx); + irda_qos_bits_to_value( qos_rx); + + DEBUG( 4, "Setting BAUD_RATE to %d bps.\n", + qos_tx->baud_rate.value); + DEBUG( 4, "Setting DATA_SIZE to %d bytes\n", + qos_tx->data_size.value); + DEBUG( 4, "Setting WINDOW_SIZE to %d\n", + qos_tx->window_size.value); + DEBUG( 4, "Setting XBOFS to %d\n", + qos_tx->additional_bofs.value); + DEBUG( 4, "Setting MAX_TURN_TIME to %d ms.\n", + qos_tx->max_turn_time.value); + DEBUG( 4, "Setting MIN_TURN_TIME to %d usecs.\n", + qos_tx->min_turn_time.value); + DEBUG( 4, "Setting LINK_DISC to %d secs.\n", + qos_tx->link_disc_time.value); +#ifdef CONFIG_IRDA_COMPRESSION + DEBUG( 4, "Setting COMPRESSION to %d\n", + qos_tx->compression.value); +#endif + +} + +/* + * Function irlap_insert_negotiation_params (qos, fp) + * + * Insert QoS negotiaion pararameters into frame + * + */ +int irda_insert_qos_negotiation_params( struct qos_info *qos, __u8 *frame) +{ + int n; + __u16_host_order word; + + ASSERT( qos != NULL, return 0;); + ASSERT( frame != NULL, return 0;); + + n = 0; + + /* Set baud rate */ + if (qos->baud_rate.bits < 256) { + frame[n++] = PI_BAUD_RATE; + frame[n++] = 0x01; /* length 1 */ + frame[n++] = qos->baud_rate.bits; + } else { + frame[n++] = PI_BAUD_RATE; + frame[n++] = 0x02; /* length 2 */ + + /* + * qos->baud_rate.bits is in host byte order, so make sure + * we transmit it in little endian format + */ + word.word = qos->baud_rate.bits; +#ifdef __LITTLE_ENDIAN + frame[n++] = word.byte[0]; /* LSB */ + frame[n++] = word.byte[1]; /* MSB */ +#else ifdef __BIG_ENDIAN + frame[n++] = word.byte[1]; /* LSB */ + frame[n++] = word.byte[0]; /* MSB */ +#endif + } + + /* Set Maximum Turn Around Time */ + frame[n++] = PI_MAX_TURN_TIME; + frame[n++] = 0x01; /* length 1 */ + frame[n++] = qos->max_turn_time.bits; + + /* Set data size */ + frame[n++] = PI_DATA_SIZE; + frame[n++] = 0x01; /* length 1 */ + frame[n++] = qos->data_size.bits; + + /* Set window size */ + frame[n++] = PI_WINDOW_SIZE; + frame[n++] = 0x01; /* length 1 */ + frame[n++] = qos->window_size.bits; + + /* Set additional BOFs */ + frame[n++] = PI_ADD_BOFS; + frame[n++] = 0x01; /* length 1 */ + frame[n++] = qos->additional_bofs.bits; + + /* Set minimum turn around time */ + frame[n++] = PI_MIN_TURN_TIME; + frame[n++] = 0x01; /* length 1 */ + frame[n++] = qos->min_turn_time.bits; + + /* Set Link Disconnect/Threshold Time */ + frame[n++] = PI_LINK_DISC; + frame[n++] = 0x01; /* length 1 */ + frame[n++] = qos->link_disc_time.bits; +#ifdef CONFIG_IRDA_COMPRESSION + /* Set compression bits*/ + if ( qos->compression.bits) { + DEBUG( 4, __FUNCTION__ "(), inserting compresion bits\n"); + frame[n++] = PI_COMPRESSION; + frame[n++] = 0x01; /* length 1 */ + frame[n++] = qos->compression.bits; + } +#endif + return n; +} + +int byte_value( __u8 byte, int *array) +{ + int index; + + ASSERT( array != NULL, return -1;); + + index = msb_index( byte); + return index_value( index, array); +} + + +/* __u8 value_byte( int value, int *array) */ +/* { */ +/* int index; */ +/* __u8 byte; */ + +/* index = value_index( value, array); */ + +/* byte = */ +/* } */ + +/* + * Function msb_index (word) + * + * Returns index to most significant bit (MSB) in word + * + */ +int msb_index ( __u16 word) +{ + __u16 msb = 0x8000; + int index = 15; /* Current MSB */ + + while( msb) { + if ( word & msb) + break; /* Found it! */ + msb >>=1; + index--; + } + + return index; +} + +/* + * Function value_index (value, array) + * + * Returns the index to the value in the specified array + */ +int value_index( int value, int *array) +{ + int i; + + for( i=0;i<8;i++) + if ( array[i] == value) + break; + return i; +} + +/* + * Function index_value (index, array) + * + * Returns value to index in array, easy! + * + */ +int index_value( int index, int *array) +{ + return array[index]; +} + +void irda_qos_bits_to_value( struct qos_info *qos) +{ + int index; + + ASSERT( qos != NULL, return;); + + index = msb_index( qos->baud_rate.bits); + qos->baud_rate.value = baud_rates[index]; + + index = msb_index( qos->data_size.bits); + qos->data_size.value = data_size[index]; + + index = msb_index( qos->window_size.bits); + qos->window_size.value = index+1; + + index = msb_index( qos->min_turn_time.bits); + qos->min_turn_time.value = min_turn_time[index]; + + index = msb_index( qos->max_turn_time.bits); + qos->max_turn_time.value = max_turn_time[index]; + + index = msb_index( qos->link_disc_time.bits); + qos->link_disc_time.value = link_disc_time[index]; + + index = msb_index( qos->additional_bofs.bits); + qos->additional_bofs.value = add_bofs[index]; + +#ifdef CONFIG_IRDA_COMPRESSION + index = msb_index( qos->compression.bits); + if ( index >= 0) + qos->compression.value = compression[index]; + else + qos->compression.value = 0; +#endif +} + diff --git a/net/irda/timer.c b/net/irda/timer.c new file mode 100644 index 000000000000..95c18f13ff7f --- /dev/null +++ b/net/irda/timer.c @@ -0,0 +1,216 @@ +/********************************************************************* + * + * Filename: timer.c + * Version: + * Description: + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sat Aug 16 00:59:29 1997 + * Modified at: Wed Dec 9 01:34:59 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1997 Dag Brattli , All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include + +static void irlap_slot_timer_expired( unsigned long data); +static void irlap_query_timer_expired( unsigned long data); +static void irlap_final_timer_expired( unsigned long data); +static void irlap_wd_timer_expired( unsigned long data); +static void irlap_backoff_timer_expired( unsigned long data); + +static void irda_device_media_busy_expired( unsigned long data); +/* + * Function irda_start_timer (timer, timeout) + * + * Start an IrDA timer + * + */ +void irda_start_timer( struct timer_list *ptimer, int timeout, int data, + TIMER_CALLBACK callback) +{ + del_timer( ptimer); + + ptimer->data = (unsigned long) data; + ptimer->function = callback; + ptimer->expires = jiffies + timeout; + + add_timer( ptimer); +} + +inline void irlap_start_slot_timer( struct irlap_cb *self, int timeout) +{ + irda_start_timer( &self->slot_timer, timeout, (unsigned long) self, + irlap_slot_timer_expired); +} + +inline void irlap_start_query_timer( struct irlap_cb *self, int timeout) +{ + irda_start_timer( &self->query_timer, timeout, (unsigned long) self, + irlap_query_timer_expired); +} + +inline void irlap_start_final_timer( struct irlap_cb *self, int timeout) +{ + irda_start_timer( &self->final_timer, timeout, (unsigned long) self, + irlap_final_timer_expired); +} + +inline void irlap_start_wd_timer( struct irlap_cb *self, int timeout) +{ + irda_start_timer( &self->wd_timer, timeout, (unsigned long) self, + irlap_wd_timer_expired); +} + +inline void irlap_start_backoff_timer( struct irlap_cb *self, int timeout) +{ + irda_start_timer( &self->backoff_timer, timeout, (unsigned long) self, + irlap_backoff_timer_expired); +} + +inline void irda_device_start_mbusy_timer( struct irda_device *self) +{ + irda_start_timer( &self->media_busy_timer, MEDIABUSY_TIMEOUT, + (unsigned long) self, + irda_device_media_busy_expired); + +} + +inline void irlmp_start_watchdog_timer( struct lsap_cb *self, int timeout) +{ + irda_start_timer( &self->watchdog_timer, timeout, (unsigned long) self, + irlmp_watchdog_timer_expired); +} + +inline void irlmp_start_discovery_timer( struct irlmp_cb *self, int timeout) +{ + irda_start_timer( &self->discovery_timer, timeout, + (unsigned long) self, + irlmp_discovery_timer_expired); +} + +/* + * Function irlap_slot_timer_expired (data) + * + * IrLAP slot timer has expired + * + */ +static void irlap_slot_timer_expired( unsigned long data) +{ + struct irlap_cb *self = (struct irlap_cb *) data; + + DEBUG( 4, "Slot timer expired!\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + irlap_do_event( self, SLOT_TIMER_EXPIRED, NULL, NULL); +} + +/* + * Function irlap_query_timer_expired (data) + * + * IrLAP query timer has expired + * + */ +static void irlap_query_timer_expired( unsigned long data) +{ + struct irlap_cb *self = (struct irlap_cb *) data; + + DEBUG( 4, "Query timer expired!\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + irlap_do_event( self, QUERY_TIMER_EXPIRED, NULL, NULL); +} + +/* + * Function irda_final_timer_expired (data) + * + * + * + */ +static void irlap_final_timer_expired( unsigned long data) +{ + struct irlap_cb *self = (struct irlap_cb *) data; + + DEBUG( 4, "Final timer expired!\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + irlap_do_event( self, FINAL_TIMER_EXPIRED, NULL, NULL); +} + +/* + * Function irda_wd_timer_expired (data) + * + * + * + */ +static void irlap_wd_timer_expired( unsigned long data) +{ + struct irlap_cb *self = (struct irlap_cb *) data; + + DEBUG( 4, "WD timer expired!\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + irlap_do_event( self, WD_TIMER_EXPIRED, NULL, NULL); +} + +/* + * Function irda_backoff_timer_expired (data) + * + * + * + */ +static void irlap_backoff_timer_expired( unsigned long data) +{ + struct irlap_cb *self = (struct irlap_cb *) data; + + DEBUG( 0, "Backoff timer expired!\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + irlap_do_event( self, BACKOFF_TIMER_EXPIRED, NULL, NULL); +} + + +/* + * Function irtty_media_busy_expired (data) + * + * + */ +void irda_device_media_busy_expired( unsigned long data) +{ + struct irda_device *self = ( struct irda_device *) data; + + DEBUG( 4, "Mediabusy timer expired!\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == IRDA_DEVICE_MAGIC, return;); + + irda_device_set_media_busy( self, FALSE); +} diff --git a/net/irda/wrapper.c b/net/irda/wrapper.c new file mode 100644 index 000000000000..b1778dba0693 --- /dev/null +++ b/net/irda/wrapper.c @@ -0,0 +1,318 @@ +/********************************************************************* + * + * Filename: wrapper.c + * Version: + * Description: IrDA Wrapper layer + * Status: Experimental. + * Author: Dag Brattli + * Created at: Mon Aug 4 20:40:53 1997 + * Modified at: Wed Dec 9 01:35:53 1998 + * Modified by: Dag Brattli + * + * Copyright (c) 1998 Dag Brattli , + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define MIN_LENGTH 14 + +__inline__ static int stuff_byte( __u8 byte, __u8 *buf); + +/* + * Function async_wrap (skb, *tx_buff) + * + * Makes a new buffer with wrapping and stuffing, should check that + * we don't get tx buffer overflow. + */ +int async_wrap_skb( struct sk_buff *skb, __u8 *tx_buff, int buffsize) +{ + __u8 byte; + int i, n; + int xbofs; + union { + __u16 value; + __u8 bytes[2]; + } fcs; + + + DEBUG( 6, __FUNCTION__ "()\n"); + ASSERT( skb != NULL, return 0;); + + /* Initialize variables */ + fcs.value = INIT_FCS; + n = 0; + + if ( skb->len > 2048) { + DEBUG( 0,"async_xmit: Warning size=%d of sk_buff to big!\n", + (int) skb->len); + + return 0; + } + + /* + * Send XBOF's for required min. turn time and for the negotiated + * additional XBOFS + */ + xbofs = ((struct irlap_skb_cb *)(skb->cb))->xbofs; + for ( i=0; ilen; i++) { + byte = skb->data[i]; + + /* + * Check for the possibility of tx buffer overflow. We use + * bufsize-5 since the maximum number of bytes that can be + * transmitted after this point is 5. + */ + if ( n > buffsize-5) { + printk( KERN_WARNING + "IrDA Wrapper: TX-buffer overflow!\n"); + return n; + } + n+=stuff_byte( byte, tx_buff+n); + fcs.value = IR_FCS( fcs.value, byte); + } + + /* Insert CRC in little endian format (LSB first) */ + fcs.value = ~fcs.value; +#ifdef __LITTLE_ENDIAN + n += stuff_byte( fcs.bytes[0], tx_buff+n); + n += stuff_byte( fcs.bytes[1], tx_buff+n); +#else ifdef __BIG_ENDIAN + n += stuff_byte( fcs.bytes[1], tx_buff+n); + n += stuff_byte( fcs.bytes[0], tx_buff+n); +#endif + tx_buff[n++] = EOF; + + DEBUG( 6, "async_wrap() -->\n"); + + return n; +} + +/* + * Function async_bump (irdev) + * + * Got a frame, make a copy of it, and pass it up the stack! + * + */ +static __inline__ void async_bump( struct irda_device *irdev, __u8 *buf, + int len) +{ + struct sk_buff *skb; + + skb = dev_alloc_skb( len+1); + if (skb == NULL) { + printk( KERN_INFO __FUNCTION__ "() memory squeeze, " + "dropping frame.\n"); + irdev->stats.rx_dropped++; + return; + } + + /* Align to 20 bytes */ + skb_reserve( skb, 1); + + /* For finding out how much time we use to + send a frame */ + do_gettimeofday( &skb->stamp); + + ASSERT( len-2 > 0, return;); + + /* Copy data without CRC */ + skb_put( skb, len-2); + memcpy( skb->data, buf, len-2); + + irdev->rx_buff.len = 0; + /* + * Feed it to IrLAP layer + */ + /* memcpy(skb_put(skb,count), ax->rbuff, count); */ + skb->dev = &irdev->netdev; + skb->mac.raw = skb->data; + skb->protocol = htons(ETH_P_IRDA); + + netif_rx( skb); + irdev->stats.rx_packets++; + + /* irlap_input( skb, skb->dev, NULL); */ +} + +/* + * Function async_unwrap (skb) + * + * Parse and de-stuff frame received from the IR-port + * + */ +void async_unwrap_char( struct irda_device *irdev, __u8 byte) +{ + DEBUG( 6, "async_unwrap()\n"); + + /* State machine for receiving frames */ + switch( irdev->rx_buff.state) { + case OUTSIDE_FRAME: + if ( byte == BOF) { + irdev->rx_buff.state = BEGIN_FRAME; + irdev->rx_buff.in_frame = TRUE; + } else if ( byte == EOF) { + irda_device_set_media_busy( irdev, TRUE); + } + break; + case BEGIN_FRAME: + switch ( byte) { + case BOF: + /* Continue */ + break; + case CE: + /* Stuffed byte */ + irdev->rx_buff.state = LINK_ESCAPE; + break; + case EOF: + /* Abort frame */ + DEBUG( 0, "Frame abort (1)\n"); + irdev->rx_buff.state = OUTSIDE_FRAME; + break; + default: + /* Got first byte of frame */ + if ( irdev->rx_buff.len < irdev->rx_buff.truesize) { + irdev->rx_buff.data[ irdev->rx_buff.len++] = byte; + + irdev->rx_buff.fcs = IR_FCS ( INIT_FCS, byte); + irdev->rx_buff.state = INSIDE_FRAME; + } else + printk( "Rx buffer overflow\n"); + break; + } + break; + case LINK_ESCAPE: + switch ( byte) { + case BOF: + /* New frame? */ + DEBUG( 4, "New frame?\n"); + irdev->rx_buff.state = BEGIN_FRAME; + irdev->rx_buff.len = 0; + irda_device_set_media_busy( irdev, TRUE); + break; + case CE: + DEBUG( 4, "WARNING: State not defined\n"); + break; + case EOF: + /* Abort frame */ + DEBUG( 0, "Abort frame (2)\n"); + irdev->rx_buff.state = OUTSIDE_FRAME; + irdev->rx_buff.len = 0; + break; + default: + /* + * Stuffed char, complement bit 5 of byte + * following CE, IrLAP p.114 + */ + byte ^= IR_TRANS; + if ( irdev->rx_buff.len < irdev->rx_buff.truesize) { + irdev->rx_buff.data[ irdev->rx_buff.len++] = byte; + + irdev->rx_buff.fcs = IR_FCS( irdev->rx_buff.fcs, byte); + irdev->rx_buff.state = INSIDE_FRAME; + } else + printk( "Rx buffer overflow\n"); + break; + } + break; + case INSIDE_FRAME: + switch ( byte) { + case BOF: + /* New frame? */ + DEBUG( 4, "New frame?\n"); + irdev->rx_buff.state = BEGIN_FRAME; + irdev->rx_buff.len = 0; + irda_device_set_media_busy( irdev, TRUE); + break; + case CE: + /* Stuffed char */ + irdev->rx_buff.state = LINK_ESCAPE; + break; + case EOF: + /* End of frame */ + irdev->rx_buff.state = OUTSIDE_FRAME; + irdev->rx_buff.in_frame = FALSE; + + /* + * Test FCS and deliver frame if it's good + */ + if ( irdev->rx_buff.fcs == GOOD_FCS) { + async_bump( irdev, irdev->rx_buff.data, + irdev->rx_buff.len); + } else { + /* + * Wrong CRC, discard frame! + */ + DEBUG( 0, "Received frame has wrong CRC\n"); + irda_device_set_media_busy( irdev, TRUE); + irdev->rx_buff.len = 0; + } + break; + default: + /* Next byte of frame */ + if ( irdev->rx_buff.len < irdev->rx_buff.truesize) { + irdev->rx_buff.data[ irdev->rx_buff.len++] = byte; + + irdev->rx_buff.fcs = IR_FCS( irdev->rx_buff.fcs, byte); + } else + printk( "Rx buffer overflow\n"); + break; + } + break; + } +} + +/* + * Function stuff_byte (byte, buf) + * + * Byte stuff one single byte and put the result in buffer pointed to by + * buf. The buffer must at all times be able to have two bytes inserted. + * + */ +__inline__ static int stuff_byte( __u8 byte, __u8 *buf) +{ + switch ( byte) { + case BOF: + case EOF: + case CE: + /* Insert transparently coded */ + buf[0] = CE; /* Send link escape */ + buf[1] = byte^IR_TRANS; /* Complement bit 5 */ + return 2; + /* break; */ + default: + /* Non-special value, no transparency required */ + buf[0] = byte; + return 1; + /* break; */ + } +} + + diff --git a/net/protocols.c b/net/protocols.c index 6ec830cca3d5..0a15b477349d 100644 --- a/net/protocols.c +++ b/net/protocols.c @@ -57,6 +57,10 @@ extern void packet_proto_init(struct net_proto *pro); #endif #endif +#ifdef CONFIG_IRDA +#include +#endif + #if defined(CONFIG_DECNET) #include #endif @@ -161,5 +165,9 @@ struct net_proto protocols[] = { { "Econet", econet_proto_init }, /* Acorn Econet */ #endif +#ifdef CONFIG_IRDA + { "IrDA", irda_proto_init }, /* IrDA protocols */ +#endif + { NULL, NULL } /* End marker */ }; diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c index 702a55931921..bb155c575c9d 100644 --- a/net/rose/rose_dev.c +++ b/net/rose/rose_dev.c @@ -56,6 +56,7 @@ int rose_rx_ip(struct sk_buff *skb, struct device *dev) { struct net_device_stats *stats = (struct net_device_stats *)dev->priv; +#ifdef CONFIG_INET if (!dev->start) { stats->rx_errors++; return 0; @@ -73,7 +74,9 @@ int rose_rx_ip(struct sk_buff *skb, struct device *dev) skb->pkt_type = PACKET_HOST; ip_rcv(skb, skb->dev, NULL); - +#else + kfree_skb(skb); +#endif return 1; } @@ -101,11 +104,8 @@ static int rose_rebuild_header(struct sk_buff *skb) unsigned char *bp = (unsigned char *)skb->data; struct sk_buff *skbn; +#ifdef CONFIG_INET if (arp_find(bp + 7, skb)) { -#if 0 - /* BUGGGG! If arp_find returned 1, skb does not exist. --ANK*/ - kfree_skb(skb); -#endif return 1; } @@ -126,7 +126,7 @@ static int rose_rebuild_header(struct sk_buff *skb) stats->tx_packets++; stats->tx_bytes += skbn->len; - +#endif return 1; } diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c index 5dda55a351fc..85f177aa7965 100644 --- a/net/wanrouter/wanmain.c +++ b/net/wanrouter/wanmain.c @@ -689,12 +689,10 @@ static int delete_interface (wan_device_t* wandev, char* name, int force) return 0; } -#ifdef MODULE EXPORT_SYMBOL(register_wan_device); EXPORT_SYMBOL(unregister_wan_device); EXPORT_SYMBOL(wanrouter_encapsulate); EXPORT_SYMBOL(wanrouter_type_trans); -#endif /* * End diff --git a/scripts/checkhelp.pl b/scripts/checkhelp.pl new file mode 100644 index 000000000000..e765233259e2 --- /dev/null +++ b/scripts/checkhelp.pl @@ -0,0 +1,30 @@ +#!/usr/bin/perl +# checkhelp.pl - finds configuration options that have no +# corresponding section in the help file +# +# made by Meelis Roos (mroos@tartu.cyber.ee) + +# read the help file +@options=split /\n/, `grep '^CONFIG' Documentation/Configure.help`; +die "Can't read Documentation/Configure.help\n" if $#options == -1; + +#read all the files +foreach $file (@ARGV) +{ + open (FILE, $file) || die "Can't open $file: $!\n"; + while () { + # repeat until no CONFIG_* are left + while (/^\s*(bool|tristate|dep_tristate|string|int|hex).*' *(.*)'.*(CONFIG_\w*)/) { + $what=$3; + $name=$2; + s/$3//; + @found = grep (/$what$/, @options); + if ($#found == -1) { + next if $nohelp{$what}; + print "$name\n$what\n No help for $what\n\n"; + $nohelp{$what}=1; + } + } + } + close (FILE); +} -- 2.39.5